SkillAgentSearch skills...

Formualizer

Embeddable spreadsheet engine — parse, evaluate & mutate Excel workbooks from Rust, Python, or the browser. Arrow-powered, 320+ functions.

Install / Use

/learn @PSU3D0/Formualizer

README

<h1 align="center">Formualizer</h1> <p align="center"> <img alt="Arrow Powered" src="https://img.shields.io/badge/Arrow-Powered-0A66C2?logo=apache&logoColor=white" /> <a href="https://github.com/psu3d0/formualizer/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/psu3d0/formualizer/actions/workflows/ci.yml/badge.svg" /></a> <img alt="Python Coverage" src="https://raw.githubusercontent.com/psu3d0/formualizer/badges/coverage.svg" /> <img alt="Rust Core Coverage" src="https://raw.githubusercontent.com/psu3d0/formualizer/badges/rust-core-coverage.svg" /> <a href="https://crates.io/crates/formualizer"><img alt="crates.io" src="https://img.shields.io/crates/v/formualizer.svg" /></a> <a href="https://pypi.org/project/formualizer/"><img alt="PyPI" src="https://img.shields.io/pypi/v/formualizer.svg" /></a> <a href="https://www.npmjs.com/package/formualizer"><img alt="npm" src="https://img.shields.io/npm/v/formualizer.svg" /></a> <a href="https://www.formualizer.dev/docs"><img alt="Documentation" src="https://img.shields.io/badge/docs-formualizer.dev-blue" /></a> <a href="#license"><img alt="License: MIT/Apache-2.0" src="https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg" /></a> </p> <p align="center"> <img alt="Formualizer banner" src="https://raw.githubusercontent.com/psu3d0/formualizer/main/assets/formualizer-banner.png" /> </p> <br />

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.

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, and My_Fn refer 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) or allowOverrideBuiltin (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 (ExcelError in 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_bytes
    • inspect_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_dir
    • bind_wasm_function
  • Runtime behavior:
    • wasm_plugins only: runtime remains pending (#N/IMPL on 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

View on GitHub
GitHub Stars113
CategoryDevelopment
Updated9h ago
Forks13

Languages

Rust

Security Score

85/100

Audited on Apr 9, 2026

No findings