Skip to content

Currency Converter

Transform

Convert a numeric column from one currency to another using exchange rates fetched from the public frankfurter.dev API (which serves European Central Bank reference rates). The result is appended as a new column. Use it to normalize multi-currency revenue, restate historical figures, or unify mixed-currency exports for downstream aggregation.

Currency Converter is a streaming transform that wraps an external rate fetch. Before the first row is processed, the executor calls https://api.frankfurter.dev/v1/{date}?from={from}&to={to} once (in manual mode) and caches the result in IndexedDB via the shared fetch cache (apps/web/src/infrastructure/persistence/fetch-cache-store.ts). Per-row work is then pure arithmetic: numericValue * rate.

Cache TTLs are tuned to the kind of rate. Live rates (rateDate="", the API’s latest endpoint) cache for 1 hour; historical rates pinned to a specific past date cache for 30 days because the ECB never revises them. If the cache has a fresh entry, no network request is made — the transform runs entirely from local cache.

In column mode, the transform reads the rate date from a per-row column instead of a single configured date. Each distinct date triggers one fetch (cached for the run plus IndexedDB), so a stream with N distinct dates incurs N requests on a cold cache.

If the row’s amount cell is non-numeric (or empty), the output cell is null and the row continues. If the API itself fails (network error, timeout after 10 seconds, unknown currency code), the transform throws and the flow stops with an error.

Input: One tabular data connection. The amount column should hold numeric values (or numeric strings). Output: The same columns plus a new column named outputColumn (defaults to {sourceColumn}_{targetCurrency}).

OptionTypeDefaultDescription
sourceColumnstring(required)Column holding the numeric amount to convert. Required.
sourceCurrency3-letter code"USD"ISO 4217 source currency (e.g. USD, EUR, GBP).
targetCurrency3-letter code"EUR"ISO 4217 target currency.
outputColumnstring""Name of the new column. When left blank, auto-generated as {sourceColumn}_{targetCurrency}.
rateDateMode"manual" | "column""manual"manual uses one rate for the whole stream; column reads the rate date from a per-row column.
rateDateYYYY-MM-DD or """"(Manual mode) Specific past date for historical rates. Empty string fetches the latest rate.
rateDateColumnstring""(Column mode) Column containing per-row dates in YYYY-MM-DD format.

The examples below render with a fixed illustrative rate. The actual rate at run time depends on whatever frankfurter.dev returns for the requested date — refresh the preview to see live numbers.

You imported a sales export in US dollars and want a parallel EUR column for an EU finance team. Assume 1 USD = 0.92 EUR for this example.

Before:

customerrevenue_usd
Acme Corp1000
Beta Inc2500
Gamma LLC750

Configuration: source column: revenue_usd, source currency: USD, target currency: EUR, output column: revenue_eur, rate date mode: manual, rate date: "" (latest).

After:

customerrevenue_usdrevenue_eur
Acme Corp1000920
Beta Inc25002300
Gamma LLC750690

Restate a 2024 figure at a historical rate

Section titled “Restate a 2024 figure at a historical rate”

You want to convert a year-end 2024 USD figure using the December 31, 2024 rate, not today’s. Assume 1 USD = 0.96 EUR on that date for this example.

Before:

accountbalance_usd
Cash50000
Receivables12500

Configuration: source column: balance_usd, source currency: USD, target currency: EUR, output column: balance_eur, rate date mode: manual, rate date: 2024-12-31.

After:

accountbalance_usdbalance_eur
Cash5000048000
Receivables1250012000

Per-row date for transaction-time conversion

Section titled “Per-row date for transaction-time conversion”

Each transaction was booked in GBP on a different day. You want each one converted at its own day’s rate.

Before:

txn_idamount_gbptxn_date
T-11002024-06-15
T-22502024-09-30
T-3802025-01-10

Configuration: source column: amount_gbp, source currency: GBP, target currency: EUR, output column: amount_eur, rate date mode: column, rate date column: txn_date.

After (rates depend on the dates above; values shown are illustrative):

txn_idamount_gbptxn_dateamount_eur
T-11002024-06-15118.30
T-22502024-09-30296.50
T-3802025-01-1095.80
  • This is the only transform in FileBender that contacts an external service. Rates are fetched from https://api.frankfurter.dev and your row data never leaves the browser, but the request itself is observable to your network. Disconnect your network and the transform will fail with a clear error after the 10-second timeout. See apps/web/src/transforms/currency-convert/logic.ts:38-78.
  • Caching is dual-layered: per-run map plus IndexedDB. Within a single run the executor memoizes rates in a Map so a column-mode stream with 10,000 rows but 30 distinct dates makes 30 fetches at most. Across runs, the IndexedDB fetch cache persists rates for 1 hour (latest) or 30 days (historical). Clearing the cache requires deleting the FileBender IndexedDB data in browser settings. See apps/web/src/transforms/currency-convert/logic.ts:18-19, apps/web/src/transforms/currency-convert/logic.ts:144-168, and apps/web/src/infrastructure/persistence/fetch-cache-store.ts.
  • Non-numeric amount cells become null, not errors. A cell that fails parseFloat (e.g. "n/a", empty string) writes null to the output column and the row continues to flow. API failures, on the other hand, throw and stop the whole stream — there is no row-level retry. See apps/web/src/transforms/currency-convert/logic.ts:118-129.
  • Formula — apply a custom rate or fee on top of the converted column.
  • Change Type — coerce a string amount column to number before conversion if the source is text.
  • Group By — sum converted amounts per period or per customer once the column is in a single currency.