Three percent looks completely normal
A supplier's price list was three percent too high. That is exactly the kind of error nobody catches.
A Dutch sun-shading installer
Suppliers send their prices as two-hundred-page PDFs and spreadsheets. Every quote meant looking a number up by hand. We built the pipeline that reads them - and, more importantly, the controls that refuse to publish a price it is not sure about.
The challenge
Eighteen suppliers, each with their own format. Some send a PDF built for a printer rather than a computer. Some send a spreadsheet with the real numbers on a hidden tab. Nobody agrees on whether a price includes VAT, or whether a measurement is in centimetres or millimetres.
The staff response was rational: look it up by hand, every time. That is slow, and it quietly guarantees that some quotes go out wrong.
The obvious project is "extract the prices automatically". The obvious project is also the dangerous one. An extraction that is ninety-nine percent right produces a price list that looks completely finished and is wrong in ways nobody will notice until a customer is invoiced.
What we did
Read the file, not the format
A pipeline that detects price grids inside PDFs and spreadsheets, reads the axes around them, and keeps the raw text alongside every number it extracts.
Make the assumptions explicit
Every file must declare its VAT basis and its unit before anything is read from it. These are the two assumptions that silently corrupt a whole catalogue, so they became required fields rather than defaults.
Stage everything for review
No import publishes directly. Each run is staged, a person confirms which price table belongs to which product, and only reviewed work becomes a live price.
Fix the readers that return nothing
One supplier's file produced zero readable numbers - the PDF carried no character map and had named its digits internally as words. Recovering it meant working at the glyph level rather than accepting the empty result.
Verify against something external
Recovered numbers were checked against colour codes that can be confirmed independently of the file they came from, so the verification does not depend on the same broken source.
How it works
Grid detection
Price tables are found structurally rather than by position, so a supplier re-laying-out their catalogue does not break the reader.
Declared units and VAT
Unit and VAT basis are per-file required declarations. A file that does not declare them cannot be imported at all.
Staged runs
An import produces a staging run, not a price change. Publication is a separate, reviewed step.
Re-readable by design
A file can be re-read after a reader improves, and the new result replaces the old one without destroying review work already done.
The VAT catch
One supplier's list was priced including VAT while the system assumed excluding. Every published price would have been twenty-one percent high. The declaration requirement caught it before publication.
The hidden-sheet catch
Eleven of thirty-four linked price blocks in one workbook resolved to a hidden duplicate sheet holding older numbers - about three percent off. Three percent does not look like a bug. It looks like a price.
Human in the loop, by design
The mapping from price table to product is a decision, not a guess. The system proposes; a person confirms.
Provenance kept
Every published price can be traced back to the file, page and cell it came from.
Technologies
The result
One 238-page catalogue yielded 278 price blocks and 29,962 individual prices. Across eighteen supplier files, roughly 2,000 pages and about 73,000 price cells are now readable rather than manual.
The file that had produced nothing went from zero to 3,301 prices once the reader worked at glyph level, verified against externally checkable colour codes.
The two catches matter more than the volume. A twenty-one percent error is embarrassing but visible - somebody would have queried it. A three percent error is not visible. It just quietly costs money on every quote until somebody reconciles a year of margin. The control caught the error that would not have looked like an error.
Supplier names, purchase prices and discount structures are commercially confidential and are not published here. The figures above describe the volume and behaviour of the pipeline, not any supplier's terms.
Related work
We read seven months of quotes and found we were building the wrong thing
The roadmap was built on what was easy to read. Not on what the business actually sells.
The first automated read looked perfect. Every field that mattered was empty
An extraction that returns a complete-looking result with nothing important in it is worse than one that fails.