statementproof

How to check whether a bank statement PDF conversion is actually correct

Converting a bank statement PDF to CSV is easy. Knowing whether the conversion is right is the part nobody talks about — and it’s the part that costs money.

This page describes a check you can run in about ten seconds, by hand, in Excel, on the output of any converter. You don’t need a tool for it and you don’t need this project. It’s just arithmetic that most people don’t know is available.

See the tool’s actual output — verified, silently-failing, and batch runs, copied verbatim from real runs: statementproof demo


The failure that actually hurts

A converter that crashes is harmless — you notice immediately and try something else.

The expensive failure is silent. A debit gets read as a credit. A decimal shifts. A page header lands in the data as a transaction. The CSV looks perfectly clean, imports without complaint, and reconciles to nothing three weeks later, in someone else’s books, with your name on the work.

The three most common silent failures, in order:

  1. Column shift. Debit and credit columns are distinguished only by where the number sits on the page. Extracting text flattens that away, so a debit can land in the credit column with no visible sign of error.
  2. Sign loss. A minus sign, a trailing -, or parentheses for negatives may not survive extraction. (42.50) becomes 42.50.
  3. Junk rows. Page headers, “continued” markers, and running totals get picked up as transactions.

None of these look like errors in the output. They look like data.

The check: a bank statement carries its own checksum

Almost every statement prints an opening balance and a closing balance. Many also print a running balance after each transaction. Those numbers are a checksum on your extraction, and they’re free.

Check 1 — the total (works on every statement)

opening balance + sum of all extracted amounts = closing balance

In Excel, with your amounts in column D:

=B1 + SUM(D:D) - B2

…where B1 is the opening balance and B2 the closing. If that doesn’t return exactly zero, at least one row is wrong. Credits positive, debits negative.

This catches sign errors, decimal shifts, dropped rows, and duplicated rows. It will not catch two errors that happen to cancel, or a junk row with a 0.00 amount.

Check 2 — the chain (only if a running balance is printed, and much better)

Check 1 tells you that something is wrong. Check 2 tells you which row.

For every row, this must hold:

balance[n] = balance[n-1] + amount[n]

In Excel, with balances in column E and amounts in D, put this in F2 and fill down:

=ROUND(E2 - E1 - D2, 2)

Every cell should be zero. The first non-zero cell is your error. Not “somewhere in the file” — that row.

Seed the first row from the opening balance rather than from the row itself, or a broken first row silently becomes your baseline.

Use integers, not floats

If you script this, compare in whole cents as integers. 0.1 + 0.2 != 0.3 in floating point, and an accounting tool that raises false alarms on rounding noise gets switched off within a week.

What passing the check does and does not mean

Does mean: the extracted transactions are arithmetically consistent with the statement’s own balances. Sign errors, misread digits, dropped rows and duplicated rows are ruled out.

Does not mean the conversion is correct. Errors that don’t disturb the arithmetic are invisible to it:

The honest claim is “arithmetically consistent,” not “correct.” Treat any tool that claims more than that — including this one — with suspicion.

What to do when the check fails

  1. Find the first non-zero row from check 2. That’s where the converter broke, not where you’ll notice the symptom.
  2. Open the PDF to that row. Usually the cause is visible immediately: the amount is in the wrong column, or a minus sign vanished.
  3. Look at the rows around it. Column-shift errors cluster; a converter that misreads one row’s columns usually misreads its neighbours.
  4. Check for a 0.00 row. That’s a header or a total that got captured as a transaction. It passes check 1 and breaks nothing arithmetically — which is exactly why it survives.

Doing it automatically

statementproof runs both checks on the output and names the failing row:

row 14 — running balance does not follow: 534.66 +37.07 should give 571.73,
statement shows 497.59 (off by -74.14)

It’s free, MIT licensed, and runs entirely on your machine — no networking library is imported anywhere in the package, and a test parses every module and fails the build if one ever is. Text-layer PDFs only; scans are detected and refused rather than guessed at.

But the check matters more than the tool. Run it with whatever you already use.


Other free, local options worth trying first: Excel’s built-in Data → Get Data → From PDF handles simple layouts and you already have it. Tabula is free and open source, though you draw the extraction regions yourself. Paid services like DocuClipper and QuickBankConvert are faster on a large pile, if uploading a client’s statement is acceptable for that engagement.