A scanned statement is not data until something reads it.
The statement arrives as a photograph of a page. Somewhere in it are three hundred transactions that a business needs in a spreadsheet — and typing them out is how a Saturday disappears. This pipeline reads the scan and hands back the workbook.
Document AI · Excel automation · SheetFlow internal build
System pipeline
Ingestinput/ folder
ReadOCR engine
StructureTransaction parsing
ExcelTransactions
Internal build — no public deployment.
The pipeline runs locally against real bank statements, and its output contains genuine account activity. It is described here and deliberately not screenshotted — the sample workbook holds real financial data belonging to a real person.
parser.py — 1,222 lines
The full pipeline: dependency bootstrap, PDF rendering, OCR, transaction extraction, categorisation and workbook generation.
output/bank_statement_analysis.xlsx
A real generated workbook, verified on 2026-08-08: four sheets — Transactions (264 rows × 9 columns), Clean Ledger, Expense Categories and Financial Summary.
input/ — two scanned statement PDFs
The actual inputs the sample output was produced from: 1.5 MB and 551 KB scans, each a photographed multi-page statement rather than a digital export.
section handoff
The problem
What the build had to solve.
01
The source is a photograph, not a text PDF, so nothing can be extracted without optical character recognition.
02
A transaction line that OCR mangles becomes a wrong number in a financial record, which is worse than a missing one.
03
The output has to land somewhere the business already works, which is a spreadsheet — not a dashboard nobody opens.
section handoff
Architecture
How the work moves through it.
Ingest
Read
Structure
Excel
1
Ingest
Scanned statement PDFs are dropped into an input folder; the pipeline picks up whatever is there with no per-file configuration.
input/ folder
Multi-file batch
Page rendering
2
Read
Each page is read twice — by direct text extraction where the PDF has a text layer, and by OCR where it does not — so digital and photographed statements both work.
OCR engine
Text-layer extraction
Page images
3
Structure
Recognised lines are parsed into dated transactions with debit, credit and running balance, each tagged with the file it came from.
Transaction parsing
Debit / credit split
Balance tracking
Source attribution
4
Publish to Excel
The result is written as a four-sheet workbook: every transaction, a cleaned ledger, spend grouped by category, and a summary.
Transactions
Clean Ledger
Expense Categories
Financial Summary
section handoff
The build
What it is made of.
Every row was read off the source, not from a project brief. Line counts, versions and limits are the ones in the files listed above.
Language
Python — 1,222 lines, single-file pipeline
OCR
PaddleOCR over rendered pages, with pdfplumber for statements carrying a text layer
Categorisation
Anthropic API for transaction categorisation
Output
Excel workbook via openpyxl — four sheets, one file
Verified output
264 transactions across two scanned statements, written on 2026-03-11
Setup
Missing dependencies are detected and installed on first run
section handoff
Engineering decisions
The choices, and why they went that way.
Excel is the destination, not a dashboard
The people who need this already live in spreadsheets — that is where their accountant wants the file and where they will filter, annotate and total it. A web dashboard would be a better demo and a worse tool: it would mean exporting to a spreadsheet anyway, with one more step in between.
Verify: The pipeline writes a single `.xlsx` with four sheets and no other output surface; the sample workbook opens with 264 rows in the Transactions sheet.
Two extraction paths, because statements arrive both ways
Some statements are digital exports with a real text layer; most that arrive from a small business are photographs taken on a phone. Running text extraction where it works and OCR where it does not means one pipeline handles both, instead of failing on whichever kind it was not built for.
Verify: Both pdfplumber and an OCR engine are required dependencies, and each transaction row records the source file it was read from.
The sample output is described here and not shown
The verified workbook is genuine, which is exactly why it cannot be a screenshot. It contains real counterparty names, real UPI identifiers and real balances. Publishing a picture of it to prove the pipeline works would leak somebody’s finances to prove a point about engineering.
Verify: This case study cites row and column counts and the sheet names rather than any transaction content, and no image of the workbook appears anywhere on this site.
The run installs what it needs
This is operated by the business owner, not by a developer with a working Python toolchain. Detecting missing packages and installing them on first run removes the single most common reason a tool like this gets abandoned before it is ever used.
Verify: The pipeline checks each required import at startup and installs any that are missing before continuing.
section handoff
Business outcome
What we can prove, and what we cannot.
Not publicly disclosed.
No business outcome has been measured against a stated method and confirmed with this client, so no figure is published. We would rather show you the system and let you judge it than print a number nobody verified.
section handoff
Questions
About this project.
What is the Bank Statement Parser?
A SheetFlow internal build: a Python pipeline that reads scanned bank statement PDFs using OCR, extracts every transaction with its date, debit, credit and running balance, categorises spending, and writes a four-sheet Excel workbook. A verified sample run produced 264 transactions from two scanned statements.
Why does it output Excel rather than a dashboard?
Because that is where the work continues. The workbook goes to an accountant, gets filtered and annotated, and totals get checked by hand. A dashboard would have required exporting to a spreadsheet as an extra step, so the spreadsheet is the product.
What business results has the Bank Statement Parser produced?
Not publicly disclosed. It is an internal build with no client engagement behind it, and no time-saving or accuracy figure has been measured against a stated method, so none is claimed.