Part 6 ended with a list of things this converter had not proven. Item 3 on that list was the scanned-PDF path on Windows: OCR worked on Linux (tesseract 5.3.4, 6/6 rows on a clean synthetic scan), but tesseract is not bundled in the installer or in either exe, and the steps for installing it on Windows had never been tested. This post closes that item — with the two failures it took to get there, because those failures are part of the result.
What the test does
A new CI job, ocr-windows, runs on every change to the converter: install tesseract with Chocolatey, add Simplified Chinese language data, install the Python dependencies, regenerate the fixtures, and run test_ocr.py against the same scanned fixture part 3 used — a 300 dpi image-only PDF rendered from fixture D, six rows of ground truth. The job passes only if all six rows come back with every field correct.
The install steps, as run
Chocolatey installed tesseract 5.5.3.20260724 at C:\Program Files\Tesseract-OCR. The Chocolatey package did not include Chinese language data, so the job downloads chi_sim.traineddata from tesseract-ocr/tessdata_fast into the tessdata directory and then asserts that tesseract --list-langs actually lists chi_sim before proceeding. That assertion matters: without it, a silent missing-language failure would look like a parser failure later.
The result
The run passed in 1 minute 24 seconds (run 42299707395): tesseract with chi_sim+eng --psm 6 recognised the scanned fixture, and the row parser extracted 6/6 rows with all fields correct (100%). The Windows install steps are now tested, not assumed.
The two failures before it
The first run failed in the OCR step, and the second run failed in the same step at a new position. Both were bugs in test_ocr.py itself — bugs that only exist on Windows, which is exactly why the job runs on Windows:
- The script called
subprocess.runwithtext=Trueand no encoding. On Windows that decodes with cp1252, which cannot decode tesseract's UTF-8 Chinese output —UnicodeDecodeErroron byte 0x90 — andproc.stdoutcame back asNone, crashing the row comparison with anAttributeError. Fixed by decoding explicitly withencoding="utf-8-sig", errors="replace". - With decoding fixed,
print(ocr_text)crashed instead: the Windows console stdout is also cp1252 and cannot encode Chinese characters. Fixed by reconfiguring stdout to UTF-8 at the start ofmain().
Neither failure was an OCR quality problem. A script that passes on Linux and crashes on Windows is the kind of thing a Windows CI job is for, and it found two of them in two runs.
What this does not prove
The same limits from part 6 still apply to the scanned path. The fixture is still one clean synthetic scan page, not a real bank scan with skew, noise, low resolution, or stamps. Tesseract is still a separate install — the exe and the installer do not bundle it, and the installer does not install it. Nobody has yet run the installer on a real Windows machine and double-clicked the installed shortcuts. Encrypted PDFs, mixed image-and-text PDFs, and heavily degraded scans are still untested. The next post in this series will be evidence closing one of those items, not a repeat of this one.
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/.


