Site logo

Output Checker for the Christmas card project

The Christmas card project script makes hundreds of print files every night during the season: order forms, Christmas cards, gift labels, calendars, mugs, keyrings, fridge magnets and so on. Each file must contain exactly what the parents ordered: the right number of pages for every pupil, with the right name, class and school on it. Nobody can check thousands of pages by eye, so I made an Output Checker that does it automatically after each run.

It’s not an InDesign script. It’s a small Python program plus a set of instructions (a skill) for Claude, the AI assistant. You can run the program on its own from the command line, or simply ask Claude to “check the result” and it runs the program, looks at the pages it flagged and writes a short report.

What it checks

The checker reads the same Excel workbook the script uses and compares it with the PDF files in the Print Files folder of the school. It knows nothing about InDesign and doesn’t trust the script’s own logs: it only looks at the input and the final result.

The checker reads the text on every page, including mirrored text (the backs of folded cards are printed upside down) and rotated text, and assigns each page to a pupil by the printed name. It checks only the products that were actually made in this run, and lists the ones that were ordered but not produced, so nothing is forgotten.

The rules

All the knowledge about the products is kept in a plain text file, rules.yaml, not in the program. For each product it says which column of the spreadsheet feeds it, how many packs one unit means, how many pages one pack takes, the file name of the PDF and which texts must be printed. Here’s the rule for the Christmas cards:

Christmas cards:
  pdf: "Christmas cards 4up - {class} - {school} - Print Files.pdf"
  pages_per_pack: 3         # 12 cards = 3 pages x 4up
  sources:
    - {column: K, packs: 1} # Christmas Cards
    - {column: O, packs: 3} # 3 for 2 = 3 packs
    - {column: Y, packs: 2} # Value Pack = 2 packs of Christmas cards
  mirrored_text: true
  check: [name, class, school]

Every season, the products and the spreadsheet change a little: a product is dropped, a column moves, a new offer appears. In this case, only the rules file has to be edited, and my client and I can both do it, since the checker lives in a shared Dropbox folder. A check that turns out to be wrong can be switched to a warning, so it’s still reported but doesn’t mark the school as a problem.

The report

For every school, the checker writes a _Check report.md file next to the school’s workbook. It starts with OK or PROBLEM, then lists each product: the file, the number of pages found and expected, and only the problems, grouped so that one missing pack in ten pupils is one line, not ten. When Claude runs the checker, it also opens the flagged pages to say why they failed (pages missing, a name printed in another form, a hidden value printed) and compares the findings with the script’s own error log and run summary.

For example, on the first test of this season, the checker found that the order deadline was missing on the order forms. The reason turned out to be a one-row shift in the new spreadsheet: the script was reading the cell above the deadline. That’s exactly the kind of error that’s easy to miss in a print file and expensive to find after printing.

How to run it

It needs Python 3 with three libraries: openpyxl to read the workbook, pdfplumber to read the PDFs and pyyaml for the rules:

pip install openpyxl pdfplumber pyyaml
python scripts/check_output.py "path/to/Schools/Some School"

Point it at one school folder or at the whole Schools folder to check every school in one go. Use --products "Christmas cards" to check only certain products.

Or, in a Claude chat connected to the project folder, just write “check the result” after the script has finished.

Pages about this project