openpyxl writes formulas.
It never evaluates them
So the workbook you just generated can build without a single warning, open beautifully in Excel, and be arithmetically wrong — and your test suite will not notice, because the "value" openpyxl reads back is the formula string you wrote.
xlcheck recalculates the workbook the way Excel would, then asserts every figure against arithmetic you worked out by hand.
Python 3.10+ · two dependencies · $49 one-time, source included
from xlcheck import load, assert_cell, assert_no_error_cells
wb = load("build/report.xlsx") # recalculated, cached
assert_cell(wb, "Dashboard!A5", 16120.00, label="current MRR")
assert_cell(wb, "Dashboard!E5", 0.032508, tolerance=1e-5, label="gross churn")
assert_no_error_cells(wb)
Or keep the expected figures in YAML next to the workbook and run
python3 -m xlcheck spec.yml — exit code 1 on any failure, so it drops
into a build or a pre-commit hook unchanged.
The defects it finds are never crashes
They are numbers that look right. These four are real — the first run of this code against a set of finished, ready-to-ship finance templates found three of them, and the fourth is the one that had already reached a layout nobody opened by hand:
- An array formula needing Ctrl-Shift-Enter in Excel: it returned the first row of a table and silently dropped every other one. A user with five clients would have seen one, with no error anywhere on the sheet.
- An average over empty months, reading 1.6% where the truth was 3.25%, and 100% where the truth was 98.6%.
-
A zero divisor that
IFERRORdressed up as a tidy "$0.00" — an error presented as a result. -
A #REF! sitting in a headline cell.
wb.error_cells()finds every one of those without you having to know where to look — the cheapest high-value assertion in the package.
Two rules it enforces on you, on purpose
- An expected value is hand-computed, never read back from the workbook.
- A test that asks the sheet what it thinks the answer is proves only that the sheet is self-consistent. This is why there is no "record current values" mode — it would be the most requested feature and would defeat the entire package.
- Blank is not zero.
-
blankandnot_blankassertions exist so the absence of a value is asserted as deliberately as its presence. A dropped table row and a suppressed error both show up as an innocent empty cell.
What you get
The full source
Five modules, readable in one sitting: recalculation model, checks, YAML spec loader, CLI, package init.
15 tests that prove it
The suite builds a workbook containing the real defect shapes above, then asserts each one is caught. No mocks.
A runnable example
Generator plus spec, end to end: python3 example/build_example.py && python3 -m xlcheck example/spec.yml.
Yours outright
One-time $49. Commercial single-organisation licence, no subscription, no seat count, no phone-home.
Limits, stated before you buy
Recalculation uses the formulas engine, not Excel's. It covers the ordinary
function surface of a generated workbook — arithmetic, the SUM/AVERAGE/COUNT family,
IF/IFERROR, INDEX/MATCH, lookups, date and text functions. It does not run macros, pivot
tables, or external links, and a very exotic formula may not resolve — which shows up
as a failed check, never as a silent pass. Large workbooks are slow to solve;
results are cached per file per process, so a suite pays that cost once.
Get xlcheck
One payment, yours to keep and modify. Commercial single-organisation licence — use and modify it across your whole company, no subscription, no per-seat pricing. Instant download through Gumroad.
Buy xlcheck — $49Checkout and delivery are handled by Gumroad, which is the merchant of record.