Formualizer
Embeddable spreadsheet engine — parse, evaluate & mutate Excel workbooks from Rust, Python, or the browser. Arrow-powered, 320+ functions.
Install / Use
/learn @PSU3D0/FormualizerREADME
The spreadsheet engine that actually evaluates formulas. Parse, evaluate, and mutate Excel workbooks from Rust, Python, or the browser.
A permissively-licensed, production-grade spreadsheet engine with 320+ Excel-compatible functions, Apache Arrow storage, incremental dependency tracking, undo/redo, and dynamic array support. One Rust core, three language targets, MIT/Apache-2.0.
Highlights
| | | |---|---| | 320+ Excel functions | Math, text, lookup (XLOOKUP, VLOOKUP), date/time, statistics, financial, database, engineering | | Three language targets | Rust, Python (PyO3), and WASM (browser + Node) with consistent APIs | | Arrow-powered storage | Apache Arrow columnar backing with spill overlays for efficient large-workbook evaluation | | Dependency graph | Incremental recalculation, cycle detection, topological scheduling, optional parallel evaluation | | Dynamic arrays | FILTER, UNIQUE, SORT, SORTBY, XLOOKUP with automatic spill semantics | | Undo / redo | Transactional changelog with action grouping, rollback, and replay | | File I/O | Load and write XLSX (calamine, umya), CSV, JSON — all behind feature flags | | SheetPort | Treat any spreadsheet as a typed API with YAML manifests, schema validation, and batch evaluation | | Deterministic mode | Inject clock, timezone, and RNG seed for reproducible evaluation (built for AI agents) |
Documentation
📖 formualizer.dev — full documentation, interactive tools, and API reference.
- Quickstarts — get running in Rust, Python, or JS/WASM in minutes
- Function Reference — 320+ built-in functions with examples
- Formula Parser — interactive browser-based formula parser and AST inspector
- SheetPort Guide — treat spreadsheets as typed, deterministic APIs
- Core Concepts — dependency graph, evaluation pipeline, coercion rules
Who is this for?
- Fintech & insurance teams replacing Excel VBA or server-side workbook evaluation with a fast, deterministic engine that doesn't require Excel installed.
- AI / agent builders who need programmatic spreadsheet manipulation with deterministic evaluation, auditable changelogs, and typed I/O via SheetPort.
- SaaS products embedding spreadsheet logic — pricing calculators, planning tools, configurators — without shipping a full spreadsheet UI.
- Data engineers extracting business logic trapped in spreadsheets into reproducible, testable pipelines.
Quick start
Rust
use formualizer_workbook::Workbook;
use formualizer_common::LiteralValue;
let mut wb = Workbook::new();
wb.add_sheet("Sheet1")?;
// Populate data
wb.set_value("Sheet1", 1, 1, LiteralValue::Number(1000.0))?; // A1: principal
wb.set_value("Sheet1", 2, 1, LiteralValue::Number(0.05))?; // A2: rate
wb.set_value("Sheet1", 3, 1, LiteralValue::Number(12.0))?; // A3: periods
// Monthly payment formula
wb.set_formula("Sheet1", 1, 2, "=PMT(A2/12, A3, -A1)")?;
let payment = wb.evaluate_cell("Sheet1", 1, 2)?;
// => ~85.61
# Cargo.toml
[dependencies]
formualizer = "0.3"
Python
pip install formualizer
import formualizer as fz
wb = fz.Workbook()
s = wb.sheet("Forecast")
# Load actuals
s.set_values_batch(1, 1, [
[fz.LiteralValue.text("Month"), fz.LiteralValue.text("Revenue"), fz.LiteralValue.text("Growth")],
[fz.LiteralValue.text("Jan"), fz.LiteralValue.number(50000.0), fz.LiteralValue.empty()],
[fz.LiteralValue.text("Feb"), fz.LiteralValue.number(53000.0), fz.LiteralValue.empty()],
[fz.LiteralValue.text("Mar"), fz.LiteralValue.number(58000.0), fz.LiteralValue.empty()],
])
# Add growth formulas
s.set_formula(3, 3, "=(B3-B2)/B2") # C3: Feb growth
s.set_formula(4, 3, "=(B4-B3)/B3") # C4: Mar growth
print(wb.evaluate_cell("Forecast", 3, 3)) # 0.06 (6%)
print(wb.evaluate_cell("Forecast", 4, 3)) # ~0.094 (9.4%)
WASM (browser / Node)
npm install formualizer
import init, { Workbook } from 'formualizer';
await init();
const wb = new Workbook();
wb.addSheet('Pricing');
wb.setValue('Pricing', 1, 1, 100); // base price
wb.setValue('Pricing', 2, 1, 0.15); // discount
wb.setFormula('Pricing', 1, 2, '=A1*(1-A2)');
console.log(await wb.evaluateCell('Pricing', 1, 2)); // 85
Custom functions (workbook-local)
You can register custom functions per workbook in Rust, Python, and JS/WASM.
- Rust:
register_custom_function/unregister_custom_function/list_custom_functions - Python:
register_function/unregister_function/list_functions - JS/WASM:
registerFunction/unregisterFunction/listFunctions
Semantics are consistent across hosts:
- Function names are case-insensitive (
my_fn,MY_FN, andMy_Fnrefer to the same function). - Custom functions are workbook-local and resolve before global built-ins.
- Overriding built-ins is blocked by default; opt in with
allow_override_builtin(Rust/Python) orallowOverrideBuiltin(JS). - Arguments are passed by value; range arguments are materialized as 2D arrays/lists.
- Returning an array spills into the grid using normal dynamic-array behavior.
- Callback failures become spreadsheet errors (
ExcelErrorin Rust,#VALUE!mapping for Python/JS exceptions).
Runnable examples:
- Rust callback custom function:
cargo run -p formualizer-workbook --example custom_function_registration - Python callback custom function:
python bindings/python/examples/custom_function_registration.py - JS/WASM callback custom function:
cd bindings/wasm && npm run build && node examples/custom-function-registration.mjs - Rust WASM plugin inspect catalog:
cargo run -p formualizer-workbook --features wasm_plugins --example wasm_plugin_inspect_catalog - Rust WASM plugin inspect + attach + bind:
cargo run -p formualizer-workbook --features wasm_runtime_wasmtime --example wasm_plugin_inspect_attach_bind - Rust WASM plugin directory attach:
cargo run -p formualizer-workbook --features wasm_runtime_wasmtime --example wasm_plugin_attach_dir
WASM plugin path (Rust workbook API):
- Effect-free inspect APIs are available:
inspect_wasm_module_bytesinspect_wasm_module_file(native only)inspect_wasm_modules_dir(native only)
- Explicit workbook-local attach/bind APIs are available:
attach_wasm_module_bytes/attach_wasm_module_file/attach_wasm_modules_dirbind_wasm_function
- Runtime behavior:
wasm_pluginsonly: runtime remains pending (#N/IMPLon bind)wasm_runtime_wasmtime(native):use_wasmtime_runtime()enables executable plugin bindings
How is this different?
| Library | Language | Parse | Evaluate | Write | Functions | Dep. graph | License | |---------|----------|-------|----------|-------|-----------|------------|---------| | Formualizer | Rust / Python / WASM | Yes | Yes | Yes | 320+ | Yes (incremental) | MIT / Apache-2.0 | | HyperFormula | JavaScript | Yes | Yes | No | ~400 | Yes | AGPL-3.0 (or commercial) | | calamine | Rust | No | No | No | N/A | N/A | MIT / Apache-2.0 | | openpyxl | Python | No | No | Yes | N/A | N/A | MIT | | xlcalc | Python | Yes | Yes | No | ~50 | Partial | MIT | | formulajs | JavaScript | No | Yes | No | ~100 | No | MIT |
- HyperFormula is the closest feature competitor, but its AGPL-3.0 license requires you to open-source your entire application or purchase a commercial license from Handsontable. Formualizer is permissively licensed with no strings attached.
- calamine is read-only — it extracts cached values from XLSX files but cannot evaluate formulas.
- openpyxl reads and writes XLSX but has no formula evaluation engine.
- xlcalc evaluates formulas but supports a fraction of Excel's function library and has limited dependency tracking.
- Formualizer is a complete, permissively-licensed engine: parse formulas, track dependencies, evaluate with 320+ functions, mutate workbooks, undo/redo — from Rust, Python, or the browser.
Architecture
Formualizer is organized as a layered crate workspace. Pick the layer that fits your use case:
formualizer <-- recommended: batteries-included re-export
formualizer-workbook <-- high-level workbook API, sheets, undo/redo, I/O
formualizer-eval <-- calculation engine, dependency gra
Related Skills
himalaya
353.1kCLI to manage emails via IMAP/SMTP. Use `himalaya` to list, read, write, reply, forward, search, and organize emails from the terminal. Supports multiple accounts and message composition with MML (MIME Meta Language).
node-connect
353.1kDiagnose OpenClaw node connection and pairing failures for Android, iOS, and macOS companion apps
taskflow
353.1kname: taskflow description: Use when work should span one or more detached tasks but still behave like one job with a single owner context. TaskFlow is the durable flow substrate under authoring layer
claude-opus-4-5-migration
111.6kMigrate prompts and code from Claude Sonnet 4.0, Sonnet 4.5, or Opus 4.1 to Opus 4.5
