{"id":50494847,"url":"https://github.com/libraz/formulon","last_synced_at":"2026-06-02T06:03:31.716Z","repository":{"id":358403438,"uuid":"1235194754","full_name":"libraz/formulon","owner":"libraz","description":"Headless Excel 365 calculation engine (C++17) — WASM, Python, and native CLI.","archived":false,"fork":false,"pushed_at":"2026-05-17T09:07:13.000Z","size":7281,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-17T09:15:26.545Z","etag":null,"topics":["calculation-engine","cpp","cpp17","excel","excel-formulas","formula","headless","nodejs","npm-package","office-365","ooxml","python","spreadsheet","wasm","webassembly","xlsx"],"latest_commit_sha":null,"homepage":"https://formulon.libraz.net","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/libraz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-05-11T05:16:36.000Z","updated_at":"2026-05-15T03:43:40.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/libraz/formulon","commit_stats":null,"previous_names":["libraz/formulon"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/libraz/formulon","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libraz%2Fformulon","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libraz%2Fformulon/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libraz%2Fformulon/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libraz%2Fformulon/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/libraz","download_url":"https://codeload.github.com/libraz/formulon/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/libraz%2Fformulon/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33808702,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-02T02:00:07.132Z","response_time":109,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["calculation-engine","cpp","cpp17","excel","excel-formulas","formula","headless","nodejs","npm-package","office-365","ooxml","python","spreadsheet","wasm","webassembly","xlsx"],"created_at":"2026-06-02T06:03:29.384Z","updated_at":"2026-06-02T06:03:31.710Z","avatar_url":"https://github.com/libraz.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Formulon\n\n[![CI](https://img.shields.io/github/actions/workflow/status/libraz/formulon/ci.yml?branch=main\u0026label=CI)](https://github.com/libraz/formulon/actions/workflows/ci.yml)\n[![npm](https://img.shields.io/npm/v/@libraz/formulon)](https://www.npmjs.com/package/@libraz/formulon)\n[![PyPI](https://img.shields.io/pypi/v/formulon)](https://pypi.org/project/formulon/)\n[![codecov](https://codecov.io/gh/libraz/formulon/branch/main/graph/badge.svg)](https://codecov.io/gh/libraz/formulon)\n[![License](https://img.shields.io/badge/license-Apache--2.0-blue)](https://github.com/libraz/formulon/blob/main/LICENSE)\n[![C++17](https://img.shields.io/badge/C%2B%2B-17-blue?logo=c%2B%2B)](https://en.cppreference.com/w/cpp/17)\n[![Platform](https://img.shields.io/badge/platform-Linux%20%7C%20macOS%20%7C%20WebAssembly-lightgrey)](https://github.com/libraz/formulon)\n[![Docs](https://img.shields.io/badge/docs-formulon.libraz.net-blue)](https://formulon.libraz.net)\n\nFormulon is a headless, Excel-compatible calculation engine — a C++17 core that defaults to the **Windows Excel 365 (ja-JP)** behavior profile, with every known divergence explicitly tracked against Excel oracle data. The same engine is packaged for the browser (WebAssembly), for Python, and for native command-line use, so a workbook recalculates to the same values wherever it runs.\n\nNo Excel installation, no Microsoft runtime, no COM automation required. The WASM build runs in browsers, Node, and Python through `wasmtime`; native CLI packages currently ship for `darwin-arm64`, `linux-x64`, and `linux-arm64`.\n\n## Why Formulon\n\n- **Strict oracle, not aspirational compatibility.** The runtime default is `win-365-ja_JP`, and profile-specific oracle suites pin observed Excel behavior. The primary checked-in oracle remains Mac Excel 365 (ja-JP), while Windows Excel 365 (ja-JP) is verified through variant goldens. Outputs are checked for bit-level parity against golden data regenerated from the real product; every accepted divergence (transcendental ulp drift, volatile-function snapshots, Excel quirks where Formulon deliberately keeps a saner answer) is recorded case-by-case in [`tests/divergence.yaml`](tests/divergence.yaml) with a reason and the last verified Excel build.\n- **One C++ core, identical results everywhere.** JS-only competitors re-run the logic in the browser and the logic on the server. Formulon ships one engine to every surface (WASM, Python, CLI) so there is no second implementation to drift.\n- **Strict WASM size budget.** Target **1.65 MB uncompressed / 530 KB Brotli**, hard ceiling **1.9 MB / 600 KB Brotli**. The budget is enforced in CI, not aspirational; features ship within the budget or do not ship.\n- **Small dependency set.** Engine deps: `miniz` (zip/deflate), `pugixml` (XML + XPath 1.0), `PCRE2` (Excel-compatible regex for `REGEX*`), `double-conversion` (Grisu3 shortest-roundtrip `dtoa`). Linear algebra, UTF-8 handling, and most number coercion are in-tree.\n- **Readable, reviewable code.** `Expected\u003cT, Error\u003e` error handling, RAII, `-fno-exceptions -fno-rtti`, Google C++ style.\n\n## What it is useful for\n\nAnywhere a spreadsheet needs to be computed without booting Excel:\n\n- running `.xlsx` workbooks headlessly in batch jobs or data pipelines,\n- evaluating Excel-style formulas inside a web application, in the browser,\n- embedding calculation into internal tools, bots, or notebooks,\n- validating formulas and migrating legacy spreadsheets.\n\n## Non-goals (by design)\n\nFormulon deliberately does **not** cover:\n\n| Area | Reason |\n|------|--------|\n| VBA execution | Security. `vbaProject.bin` is preserved byte-for-byte, never executed. |\n| Legacy `.xls` (BIFF8, Excel 97–2003) | Out of scope for Excel 365 compatibility. |\n| Chart / drawing rendering | Belongs to a rendering layer, not the engine. |\n| PowerQuery (M) / DAX | Separate engine, separate problem domain. |\n| Pivot cache recomputation | Structurally preserved; recomputation is out of scope. |\n| Spreadsheet UI | A thin UI integration layer is planned; rendering is yours. |\n\nThese are **permanent** non-goals, not \"not yet.\" The scope is finite on purpose.\n\n## Packaging\n\n| Surface | Name | Notes |\n|---------|------|-------|\n| npm | `@libraz/formulon` | WASM ESM module, type definitions included. Node 18+, browsers, workers. |\n| PyPI | `formulon` | Python 3.9+ `py3-none-any` wheel that bundles `formulon_capi.wasm` plus a pure-Python wrapper. `pip` resolves the platform-specific `wasmtime` runtime. |\n| GitHub Releases | `formulon-cli-\u003cplatform-arch\u003e` | Standalone CLI binaries (`eval`, `recalc`, `dump`) for `darwin-arm64`, `linux-x64`, `linux-arm64`. |\n\n## Status\n\n**All 522 catalogued Excel functions are recognized**, but recognition is not the same as full Excel-compatible execution. The function catalog exposes availability explicitly; `make function-status` reports the current split.\n\n| Availability | Count | Meaning | Examples |\n|--------------|-------|---------|----------|\n| Real implementation | 507 | Evaluates inside the normal calculation engine and is covered by unit and/or oracle tests. | Math, statistics, lookup, text, dynamic arrays |\n| Implemented, verification ongoing | 0 | Implemented, but still waiting for additional oracle confirmation on Excel edge cases. | None currently |\n| Environment-bound | 2 | Depends on host or workbook state, so a fixed golden cannot fully describe it. | `INFO`, `CELL` |\n| Unavailable stub | 15 | Requires external services, network I/O, COM providers, or OLAP connections that Formulon does not embed; returns a fixed unavailable error surface. | `PY`, `WEBSERVICE`, `STOCKHISTORY`, `IMAGE`, `RTD`, `TRANSLATE`, `DETECTLANGUAGE`, `COPILOT`, `CUBE*` |\n\n**92 oracle categories** are defined and regenerated from Mac Excel 365 ja-JP, with Windows Excel 365 ja-JP covered by the `win-365-ja_JP` variant goldens. Current local verification is `14342/14342` fast tests passing, `4026/4026` primary formula oracle cases passing with `166` documented skips. Every remaining skip is an explicit divergence, host-service dependency, volatile/environment-bound case, or driver limitation, not a silent stub. Of the 522 catalogued functions, `515` satisfy all six closure conditions (`behaviors_declared` / `cases_cover_behaviors` / `golden_present` / `divergence_documented` / `not_in_pilot` / `behavior_drift`); the remaining `7` (`FILTERXML`, `ARRAYTOTEXT`, `CONCAT`, `CHAR`, `TRUE`, `GETPIVOTDATA`, `PHONETIC`) are blocked on oracle metadata gaps — missing goldens or under-specified behavior taxonomies — rather than implementation gaps.\n\nBeyond formula results, **pivot tables and print areas / pagination** have a dedicated **workbook oracle track** whose primary is `win-365-ja_JP` (reliable PivotTable automation needs Windows Excel COM). Goldens are captured end-to-end: the pivot suites close at `28/28`, and the `print_basic`, `print_pagination`, `print_fit`, and `print_matrix` suites pass `35/41` cases via the `formulon_workbook_oracle_tests` harness with `6` documented divergence-skip entries scoped to `win-365-ja_JP` for a known Excel PageBreakPreview COM quirk at `PageSetup.Zoom \u003c= 50` (low-zoom column auto-breaks invert the intuitive shrink-to-fit rule; the engine emits no break, matching the geometric model rather than Excel's PBP overlay).\n\nNew workbooks use the `win-365-ja_JP` formula profile by default; callers can switch with the profile-id API (`mac-365-ja_JP`, `win-365-ja_JP`). English-locale profiles are intentionally not exposed until matching EN oracle data and verified locale-specific behavior are available. A bytecode compiler and stack-machine VM run in parallel with the tree-walker for parity verification. The OOXML reader/writer round-trips sheets, styles, conditional formatting, comments, hyperlinks, merges, data validations, defined names, tables, and pivot tables; an MS-XLSB reader/writer is in place. Workbook-level operations (sheet add / rename / move, row/column insert / delete with formula rewriting, partial recalc, iterative-solver progress callbacks) are wired through the C ABI and exposed in the WASM, Python, and CLI surfaces.\n\nFeedback, issue reports, and oracle divergence reports are very welcome.\n\n## Contributing\n\nThe fastest way to help right now is to **donate Excel oracle data from your locale**. If you have Excel 365 in any locale beyond Mac ja-JP, one command (`make oracle-contribute`) drives Excel, captures goldens, and walks you through the PR. See [CONTRIBUTING.md](CONTRIBUTING.md) for the full flow and the rationale for why this is community-driven.\n\n## License\n\nApache License 2.0. See [LICENSE](LICENSE) and [NOTICE](NOTICE).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibraz%2Fformulon","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flibraz%2Fformulon","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flibraz%2Fformulon/lists"}