DEV Community

alapha888
alapha888

Posted on

Bank statement PDFs to CSV, part 8: encrypted, stamped, and line-less — three edge cases I finally tested

Part 6 ended with a list of things this converter had not proven. One item on that list was three PDF shapes I had never tested: encrypted PDFs, image PDFs that still have a text layer, and statements with no table ruling lines at all. This post closes that item. Two of the three went fine. The third found a real limitation, and that is the most useful part.

The test setup is the same as the rest of the series: synthetic fixtures, invented payees and amounts, ground truth written down before the converter runs. The new fixtures are E1, E2 and E3 in the repository, all built from the same 12-row statement as fixture A, so the results compare directly.

E1: the encrypted PDF

I took fixture A and re-saved it with AES-256 encryption (user password test123 — a synthetic fixture, nothing secret in it). Before this round, the converter's answer was bad: pdfplumber raised a PdfminerException with an empty message, wrapping pdfminer's PDFPasswordIncorrect, and the CLI printed a bare traceback. A user would have learned nothing from that output.

The fix is small and now tested: extract_transactions translates that specific failure into a PasswordProtectedError with a plain message — the PDF is password-protected, decrypt it first, then convert — and the CLI exits with code 2, no traceback, and writes no CSV. The GUI already turned every failure into a human message; its technical-reason line is no longer empty for this case either. The converter still cannot open an encrypted PDF. What changed is that it now says so clearly instead of crashing obscurely.

E2: a stamp image on the same page

Real statements often carry a raster stamp or logo on the same page as the transaction table. I embedded a small raster stamp image ("business seal") in the top-right corner of page 1, leaving the text layer untouched, and ran the same 12 rows through.

Result: 12/12 rows, every field correct, identical to fixture A. An embedded image does not disturb table extraction, because pdfplumber reads the text layer and the image is simply not text. This was the expected outcome; it is worth having as a test rather than an assumption, since the converter will meet stamped statements in the real world.

E3: no ruling lines at all — the honest failure

This is the interesting one. I drew the same 12 rows at the same column positions, with the same header, but no table lines whatsoever. Without lines, pdfplumber finds no table, and the converter falls back to its line parser, which reads each row as a line of text: date, description, then the numbers.

Result: 12/12 rows found, 12/12 dates correct — but only 2 of the 12 rows are fully correct. The 10 spending rows came back with debit and credit swapped.

The reason is structural, not a typo. In this fixture the debit and credit are separate columns with unsigned amounts — 328.50 in the debit column, no minus sign. The line parser sees two trailing numbers (amount, balance) and, with no sign to go on, assigns the amount to income. The table path never has this problem, because the header tells it which column is which; the line fallback has no column information at all.

I locked this in as a characterisation test — it asserts the measured behaviour, 2 fully correct out of 12, with the 10 swaps — so the limitation is on the record and any future fix has to update the test deliberately. The fix would be to give the fallback column positions, for example by reading word x-coordinates instead of plain text lines. That is real work and out of scope for presale v1, so for now the honest statement is: statements without ruling lines extract, but spending and income may be swapped. The two income rows were correct, which is consistent with the mechanism, not luck.

What this does not prove

The three shapes were tested on synthetic fixtures, not real bank PDFs — real statements with the same shapes are still untested, as are real bank samples in general. The Windows installer still has no real-machine install check, and there is still no auto-update. Those items stay on the list from part 6.

Links: the converter repository is at https://github.com/alapha888/bank-statement-presale, and the presale page is at https://alapha888.github.io/bank-statement-presale/.

Top comments (1)

Collapse
 
gautamtalksdev profile image
Gautam K •

Writing the ground truth down before the converter runs is what makes this series trustworthy. On the shape that found the real limitation: does the converter refuse when it can't find columns, or guess? A clear refusal with the page number is worth more than a CSV that looks right.