CI for generated XLSX files. SheetParity opens a workbook in named spreadsheet engines, forces recalculation where the engine supports it, and reports material formula, value, error, and structural differences before a customer finds them.
Use SheetParity in GitHub Actions or local CI to test generated Excel-compatible .xlsx workbooks, catch stale formula caches and unsupported formulas, and detect lost names, protection, page setup, headers, footers, and other OOXML structure. The implemented engine matrix is stable LibreOffice plus opt-in Google Sheets; SheetParity does not mislabel either one as desktop Excel validation.
$ sheetparity test report.xlsx --matrix libreoffice
SheetParity FAIL
report.xlsx sha256:18e2cb9dda66 4078 bytes
Engine Outcome Evidence
LibreOffice 26.2.4.2 FAIL 1 material / 1 total differences
Material differences
Report!D4 libreoffice value_changed 999 → 75
That workbook is a valid OOXML ZIP package. Its formula cache says 999; LibreOffice recalculates the formula to 75. A package validator alone cannot expose that difference.
- Static XLSX package inspection: required parts, XML parsing, internal relationships, formula/cached values, errors, sheets, names, tables, charts, drawings, macros, and external-link inventory.
- A real LibreOffice adapter with an isolated user profile, controlled
Clocale andUTCtimezone, hard timeout, explicit version capture,calculateAll(), and XLSX export. - A credentialed Google Sheets adapter that imports XLSX as a native Sheet in a dedicated folder, performs a reversible edit trigger, captures formulas and calculated effective values after two stable reads, and permanently deletes the remote file.
- Stable normalized JSON with a versioned JSON Schema and a semantic fingerprint that excludes operational timing/path noise and nondeterministic managed-export diagnostic bytes.
- Human terminal output and a standalone HTML report.
- Materiality rules for numeric tolerances, formula/error changes, structural loss, volatile functions, and external references.
- A 68-file CC0 fixture corpus with provenance, hashes, 20 known-good controls, 20 known-bad cases, and 28 prospectively specified exploratory edges.
- A composite GitHub Action plus a pinned LibreOffice 26.2.4 Linux installer.
Excel Web, OnlyOffice, and desktop Excel are adapter boundaries, not implemented engines. Google Sheets is implemented and live-scored, but remains opt-in and credential-gated for users. The prospectively frozen third falsification round passed every unchanged technical threshold: 20/20 known-bad detections, 0/20 known-good false positives, 20/20 stable repeats, 7 qualifying package-well-formed LibreOffice-versus-Google divergences against a requirement of 5, one independently reproduced public silent-value failure, and zero remote cleanup failures. SheetParity never calls Excel Web “Excel” and never treats a validator as a spreadsheet engine.
Requires Node.js 20+ and a stable LibreOffice installation.
Project-local install from npm:
npm install --save-dev sheetparity@next
npx sheetparity test report.xlsx \
--matrix libreoffice \
--json result.json \
--html report.htmlOr install the prerelease CLI globally:
npm install --global sheetparity@next
sheetparity test report.xlsx --matrix libreofficeIf soffice is not on PATH, pass it explicitly:
sheetparity test report.xlsx \
--matrix libreoffice \
--soffice /path/to/sofficeGoogle Sheets is opt-in. SheetParity accepts an explicitly named service-account credential for a Shared Drive or an explicitly authorized OAuth user credential for a dedicated personal-Drive folder. It deliberately ignores Application Default Credentials and ambient browser cookies.
- Enable Drive API v3 and Sheets API v4 in a dedicated Google Cloud project.
- Use either a service account with Manager access to a dedicated Google Workspace Shared Drive, or a Desktop OAuth client authorized with only
drive.filefor a dedicated user-owned folder. - Store the resulting credential outside the repository and set the two explicit variables below.
export SHEETPARITY_GOOGLE_CREDENTIALS=/absolute/path/sheetparity.credentials.json
export SHEETPARITY_GOOGLE_TEST_FOLDER_ID=your_dedicated_folder_id
node bin/sheetparity.js test report.xlsx \
--matrix libreoffice,google-sheets \
--soffice /path/to/soffice \
--timeout 120000 \
--json result.jsonThe adapter uses only Google's recommended, non-sensitive drive.file scope, includes Shared Drive support on create/delete calls, never returns a remote spreadsheet URL, and treats cleanup failure as a material engine error. The scope supports Sheets API reads for app-created files without granting access to every spreadsheet in the user's Drive. Google does not expose an exact spreadsheet-engine build number through these APIs, so version is truthfully null; the API surfaces, locale, timezone, and calculation mode are recorded instead.
See docs/google-sheets-setup.md for the exact dedicated-project, Shared Drive, smoke-test, and credential requirements.
Exit codes are CI-friendly:
| Code | Meaning |
|---|---|
0 |
No material source or engine difference |
1 |
Material package, open/import, formula, value, error, or structure failure |
2 |
Usage or internal error |
3 |
Requested engine matrix is incomplete |
Pin the prerelease Action tag:
- name: Test generated XLSX
uses: Atomics-hub/sheetparity@v0.1.0-alpha.3
with:
file: reports/quarterly-report.xlsx
matrix: libreofficeThe action downloads the official LibreOffice 26.2.4 Linux package, verifies its pinned SHA-256, installs it on an Ubuntu runner, runs SheetParity, and writes the terminal summary to the GitHub job summary. JSON and HTML paths are exposed as action outputs.
Every result identifies:
- source SHA-256 and package evidence;
- exact engine id, kind, version, release channel, locale, timezone, font source, and calculation mode;
- open/import outcome and captured diagnostics;
- formulas, cached/recalculated values, errors, named objects, and structural losses;
- materiality decisions and unavailable proof layers;
- a deterministic semantic fingerprint.
The contract is in schemas/result.schema.json. See docs/adapter-contract.md before implementing another engine.
Default policy:
{
"numericAbsoluteTolerance": 1e-9,
"numericRelativeTolerance": 1e-9,
"ignoreVolatileFormulaValues": true,
"ignoreExternalFormulaValues": true,
"structuralLossIsMaterial": true,
"formulaChangeIsMaterial": true,
"errorChangeIsMaterial": true
}Override it with --policy policy.json. Volatile and external formulas remain visible in JSON even when their value changes are non-material.
The corpus is intentionally small enough to audit. fixtures/manifest.json records classification, expected outcome, provenance, license, SHA-256, and whether a fixture is a well-formed package with a semantic divergence.
Run the full local experiment with a stable engine:
SHEETPARITY_SOFFICE=/path/to/soffice npm run falsifyRun the credentialed two-engine experiment only in a dedicated Google test environment:
SHEETPARITY_MATRIX=libreoffice,google-sheets \
SHEETPARITY_SOFFICE=/path/to/soffice \
SHEETPARITY_GOOGLE_CREDENTIALS=/absolute/path/sheetparity.credentials.json \
SHEETPARITY_GOOGLE_TEST_FOLDER_ID=your_dedicated_folder_id \
npm run falsifyThe dossier-level gate is stricter than the local experiment. A source cache versus one LibreOffice recalculation is useful local proof, but it is not disagreement between two independent real engines. Round one found 3/5 qualifying files. Round two remained at 3/5 and exposed a nondeterministic managed-export fingerprint, which was fixed without changing that round's result. The prospectively frozen 68-file third round passed at 7/5 with 0/20 known-good false positives and 20/20 stable repeats. The complete evidence and publication decision are recorded in docs/falsification.md.
SheetParity can report what a named engine version did in a controlled environment. It cannot prove behavior across every Office build, device, font set, locale, printer driver, add-in, macro, or external data connection.
Current render comparison is unavailable and labeled as such in every result. Google import/recalculation proof is implemented and was live-scored through a dedicated OAuth test folder; Google still does not expose a precise Sheets engine build number. Native Excel repair prompts also remain unavailable until a properly licensed user-owned runner exists. Desktop Office server automation is not silently substituted.
The CLI, local runner, result model, materiality policy, and public fixture corpus belong in the open. The credible hosted surface is managed Excel Web and Google execution, private fixtures, retained baselines, pull-request checks, team policy, audit history, zero-retention controls, and user-owned runners.
The most valuable contribution is a minimized, redistributable XLSX fixture with exact producer and engine versions. Read CONTRIBUTING.md and the fixture provenance rules before opening a pull request.
MIT licensed. Synthetic fixture bytes are CC0-1.0.