SheetStatement
Accounting software

Convert a Bank Statement PDF to OFX: What Works

What an OFX file is, when your software needs one, and practical ways to turn a bank statement PDF into OFX or a format that imports just as cleanly.

SheetStatement Team11 min read

On this page

TL;DR OFX (Open Financial Exchange) is a structured text format banks use to send transactions to finance software. A PDF statement can't be renamed to OFX; you have to extract the transactions first, then either build an OFX file from them or use another format your software accepts. Most apps that read OFX also read CSV, and QuickBooks prefers its own OFX-based QBO format. Whatever route you take, check that the imported balance matches the statement and that each transaction has a unique ID so re-imports don't create duplicates.

People usually go looking for "PDF to OFX" for one of three reasons. Their bank only offers PDF statements for older months. Their accounting or budgeting app imports OFX more reliably than CSV. Or they're catching up on bookkeeping and want something that behaves like a bank feed rather than a spreadsheet.

This guide explains what's actually inside an OFX file, how it differs from QBO, QFX and CSV, and the realistic ways to get from a PDF to something your software will import cleanly, including building a valid OFX file from Excel if you need to.

What OFX is

OFX stands for Open Financial Exchange, an open specification for exchanging financial data between institutions and software. In practice, when online banking offers a download labeled something like "OFX" or "Microsoft Money", you get a text file with a header and a set of tagged records.

There are two broad generations:

  • OFX 1.x uses an SGML-style syntax. Tags don't always need closing tags, and the file starts with a plain-text header block such as OFXHEADER:100.
  • OFX 2.x is XML. Every tag closes, and the file starts with an XML declaration.

Most software that imports OFX handles both, though older tools are more comfortable with 1.x.

A bank statement in OFX contains, roughly:

  • Account information: bank identifier, account number or ID, account type and currency.
  • A transaction list with a start and end date.
  • One record per transaction, with type, posted date, amount, a unique transaction ID and a name or memo.
  • A ledger balance and the date it applies to.

A single transaction looks something like this:

<STMTTRN>
<TRNTYPE>DEBIT
<DTPOSTED>20260412
<TRNAMT>-64.37
<FITID>20260412-0003
<NAME>SUPERMARKET
</STMTTRN>

The field that matters most is FITID, the financial institution's transaction ID. Importing software uses it to decide whether a transaction is new or one it has already seen. If two different transactions share a FITID, one may be silently dropped. If the same transaction gets a different FITID each time you import, you'll get duplicates.

OFX, QFX, QBO and CSV compared

Format What it is Typical use
OFX Open standard, structured Many accounting and budgeting apps, Xero, GnuCash and others
QFX OFX with Quicken-specific fields Quicken's Web Connect imports
QBO OFX with QuickBooks-specific fields QuickBooks Online and Desktop Web Connect
CSV Plain table of rows and columns Almost everything, with a column mapping step

The OFX family carries the account, balance and transaction IDs, so imports behave like a bank feed. CSV is simpler and more universal but usually needs you to map columns, and duplicate detection depends on the software comparing dates, amounts and descriptions.

Our article on QBO vs IIF vs CSV goes deeper on the QuickBooks side, and the bank statement CSV format guide covers what makes a CSV import cleanly.

Do you actually need OFX?

Before building an OFX file, check whether your software takes something easier.

  • QuickBooks Online and Desktop: use QBO or CSV. A plain OFX file may not import into QuickBooks without the QuickBooks-specific fields. See converting a bank statement PDF to QBO.
  • Xero: accepts OFX and also CSV in its own layout. See the Xero CSV import format.
  • Quicken: prefers QFX through Web Connect; some versions accept other formats. See importing into Quicken.
  • GnuCash: imports OFX and CSV. See importing into GnuCash.
  • Other apps: check the import screen. If CSV is offered with a column mapping step, it's often the quickest route.

OFX is the better choice when:

  • Your software's CSV import is limited or doesn't detect duplicates well.
  • You want the account and balance information carried with the data.
  • You're importing many months and want repeatable transaction IDs.

Step 1: Extract the transactions from the PDF

A PDF is a page layout, not data. Whatever the final format, the first step is the same: get one row per transaction with a date, description and signed amount.

Copy and paste works on short statements but tends to merge columns and lose signs.

Power Query can detect tables in PDFs and is worth trying on clean layouts. See our Power Query guide.

A statement converter is the most reliable on long or multi-section statements. SheetStatement extracts transactions, adds the year from the statement period, checks the balance, and exports Excel, CSV, QuickBooks QBO, QuickBooks Desktop IIF or Xero CSV. It doesn't currently export a file labeled OFX, so if your software strictly needs OFX, use the CSV export as the source for the steps below. The free plan covers 3 pages a month; Starter ($9), Pro ($19) and Business ($39) monthly plans cover more.

You want this table at the end of step 1:

Date Description Amount
2026-04-01 SALARY ACME LTD 2850.00
2026-04-02 SUPERMARKET -64.37
2026-04-03 TRANSFER TO SAVINGS -300.00

Step 2: Check the balance before you convert again

Converting an incomplete table to OFX just produces an incomplete OFX file. Check it first:

=ROUND(OpeningBalance + SUM(C:C) - ClosingBalance, 2)

It should be 0. If it isn't, a row is missing or duplicated, a sign is wrong, or a fee section was skipped. Fix it now. The free balance checker helps if you'd rather not build the formula.

Step 3: Build the OFX file

You have three options.

Option A: use the destination software's CSV import

If the software accepts CSV, this is usually best. Map Date, Description and Amount, import one month, and reconcile. You skip OFX entirely.

Option B: use a CSV-to-OFX tool

There are utilities, both free and paid, that turn a CSV into OFX or QFX. If you use one, check how it creates FITIDs. Ideally they should be stable, meaning the same transaction gets the same ID each time you convert, so a re-import is recognized as a duplicate.

Option C: build it in Excel

If you're comfortable with formulas, you can generate a valid OFX 1.x file from a spreadsheet. This gives you full control over the transaction IDs.

1. Prepare columns. Next to Date, Description and Amount, add:

  • DT: =TEXT(A2, "yyyymmdd")
  • Type: =IF(C2<0, "DEBIT", "CREDIT")
  • FITID: a stable ID such as =D2 & "-" & TEXT(COUNTIFS($A$2:A2, A2), "000"), which gives the date plus a sequence number within that date. As long as you never reorder transactions within a day, it stays stable.
  • Name: a cleaned description, at most 32 characters to be safe, and with &, < and > replaced, since those characters break the markup: =LEFT(SUBSTITUTE(SUBSTITUTE(SUBSTITUTE(B2,"&","and"),"<",""),">",""),32)

2. Build each transaction line. In another column:

="<STMTTRN><TRNTYPE>"&E2&"<DTPOSTED>"&D2&"<TRNAMT>"&TEXT(C2,"0.00")&"<FITID>"&F2&"<NAME>"&G2&"</STMTTRN>"

3. Wrap with a header and footer. The file needs a header block, sign-on response, account details, the transaction list and a ledger balance. A minimal structure:

OFXHEADER:100
DATA:OFXSGML
VERSION:102
SECURITY:NONE
ENCODING:USASCII
CHARSET:1252
COMPRESSION:NONE
OLDFILEUID:NONE
NEWFILEUID:NONE

<OFX>
<SIGNONMSGSRSV1><SONRS><STATUS><CODE>0<SEVERITY>INFO</STATUS>
<DTSERVER>20260430<LANGUAGE>ENG</SONRS></SIGNONMSGSRSV1>
<BANKMSGSRSV1><STMTTRNRS><TRNUID>1<STATUS><CODE>0<SEVERITY>INFO</STATUS>
<STMTRS><CURDEF>USD
<BANKACCTFROM><BANKID>000000000<ACCTID>1234<ACCTTYPE>CHECKING</BANKACCTFROM>
<BANKTRANLIST><DTSTART>20260401<DTEND>20260430
... transaction lines here ...
</BANKTRANLIST>
<LEDGERBAL><BALAMT>3047.81<DTASOF>20260430</LEDGERBAL>
</STMTRS></STMTTRNRS></BANKMSGSRSV1>
</OFX>

Use placeholder or last-four values for the bank and account IDs rather than your full account number; most software only uses them to recognize which account the file belongs to, and keeping them consistent across months is what matters. Set CURDEF to your currency and ACCTTYPE to CHECKING, SAVINGS or another valid type. Credit cards use a slightly different block (CREDITCARDMSGSRSV1 and CCACCTFROM), so if you're converting a card statement, look up that variant in your software's documentation or use CSV.

4. Save as plain text. Copy the header, the transaction lines and the footer into a plain text editor and save with a .ofx extension using a basic encoding. Don't save from Excel as CSV, which adds quotes and commas.

5. Test with one month. Import it, confirm the transaction count and the balance, then import it again to make sure the software recognizes the duplicates. If the second import adds new rows, your FITIDs aren't stable.

Step 4: Reconcile after importing

After every import, compare the account balance in your software with the statement's closing balance for that date. If they match and the transaction count is right, you're done. If not:

  • More transactions than expected: duplicates from overlapping imports or unstable IDs.
  • Fewer than expected: transactions dropped because two shared a FITID.
  • Balance off by a round amount: an amount was misread; compare with the PDF.

Our guides to finding reconciliation discrepancies and fixing duplicates in QuickBooks cover the cleanup.

A worked example

A freelancer uses budgeting software that imports OFX far more reliably than CSV. Their bank only offers PDF statements for anything older than a few months, and they need the last eight months in the software.

  1. Extract. Each PDF is converted to CSV and checked against its opening and closing balances. All eight balance.
  2. Combine. The eight CSVs are stacked into one sheet, sorted by date.
  3. Build columns. DT, Type, FITID, Name and the transaction line formula are added. FITIDs are date plus sequence.
  4. Generate. One OFX file per month is built from the header, the month's lines and a footer with that month's closing balance.
  5. Test. The first month imports with the right count and balance. Importing it a second time adds nothing, so the IDs are stable.
  6. Import the rest in order, checking the balance after each.

The result behaves exactly like a bank download, and if a month ever needs re-importing, the software recognizes what it already has.

Working with several accounts and many months

Catch-up projects often involve more than one account: a checking account, a savings account and a card, each with a year of statements. A little structure keeps the OFX route manageable.

One workbook per account. Keep each account's transactions in its own workbook or sheet, with its own fixed BANKID, ACCTID and account type. Mixing accounts in one file is the quickest way to import transactions into the wrong place.

One OFX file per statement period. Matching files to statements makes reconciliation simple: after each import, the software's balance should equal that statement's closing balance. If something goes wrong, you know exactly which file to look at.

A control sheet. List each file with the statement period, the opening and closing balance from the PDF, the number of transactions, and a column you tick after importing and reconciling:

Account Period Opening Closing Rows Imported Reconciled
Checking 2026-01 2,104.55 2,611.20 48 ✔ ✔
Checking 2026-02 2,611.20 1,998.03 52 ✔ ✔
Savings 2026-01 5,000.00 5,206.10 3 ✔

Each month's opening balance should equal the previous month's closing balance. If it doesn't, a statement is missing or a period overlaps. Our guide to an opening balance that doesn't match the statement covers the fixes.

Consistent FITIDs across rebuilds. If you rebuild a month's file after fixing an error, keep the same ID scheme. A transaction that was already imported should get the same FITID so the software skips it, and only the corrected or missing rows are added.

Privacy and file handling

OFX files are plain text, so anyone who opens one can read every transaction. Treat them like the statements themselves:

  • Store them in the same protected folder as the PDFs, not on a shared desktop.
  • Don't include full account numbers when a consistent short identifier will do.
  • Delete working copies you no longer need once the import is reconciled, and keep the PDFs as the official record.
  • Before uploading statements to any service, read its security page or privacy policy so you know how files are processed and stored.

Common OFX import errors

"Invalid file" or "unable to read". Often a header problem, an unescaped & in a description, or the file saved with the wrong encoding. Open it in a text editor and check the first lines and any descriptions with special characters.

Transactions import to the wrong account. The BANKID and ACCTID values differ from what the software has on file for that account. Keep them consistent across every file for the same account.

Dates are off by a day. Some software interprets dates with time zones. Using date-only values (yyyymmdd) usually avoids this.

Signs are reversed. In OFX, debits are negative amounts. If everything comes in backwards, check the sign of TRNAMT.

Credit card files won't import. Card statements need the credit card message block, not the bank one.

Try it

Upload a statement to SheetStatement, confirm the balance check, and download CSV for an OFX build, or QBO and Xero formats if that's what your software prefers. The free plan includes 3 pages a month.

FAQ

Can I just rename a PDF to .ofx?

No. A PDF is a page layout. The transactions have to be extracted into structured data first, then written in OFX format.

What's the difference between OFX and QBO?

QBO is based on OFX but includes QuickBooks-specific fields. QuickBooks generally expects QBO; other apps generally expect OFX. A plain OFX file may not import into QuickBooks.

Does SheetStatement export OFX?

It exports Excel, CSV, QuickBooks QBO, QuickBooks Desktop IIF, Xero CSV and JSON. If your software strictly needs OFX, use the CSV export as the source for an OFX build, or check whether the software also accepts CSV.

What is a FITID and why does it matter?

It's the unique ID for each transaction. Importing software uses it to detect duplicates. Stable, unique FITIDs mean re-imports don't create duplicate rows and different transactions are never merged.

Is OFX better than CSV?

OFX carries account, balance and ID information and behaves like a bank feed. CSV is simpler and accepted almost everywhere. If your software's CSV import works well, it's usually the easier option.

Can I convert a credit card statement to OFX?

Yes, but card files use a different message block from bank accounts. If that's unfamiliar, CSV is often the simpler route for cards.

Should I include my full account number in the file?

It isn't usually necessary. Use a consistent identifier, such as the last four digits, so the software recognizes the account each time.

Can I open an OFX file in Excel?

You can open it as text, but it won't appear as a tidy table. If you want to review the data in Excel, use the CSV you built it from, or import the OFX into your finance software and export from there.

How do I avoid duplicates when importing several months?

Import one month at a time, keep FITIDs stable, and reconcile to the closing balance after each import.

Related articles

Convert your first statement free

3 pages a month on the free plan. No credit card.