Torna al Blog

Come ottenere tassi di cambio in tempo reale in Power BI: Power Query, DAX e la trappola dell'aggiornamento

V
Vlado Grigirov
September 01, 2026
Currency API Exchange Rates Power BI Power Query DAX Tutorial Finexly

Ottenere tassi di cambio in tempo reale in Power BI è uno di quei compiti che sembrano finiti molto prima di esserlo davvero. Incolli un URL di API in Recupera dati → Web, compare una tabella di tassi, la misura del fatturato convertito si accende e pubblichi. Due giorni dopo l'aggiornamento del set di dati fallisce nel servizio Power BI con un messaggio su un'origine dati dinamica — oppure riesce e converte silenziosamente ogni transazione storica al tasso di oggi.

Questa guida copre l'intero percorso: una query M di Power Query che restituisce una tabella di tassi pulita, il pattern RelativePath che la mantiene aggiornabile nel servizio, una funzione di tassi storici per convertire alla data della transazione, una misura DAX per una valuta di reporting dinamica e il calcolo del numero di richieste che decide se la tua pianificazione di aggiornamento entra in un piano API.

Tutte le query che seguono sono scritte sulle strutture di risposta documentate dell'API Finexly. Se hai già letto la nostra guida sui tassi di cambio in tempo reale in Excel, il codice M ti sembrerà familiare — ma Power BI aggiunge un livello di aggiornamento lato servizio che Excel non ha, ed è lì che la maggior parte di questi progetti si rompe.

I tre modi per portare i tassi in Power BI

ApproccioSi aggiorna nel servizio?Chiave API al sicuro?Tassi storiciIdeale per
Connettore Web, URL incollato nella finestraSpesso no — l'URL diventa di solito un'origine dati dinamica❌ La chiave finisce nell'URLNoUna proof of concept da cinque minuti
Query vuota con Web.Contents + RelativePath✅ Sì✅ Tramite intestazione✅ SìQuasi ogni modello reale
Dataflow (o pipeline Fabric) che alimenta una tabella di tassi✅ Sì, e disaccoppiato dall'aggiornamento del report✅ Tramite intestazione✅ SìPiù report, molte righe
La seconda riga è la risposta predefinita. Alla terza si passa quando più di un report ha bisogno degli stessi tassi. La prima è quella che insegnano tutti i tutorial fatti di screenshot, ed è il motivo per cui tanti modelli valutari falliscono al primo aggiornamento pianificato.

Metodo 1: una tabella di tassi in tempo reale con Power Query

Apri Trasforma dati → Nuova origine → Query vuota → Editor avanzato e incolla questo. Restituisce una riga per coppia di valute con marca temporale UTC di prelievo.

let
    ApiKey  = "YOUR_API_KEY",
    Base    = "USD",
    Symbols = "EUR,GBP,JPY,CHF,AUD,CAD,SEK,NZD",

    Source = Json.Document(
        Web.Contents(
            "https://api.finexly.com",
            [
                RelativePath = "v1/latest",
                Query        = [ base = Base, symbols = Symbols ],
                Headers      = [ #"Authorization" = "Bearer " & ApiKey ]
            ]
        )
    ),

    Rates    = Record.ToTable( Source[rates] ),
    Renamed  = Table.RenameColumns( Rates, {{"Name", "Quote"}, {"Value", "Rate"}} ),
    AddBase  = Table.AddColumn( Renamed, "Base", each Base, type text ),
    AddStamp = Table.AddColumn( AddBase, "RetrievedUTC", each DateTimeZone.UtcNow(), type datetimezone ),
    Typed    = Table.TransformColumnTypes(
                   AddStamp,
                   {{"Quote", type text}, {"Rate", type number}}
               )
in
    Typed

L'endpoint che chiama si presenta così da riga di comando — vale la pena eseguirlo una volta per vedere la struttura che stai analizzando:

curl "https://api.finexly.com/v1/latest?base=USD&symbols=EUR,GBP,JPY" \
  -H "Authorization: Bearer YOUR_API_KEY"
{
  "success": true,
  "base": "USD",
  "date": "2026-09-01",
  "rates": { "EUR": "…", "GBP": "…", "JPY": "…" }
}

Perché RelativePath e Query non sono opzionali

È il punto più importante dell'articolo, quindi merita un titolo tutto suo.

Se costruisci l'URL come un'unica stringa concatenata — "https://api.finexly.com/v1/latest?base=" & Base — Power Query non può determinare la destinazione finché la query non viene eseguita. Microsoft classifica questo caso come origine dati dinamica, e le origini dinamiche non vengono aggiornate nel servizio Power BI, per ragioni di sicurezza e privacy. Il report si aggiornerà perfettamente sul tuo portatile e fallirà nel momento in cui verrà pianificato.

Passare il percorso in RelativePath e i parametri in Query è l'eccezione documentata. Power BI può allora risolvere un unico URL di base statico — https://api.finexly.com — per i controlli di credenziali e privacy, mentre le parti variabili restano variabili. Ne discendono tre regole:

  1. L'URL di base deve essere una stringa letterale. Nessun parametro, nessuna concatenazione, nessun &.
  2. RelativePath dev'essere il percorso fisso dell'endpoint. "v1/latest", non "v1/latest?base=USD".
  3. Non concatenare mai dentro Query. Passa un record di coppie nome/valore e lascia che sia Power Query a fare la codifica URL. Provvederà anche a fare l'escape dei caratteri che altrimenti romperebbero la richiesta.

Impostare le credenziali

Alla prima esecuzione Power BI chiede come autenticarsi su https://api.finexly.com. Scegli Anonimo. Sembra sbagliato, ma è corretto: la chiave API viaggia nell'intestazione Authorization che hai fornito nel codice M, non attraverso l'archivio credenziali di Power BI. Selezionare API Web o Di base porterebbe Power BI ad aggiungere una propria intestazione e la richiesta verrebbe rifiutata.

Imposta il livello di privacy su Pubblico o Organizzazione in modo coerente su tutte le origini. Livelli di privacy incompatibili sono la seconda causa più frequente di un aggiornamento che funziona in Desktop e fallisce nel servizio — Power BI preferisce bloccare la query piuttosto che rischiare di far filtrare i dati di un'origine nella richiesta di un'altra.

Una precisazione onesta: la chiave ora è memorizzata in chiaro dentro la query. Chiunque apra il .pbix può leggerla. Per tutto ciò che viene condiviso oltre la tua macchina, promuovi la chiave a parametro di Power Query e tieni la versione valorizzata in un dataflow di proprietà di un account di servizio, così gli autori dei report usano la tabella dei tassi senza vedere mai la credenziale.

Metodo 2: tassi storici per la conversione alla data della transazione

Una tabella di tassi in tempo reale risponde a "quanto vale EUR/USD adesso". Non risponde a "quanto è stato il fatturato di gennaio in USD", e usarla per questo è l'errore più costoso dell'intero argomento — ripresentare i numeri del trimestre scorso perché il modello li ha riconvertiti a un nuovo tasso è esattamente ciò che i revisori cercano. Se il tuo report alimenta qualcosa che dovrai difendere in seguito, leggi anche la nostra guida su tassi di cambio e adempimenti fiscali.

Serve una tabella di tassi indicizzata per data. Questa funzione M incapsula l'endpoint delle serie storiche e restituisce una riga per data e per valuta:

let
    FxHistory = (base as text, symbols as text, startDate as date, endDate as date) as table =>
        let
            ApiKey = "YOUR_API_KEY",

            Source = Json.Document(
                Web.Contents(
                    "https://api.finexly.com",
                    [
                        RelativePath = "v1/timeseries",
                        Query = [
                            base       = base,
                            symbols    = symbols,
                            start_date = Date.ToText( startDate, [Format = "yyyy-MM-dd", Culture = "en-US"] ),
                            end_date   = Date.ToText( endDate,   [Format = "yyyy-MM-dd", Culture = "en-US"] )
                        ],
                        Headers = [ #"Authorization" = "Bearer " & ApiKey ]
                    ]
                )
            ),

            Days      = Table.RenameColumns( Record.ToTable( Source[rates] ), {{"Name", "RateDate"}} ),
            Expanded  = Table.ExpandRecordColumn( Days, "Value", Record.FieldNames( Days{0}[Value] ) ),
            Unpivoted = Table.UnpivotOtherColumns( Expanded, {"RateDate"}, "Quote", "Rate" ),
            AsDate    = Table.TransformColumns(
                            Unpivoted,
                            {{"RateDate", each Date.FromText( _, [Format = "yyyy-MM-dd", Culture = "en-US"] ), type date}}
                        ),
            AddBase   = Table.AddColumn( AsDate, "Base", each base, type text ),
            Typed     = Table.TransformColumnTypes( AddBase, {{"Quote", type text}, {"Rate", type number}} )
        in
            Typed
in
    FxHistory

Due dettagli lì dentro fanno un lavoro concreto:

  • Culture = "en-US" sia su Date.ToText sia su Date.FromText. Senza, una macchina impostata su tedesco o francese invia 01.09.2026 come start_date e l'API rifiuta — o peggio, l'aggiornamento di un collega produce una tabella di forma diversa dalla tua. Le impostazioni locali sono la variabile invisibile di ogni progetto Power Query che attraversi più di un paese.
  • Table.UnpivotOtherColumns. L'API restituisce le date come chiavi di record, con un record annidato di valute. Trasformare nel formato lungo RateDate / Base / Quote / Rate dà una tabella che si unisce pulita a una dimensione data e che non va rimodellata ogni volta che aggiungi una valuta.

Invocala una volta per caricamento: FxHistory( "USD", "EUR,GBP,JPY", #date(2026,1,1), Date.From( DateTime.LocalNow() ) ).

Poiché i tassi di una data passata non cambiano mai, questa tabella è il caso da manuale per l'aggiornamento incrementale: partiziona su RateDate, aggiorna gli ultimi 7 giorni, archivia il resto. Il tempo di aggiornamento smette di crescere con lo storico — e il conteggio delle richieste pure.

Non chiamare l'API una volta per riga

Il pattern che uccide questi modelli è invocare una funzione di tasso come colonna personalizzata sulla tabella dei fatti. Diecimila transazioni significano diecimila richieste HTTP per aggiornamento, un aggiornamento da quaranta minuti e un conto di quota che arriva prima di pranzo.

Fai i conti prima di costruire. Power BI Pro consente 8 aggiornamenti pianificati per set di dati al giorno; Premium Per User e la capacità Fabric ne consentono 48. Una singola chiamata /v1/latest che copre tutte le valute necessarie, aggiornata al massimo di Pro, costa 8 richieste al giorno — circa 240 al mese, comodamente dentro un piano gratuito da 1.000. La stessa pianificazione con una funzione per riga non ha limite. Anche al massimo PPU di 48 aggiornamenti, una chiamata consolidata si attesta su circa 1.440 richieste al mese, che è un piccolo piano a pagamento anziché una catastrofe riga per riga. I nostri piani tariffari elencano le soglie se devi dimensionare con precisione.

Quando più di un report ha bisogno dei tassi, sposta la query in un dataflow. Il dataflow chiama l'API con la propria pianificazione e materializza il risultato; ogni set di dati a valle legge dallo storage invece di bussare di nuovo all'API. Cinque report sullo stesso dataflow producono un solo gruppo di richieste, non cinque.

Convertire gli importi: merge in Power Query o misura DAX

Ci sono due posti legittimi dove applicare la conversione, e rispondono a domande diverse.

Opzione A: unire in Power Query

Se la valuta di reporting è fissa — tutto è riportato in USD, punto — fai il join al caricamento.

  1. Carica la tabella dei fatti in Power Query.
  2. Merge query con la tabella dei tassi, abbinando su codice valuta e data. Tieni premuto Ctrl e seleziona le colonne nello stesso ordine in entrambe le tabelle.
  3. Espandi solo la colonna Rate e impostala su Numero decimale fisso.
  4. Seleziona Amount e Rate, poi Aggiungi colonna → Standard → Moltiplica.
  5. Disabilita il caricamento della tabella dei tassi se nient'altro la referenzia.

È veloce, si materializza una volta e nessun filtro dei dati può alterarlo. Quest'ultimo punto è il compromesso.

Opzione B: una misura DAX con valuta di reporting selezionabile

Se gli utenti devono commutare l'intero report tra USD, EUR e GBP, la conversione deve avvenire in fase di query. Aggiungi una tabella scollegata Reporting Currency con una colonna di codici ISO, mettila in un filtro dei dati e scrivi:

Revenue (Reporting Currency) =
VAR ReportingCurrency = SELECTEDVALUE( 'Reporting Currency'[Code], "USD" )
RETURN
SUMX (
    'Sales',
    VAR TxCurrency = 'Sales'[CurrencyCode]
    VAR TxDate     = 'Sales'[OrderDate]
    VAR Rate =
        CALCULATE (
            MAX ( 'FX Rates'[Rate] ),
            REMOVEFILTERS ( 'FX Rates' ),
            'FX Rates'[Base]     = TxCurrency,
            'FX Rates'[Quote]    = ReportingCurrency,
            'FX Rates'[RateDate] = TxDate
        )
    RETURN 'Sales'[Amount] * Rate
)

Tre cose da notare:

  • Le righe VAR sono portanti. Catturare TxCurrency e TxDate in variabili prima di CALCULATE le àncora alla riga corrente di SUMX. Referenziare le colonne direttamente negli argomenti di filtro invita un bug di transizione di contesto che produce totali plausibili ma sbagliati.
  • REMOVEFILTERS( 'FX Rates' ) impedisce a qualsiasi filtro in ingresso sulla tabella dei tassi di restringere la ricerca.
  • Un tasso mancante restituisce BLANK(), e Amount * BLANK() è BLANK(). È il comportamento che vuoi. Una riga che ripiega in silenzio sull'importo non convertito è una riga che gonfia il totale di quanto vale il tasso di cambio.

La trappola delle relazioni

Non creare una relazione fisica dalla tabella dei fatti a quella dei tassi sul solo codice valuta. In una tabella indicizzata per data il codice valuta non è univoco, quindi Power BI propone una relazione molti-a-molti — e molti-a-molti con filtro bidirezionale moltiplicherà allegramente righe e fatturato. Usa il merge composito in Power Query, oppure tieni la tabella dei tassi scollegata e cerca i tassi in DAX come sopra.

Cinque errori che producono numeri sbagliati senza dare errore

  1. URL concatenati. Si aggiorna in Desktop, fallisce nel servizio con "Questo set di dati include un'origine dati dinamica". Si risolve con RelativePath e Query.
  2. Coppie invertite. base=USD&symbols=EUR restituisce USD→EUR. Se la tabella dei fatti contiene importi in EUR ti serve il reciproco. Verifica a mano una coppia nota prima di fidarti di un qualsiasi totale. Il nostro riferimento ISO 4217 aiuta se non sei sicuro di quale codice vada da quale parte.
  3. Il tasso di oggi su righe storiche. Il numero cambia a ogni aggiornamento e nessuno se ne accorge finché qualcuno non confronta due export dello stesso report.
  4. Date e decimali in formato locale. Una virgola decimale trasforma 1,0842 in testo, Table.TransformColumnTypes restituisce un errore che il modello tratta come vuoto e le righe coinvolte spariscono dai totali.
  5. Arrotondare nel passaggio sbagliato. Arrotonda una sola volta, in presentazione, dopo la moltiplicazione. Arrotondare il tasso a quattro decimali prima di moltiplicare un importo a sette cifre introduce una discrepanza visibile rispetto al sistema contabile.

Domande frequenti

Power BI può aggiornare i tassi di cambio automaticamente?

Sì. Un set di dati pubblicato può essere pianificato fino a 8 aggiornamenti al giorno su Power BI Pro e 48 al giorno su Premium Per User o capacità Fabric. L'endpoint XMLA di Premium consente a strumenti esterni di attivare aggiornamenti oltre quei limiti. La query dei tassi non richiede nulla di speciale, se non essere costruita con Web.Contents + RelativePath così che il servizio la accetti.

Come passo una chiave API in modo sicuro in Power BI?

Mettila nel record Headers di Web.Contents come Authorization = "Bearer " & ApiKey e scegli l'autenticazione Anonima quando Power BI lo chiede. Così la chiave resta fuori dall'URL, dai log del proxy e dalla cronologia del browser. Non la cripta però dentro il .pbix — per i modelli condivisi, tieni la chiave in un dataflow di proprietà di un account di servizio e lascia che i report leggano la tabella materializzata.

Perché il set di dati dice "Questo set di dati include un'origine dati dinamica"?

Perché l'URL viene assemblato nel codice, quindi Power BI non può verificare la destinazione prima dell'esecuzione della query e si rifiuta di aggiornarlo nel servizio. Ricostruisci la chiamata con un URL di base statico più le opzioni RelativePath e Query, ripubblica e reinserisci la credenziale per l'URL di base.

Come converto gli importi usando il tasso alla data della transazione?

Carica una tabella di tassi indicizzata per data da un endpoint di serie storiche, poi abbina su valuta e data — con un merge composito in Power Query oppure con una ricerca CALCULATE dentro SUMX come mostrato sopra. Non fare mai il join sulla sola valuta: prenderesti in silenzio la riga di tasso che capita prima nell'ordinamento.

Esiste un'API valutaria gratuita che funzioni con Power BI?

Sì. Il livello gratuito dell'API valutaria gratuita di Finexly include 1.000 richieste al mese senza carta di credito, che coprono con ampio margine un set di dati con licenza Pro aggiornato otto volte al giorno. Se stai valutando fornitori su limiti di aggiornamento, profondità storica o copertura valutaria, confronta le API valutarie prima di cablarne una in un modello che manterrai per anni.


Inizia con Finexly

Pronto a portare tassi di cambio in tempo reale nei tuoi report Power BI? Ottieni la tua chiave API Finexly gratuita — senza carta di credito. Parti con 1.000 richieste gratuite al mese e cresci quando serve. Tassi in tempo reale e storici per oltre 170 valute, da una sola API REST che si comporta allo stesso modo che tu la chiami da Power Query, Python o un servizio di pagamento.

Vlado Grigirov

Senior Currency Markets Analyst & Financial Strategist

Vlado Grigirov is a senior currency markets analyst and financial strategist with over 14 years of experience in foreign exchange markets, cross-border finance, and currency risk management. He has wo...

View full profile →

Condividi questo articolo