Statement checks
The file imported. Did the transactions survive?
Compare the original transaction file with a fresh export of what arrived. Counts, inflows and outflows need to agree for each account and currency, but equal totals alone don't prove the transactions survived. Match the individual rows too, keeping every repeated occurrence.
By AnyStatement
Published , 8 min read
An import confirmation tells you the app accepted something. It doesn't tell you whether every date, amount and description reached the right account. Comparing the two files can reveal differences, but it can't tell you which file is correct. You still need the bank's records to resolve discrepancies, and your bookkeeper or accountant to settle their treatment in the books. A file comparison neither reconciles the whole ledger nor authenticates a statement.
Keep the file you sent and export what arrived
If both CSVs are ready, the free CSV before and after compare reports counts and signed sums. You'll also need to check separate inflow and outflow totals, as shown below; you can do the whole review manually if you prefer. Start with the bank's native export when it covers the required period. There's no need to convert a PDF if you already have the transaction data you need.
Keep an untouched copy at each boundary: bank export or PDF, extracted CSV, import file, then destination export. Comparing adjacent stages helps you locate a difference. If the extracted CSV already lost a transaction, comparing it with the destination can't reveal that earlier loss. That's why PDF-only sources need a separate row-by-row review against their printed transactions.
Both sides need to cover the same account, currency and inclusive date range for the comparison to mean anything. Record the export filters, whether pending rows are included, and whether the destination shows individual bank transactions or bookkeeping splits. Include payee and memo fields where available, but if the destination can't export a field, mark it “not compared,” not “preserved.”
For a backfill into an existing account, the destination export also contains transactions that were there before you started. Keep a pre-import snapshot so you can distinguish existing rows from newly added ones. The historical import and duplicate guide explains how to set that boundary before adding another batch.
Agree what each column means before matching
Account labels can be misleading: “Current account” and “Checking” may mean the same account, but two accounts can also share a nickname or final digits. Map them explicitly and keep currencies separate, even within one account. An unidentified account or currency is an unresolved input, not permission to pool the rows.
Dates only make a useful comparison when they mean the same thing, such as posted date to posted date. Parse them using each file's stated convention, and convert amounts to exact decimal values with one agreed sign convention. Here, money entering the account is positive and money leaving is negative. Don't round away a difference or guess whether 03/04 means March 4 or April 3. If either file is unclear, work through the date and number-format checks first.
Removing references, punctuation or whole words to get more matches can hide the loss you're trying to find, so retain the original text beside any comparison value. If you deliberately ignore case or whitespace, record that choice and review the original text differences separately. Invalid dates and amounts belong on an exception list, never in the totals as zero.
Match rows as a multiset, not a list of unique purchases
Repeated rows need to stay in the comparison. A multiset keeps the number of occurrences of each row, using account, currency, parsed date, exact signed amount and description text as the key here. Row order doesn't matter, but each matching occurrence on one side consumes only one occurrence on the other.
Suppose the original contains two identical cafe purchases and the export contains one. A unique-row lookup says the cafe purchase exists in both files, while a multiset comparison reports one matched occurrence and one before-only occurrence. It can't identify which physical purchase survived without further evidence, but it does preserve the discrepancy. Deduplicating either input before this check would lose that distinction.
Start with transaction count, positive-amount total, outflow magnitude and signed net for each account/currency group, then separate exact matches, before-only rows and after-only rows. Those last two labels tell you which file a row appears in, not what went wrong. A before-only row might have changed, been skipped, or fallen outside an export filter.
A row match covers only the fields in the key, so category, reference, memo and split structure need separate checks if they matter to the migration. Matching a displayed description can't establish that a longer source memo survived somewhere else.
A fictional pair with equal checking totals and wrong rows
These synthetic CSVs represent the same intended January period. They use ISO dates and decimal points, with identical account labels on both sides. All names and transactions are fictional. To follow the example, copy the first block as the before file and the second as the after file, using exact description matching.
Before: nine transactions.
Account,Currency,Date,Description,Amount
Checking,USD,2026-01-02,Salary,1000.00
Checking,USD,2026-01-03,Rent,-600.00
Checking,USD,2026-01-05,Cafe,-12.50
Checking,USD,2026-01-05,Cafe,-12.50
Checking,USD,2026-01-06,Client refund REF0042,25.00
Checking,USD,2026-01-07,Adjustment,-25.00
Checking,USD,2026-01-08,Store,-80.00
Savings,USD,2026-01-09,Interest,1.10
Travel,EUR,2026-01-10,Train,-40.00After: eight transactions.
Account,Currency,Date,Description,Amount
Checking,USD,2026-01-02,Salary,1000.00
Checking,USD,2026-01-04,Rent,-600.00
Checking,USD,2026-01-05,Cafe,-12.50
Checking,USD,2026-01-05,Parking,-12.50
Checking,USD,2026-01-06,Refund,25.00
Checking,USD,2026-01-07,Adjustment,-24.00
Checking,USD,2026-01-08,Store,-81.00
Savings,USD,2026-01-09,Interest,1.01| Account / measure | Currency | Before | After |
|---|---|---|---|
| Checking count | USD | 7 | 7 |
| Checking inflows | USD | 1,025.00 | 1,025.00 |
| Checking outflows | USD | 730.00 | 730.00 |
| Checking net | USD | 295.00 | 295.00 |
| Savings count | USD | 1 | 1 |
| Savings inflows / net | USD | 1.10 | 1.01 |
| Savings outflows | USD | 0.00 | 0.00 |
| Travel count | EUR | 1 | 0 |
| Travel inflows | EUR | 0.00 | No rows |
| Travel outflows / net | EUR | 40.00 / -40.00 | No rows |
Checking passes every summary comparison, including the separate inflow and outflow totals. Yet the rent date moved, the refund description lost its reference, one cafe occurrence is absent, and a parking row appeared. The adjustment changed from -25.00 to -24.00 while the store changed from -80.00 to -81.00. Their +1.00 and -1.00 differences cancel exactly.
Savings is 0.09 USD lower in the after file, while Travel has no after rows at all. Its source net is -40.00 EUR; the absence doesn't mean the account had no activity. The export scope needs checking before you blame the import. There's no combined USD-plus-EUR total because adding different currencies would obscure the comparison.
Exact multiset matching finds only two unchanged occurrences: Salary and one Cafe row. That leaves seven before-only and six after-only occurrences across the files to review. It doesn't mean seven proven deletions and six proven new purchases. Several are plausible changed-row pairs, as the next step shows.
A likely changed row is still a candidate
Once the exact occurrences are accounted for, the remaining rows may suggest changes. Keep that search within the same account and currency. Equal date and amount with different text suggests a description change; if the amount and text agree but the dates differ, it suggests a date change. Equal date and text with different amounts suggests an amount change. None of those combinations establishes identity on its own.
| Candidate | Observed difference | What remains to check |
|---|---|---|
| Rent | January 3 becomes January 4 | Which date the source records |
| Refund | Client refund REF0042 becomes Refund | Whether the reference survives elsewhere |
| Adjustment | Amount increases by 1.00 USD | Source amount and mapped column |
| Store | Amount decreases by 1.00 USD | Source amount and mapped column |
| Cafe / Parking | Same date and -12.50 USD | Missing occurrence plus added row, or changed text? |
| Interest | 1.10 becomes 1.01 USD | Source decimal digits |
Cafe and Parking are deliberately ambiguous. The files alone can't tell you whether a cafe description changed or a cafe disappeared while a different transaction was added. Even a single remaining candidate isn't proof, and if several rows qualify, you need to retain the candidate group rather than pair the first rows you happen to see.
A stable transaction reference can help when both exports retain the same identifier, alongside the statement or destination detail view. Don't invent IDs from row numbers. For a split transaction, check the parent/child relationship too: one bank row becoming several category rows isn't automatically missing data, but those rows are no longer a one-to-one comparison.
The reports behind this workflow are questions, not defect rates
Historical Actual Budget threads describe payee and notes mapping mismatches (opened July 28, 2024), categories missing during migration (opened September 13, 2024), and file/feed overlap with differing payee data (opened July 16, 2025). The mapping issue was closed as completed on August 6, 2024. In the category discussion, a project member explained that categories needed to exist in that budget first, and the reporter accepted the explanation. The overlap issue was automatically closed after a request for more information went unanswered. These threads record specific historical reports and responses, not current defect rates or evidence that every import loses data.
Another October 12, 2024 OFX amount report, filed for version 24.10.1, includes the reporter's confirmation that a test-build fix worked. It is a historical, version-specific example, not a current warning against OFX. The dated reports are reasons to compare your own files rather than infer an accuracy rate from someone else's experience.
The current Actual import guide, checked on October 18, 2026, documents duplicate matching using an ID, then nearby dates, equal amounts and similar payees. That is different from the strict comparison described here. A personal Mint-to-Simplifi migration repository also describes exporting before and after linking an account to inspect added rows. We have not run that script or adopted its deletion advice; the useful idea is preserving both snapshots.
Finish with an exception record, not a green total
The free CSV comparison tool lets you inspect the two files you supply; it doesn't connect to your bank or accounting app. Keep the account/currency summaries and unresolved source rows with your review notes so you have a record of what still needs attention. The difference report is a review aid, not a corrected import file or permission to delete anything.
Each exception needs both file row references, what changed, the source evidence and your decision. After an approved correction, re-export and compare again to check the result. Agreement still isn't enough if both files descend from the same incomplete extraction: you need to check the original statement. Read why a balanced statement can still be wrong before treating a zero difference as completion.
If the starting point is PDF-only, first request a native bank export or transcribe a short period with source references. For a larger file, AnyStatement converts statement PDFs into reviewable Excel or CSV. That's a separate upload-based conversion, not the local comparison. Its extracted rows need checking against the PDF before you use them as the before file.
What we checked
We reopened the four linked issue threads, the current Actual import guide and the migration repository on October 18, 2026. Issue opening and closure dates are identified above; the guide and repository showed no editorial update date. We parsed both fictional CSVs and recomputed every group count, inflow, outflow, net and amount difference with Python Decimal. A separate occurrence count checked the exact multiset result. We did not import these files into a live accounting app, run the migration script or test a real bank export. The example demonstrates file differences, not a measured converter failure rate.