Skip to main content

Embeddable spreadsheet engine — parse, evaluate & mutate Excel workbooks at native speed

Project description

Formualizer for Python

Parse, evaluate, and mutate Excel workbooks at native speed from Python.

A Rust-powered spreadsheet engine with 320+ Excel-compatible functions, exposed through a clean Pythonic API. Tokenize formulas, walk ASTs, evaluate workbooks, and use SheetPort to treat spreadsheets as typed APIs.

PyPI License: MIT/Apache-2.0

Installation

pip install formualizer

Prebuilt wheels are available for Python 3.10-3.13 on Linux, macOS, and Windows. No Rust toolchain required.

Quick start

Evaluate a workbook

import formualizer as fz

wb = fz.Workbook()
s = wb.sheet("Sheet1")

s.set_value(1, 1, fz.LiteralValue.number(1000.0))   # A1: principal
s.set_value(2, 1, fz.LiteralValue.number(0.05))      # A2: annual rate
s.set_value(3, 1, fz.LiteralValue.number(12.0))       # A3: periods

s.set_formula(1, 2, "=PMT(A2/12, A3, -A1)")
print(wb.evaluate_cell("Sheet1", 1, 2))  # ~85.61

Load an XLSX and evaluate

import formualizer as fz

wb = fz.load_workbook("financial_model.xlsx", strategy="eager_all")
print(wb.evaluate_cell("Summary", 1, 2))

Parse and analyze formulas

from formualizer import parse
from formualizer.visitor import collect_references, collect_function_names

ast = parse("=SUMIFS(Revenue,Region,A1,Year,B1)")
print(ast.pretty())                          # indented AST tree
print(ast.to_formula())                      # canonical Excel string
print(collect_references(ast))               # [Revenue, Region, A1, Year, B1]
print(collect_function_names(ast))           # ['SUMIFS']

Key features

Capability Description
Tokenization Break formulas into structured Token objects with byte spans and operator metadata
Parsing Produce a rich AST with reference normalization, source tracking, and 64-bit structural fingerprints
320+ built-in functions Math, text, lookup (XLOOKUP, VLOOKUP), date/time, financial, statistics, database, engineering
Workbook evaluation Set values and formulas, evaluate cells/ranges, load XLSX/CSV/JSON
Batch operations set_values_batch / set_formulas_batch for efficient bulk updates
Undo / redo Optional changelog with automatic action grouping — single edits are individually undoable
Evaluation planning Inspect the dependency graph and evaluation schedule before computing
SheetPort Treat spreadsheets as typed functions with YAML manifests, schema validation, and batch scenarios
Deterministic mode Inject clock, timezone, and RNG seed for reproducible evaluation
Visitor utilities walk_ast, collect_references, collect_function_names for ergonomic tree traversal
Rich errors Typed TokenizerError / ParserError / ExcelEvaluationError with position info

Workbook evaluation

import formualizer as fz

wb = fz.Workbook()
s = wb.sheet("Data")

# Set values and formulas
s.set_value(1, 1, fz.LiteralValue.number(100.0))
s.set_value(2, 1, fz.LiteralValue.number(200.0))
s.set_value(3, 1, fz.LiteralValue.number(300.0))
s.set_formula(4, 1, "=SUM(A1:A3)")
s.set_formula(4, 2, "=AVERAGE(A1:A3)")

print(wb.evaluate_cell("Data", 4, 1))  # 600.0
print(wb.evaluate_cell("Data", 4, 2))  # 200.0

Batch operations

# Bulk-set values (auto-grouped as one undo step when changelog is enabled)
s.set_values_batch(1, 1, 3, 2, [
    [fz.LiteralValue.number(10.0), fz.LiteralValue.number(20.0)],
    [fz.LiteralValue.number(30.0), fz.LiteralValue.number(40.0)],
    [fz.LiteralValue.number(50.0), fz.LiteralValue.number(60.0)],
])

Undo / redo

The changelog is opt-in. Once enabled, every edit is tracked:

wb.set_changelog_enabled(True)

s.set_value(1, 1, fz.LiteralValue.number(10.0))
s.set_value(1, 1, fz.LiteralValue.number(20.0))
wb.undo()  # back to 10
wb.redo()  # back to 20

# Batch methods are auto-grouped as one undo step.
# For manual grouping of multiple calls:
wb.begin_action("update prices")
s.set_value(1, 1, fz.LiteralValue.number(100.0))
s.set_value(2, 1, fz.LiteralValue.number(200.0))
wb.end_action()
wb.undo()  # reverts both values at once

Evaluation planning

Inspect what the engine will compute before running:

plan = wb.get_eval_plan([("Sheet1", 1, 2)])
print(f"Vertices to evaluate: {plan.total_vertices_to_evaluate}")
print(f"Parallel layers: {plan.estimated_parallel_layers}")
for layer in plan.layers:
    print(f"  Layer: {layer.vertex_count} vertices, parallel={layer.parallel_eligible}")

SheetPort: spreadsheets as typed APIs

Define a YAML manifest to treat a spreadsheet as a typed function with validated inputs/outputs:

from formualizer import SheetPortSession, Workbook

manifest_yaml = """
spec: fio
spec_version: "0.3.0"
manifest:
  id: pricing-model
  name: Pricing Model
  workbook:
    uri: memory://pricing.xlsx
    locale: en-US
    date_system: 1900
ports:
  - id: base_price
    dir: in
    shape: scalar
    location: { a1: Inputs!A1 }
    schema: { type: number }
  - id: final_price
    dir: out
    shape: scalar
    location: { a1: Outputs!A1 }
    schema: { type: number }
"""

wb = Workbook()
wb.add_sheet("Inputs")
wb.add_sheet("Outputs")
wb.set_formula("Outputs", 1, 1, "=Inputs!A1*1.2")

session = SheetPortSession.from_manifest_yaml(manifest_yaml, wb)
session.write_inputs({"base_price": 100.0})
result = session.evaluate_once(freeze_volatile=True)
print(result["final_price"])  # 120.0

API reference

Top-level functions

tokenize(formula: str, dialect: FormulaDialect = None) -> Tokenizer
parse(formula: str, dialect: FormulaDialect = None) -> ASTNode
load_workbook(path: str, strategy: str = None) -> Workbook

Core classes

  • Workbook — create, load, evaluate, undo/redo. Supports from_path() and load_path() class methods.
  • Sheet — per-sheet facade for set_value, set_formula, get_cell, batch operations.
  • LiteralValue — typed values: .int(), .number(), .text(), .boolean(), .date(), .empty(), .error(), .array().
  • Tokenizer — iterable token sequence with .render() and .tokens.
  • ASTNode.pretty(), .to_formula(), .fingerprint(), .children(), .walk_refs().
  • CellRef / RangeRef / TableRef / NamedRangeRef — typed references.
  • SheetPortSession — bind manifests to workbooks, read/write typed ports, evaluate.
  • EvaluationConfig — tune parallel evaluation, warmup, range limits, date systems.

Visitor helpers (formualizer.visitor)

walk_ast(node, visitor_fn)              # DFS with VisitControl (CONTINUE/SKIP/STOP)
collect_references(node)                # -> list[ReferenceLike]
collect_function_names(node)            # -> list[str]
collect_nodes_by_type(node, "Function") # -> list[ASTNode]

Full type stubs are included in the package (.pyi files) for IDE autocompletion and mypy.


Building from source

Requires Rust >= 1.70 and maturin:

pip install maturin
cd bindings/python
maturin develop          # debug build
maturin develop --release  # optimized build

Testing

pip install formualizer[dev]
pytest bindings/python/tests
ruff check bindings/python
mypy bindings/python/formualizer

Workspace layout

formualizer/
  crates/                    # Rust core (parse, eval, workbook, sheetport)
  bindings/python/
    formualizer/             # Python package (helpers, visitor, type stubs)
    src/                     # PyO3 bridge (Rust -> Python)

The Python wheel links directly against the Rust crates — there is no runtime FFI overhead beyond the initial C-to-Rust boundary.

License

Dual-licensed under MIT or Apache-2.0, at your option.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

formualizer-0.3.4.tar.gz (790.0 kB view details)

Uploaded Source

Built Distributions

If you're not sure about the file name format, learn more about wheel file names.

formualizer-0.3.4-cp310-abi3-win_amd64.whl (4.0 MB view details)

Uploaded CPython 3.10+Windows x86-64

formualizer-0.3.4-cp310-abi3-musllinux_1_2_x86_64.whl (5.1 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ x86-64

formualizer-0.3.4-cp310-abi3-musllinux_1_2_aarch64.whl (4.9 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ ARM64

formualizer-0.3.4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.0 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ x86-64

formualizer-0.3.4-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (4.8 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.17+ ARM64

formualizer-0.3.4-cp310-abi3-macosx_11_0_arm64.whl (4.3 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

formualizer-0.3.4-cp310-abi3-macosx_10_12_x86_64.whl (4.4 MB view details)

Uploaded CPython 3.10+macOS 10.12+ x86-64

File details

Details for the file formualizer-0.3.4.tar.gz.

File metadata

  • Download URL: formualizer-0.3.4.tar.gz
  • Upload date:
  • Size: 790.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for formualizer-0.3.4.tar.gz
Algorithm Hash digest
SHA256 78b763de69176e00fadd97b5222dfc8a83f30b215bb528dde518c04c9a9220ce
MD5 7c1ae90c719a67bbafcb9c353e95eb0b
BLAKE2b-256 2783ea056bc73e55fe73025327cae7191bbd918f7be0f82ba119dd445bb7953d

See more details on using hashes here.

File details

Details for the file formualizer-0.3.4-cp310-abi3-win_amd64.whl.

File metadata

  • Download URL: formualizer-0.3.4-cp310-abi3-win_amd64.whl
  • Upload date:
  • Size: 4.0 MB
  • Tags: CPython 3.10+, Windows x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for formualizer-0.3.4-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 00631ae8d4423e69a9a4aeedd562bdef12f92d5732ff2c7c9b52d9d8187de711
MD5 5b6f44e7ca7e35948dd8db3d57bacd85
BLAKE2b-256 5b61e41b8ec30d45e2150276a2c962a043857bc2fafe5bbf811473645e8ca16c

See more details on using hashes here.

File details

Details for the file formualizer-0.3.4-cp310-abi3-musllinux_1_2_x86_64.whl.

File metadata

  • Download URL: formualizer-0.3.4-cp310-abi3-musllinux_1_2_x86_64.whl
  • Upload date:
  • Size: 5.1 MB
  • Tags: CPython 3.10+, musllinux: musl 1.2+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for formualizer-0.3.4-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 f34af4d932a28b5fdde03a53cd9728c2e31bdbb26bca2cf40cad733f4ab6a86e
MD5 5e303be8fd1e31cff99d7a6d7c06477d
BLAKE2b-256 f80884bddeb0ac6cb4ac8640e03d0cdb102c2c6b42178305a749b84df908846a

See more details on using hashes here.

File details

Details for the file formualizer-0.3.4-cp310-abi3-musllinux_1_2_aarch64.whl.

File metadata

  • Download URL: formualizer-0.3.4-cp310-abi3-musllinux_1_2_aarch64.whl
  • Upload date:
  • Size: 4.9 MB
  • Tags: CPython 3.10+, musllinux: musl 1.2+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for formualizer-0.3.4-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 03022af40c38256a86eb001ba38aee4eb6437c5639608ca0ab60e8307d64264c
MD5 4ee184977672bee9b6b01d423fbf1916
BLAKE2b-256 b1f94cb9d37b927f4c17ab346cbb5630abe18eff280c4392fafbd56e9dc1073e

See more details on using hashes here.

File details

Details for the file formualizer-0.3.4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

  • Download URL: formualizer-0.3.4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
  • Upload date:
  • Size: 5.0 MB
  • Tags: CPython 3.10+, manylinux: glibc 2.17+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for formualizer-0.3.4-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 b7caea1762d2d4dba6c6b34a33a02d2f0792362a6078ecc06a6aa82dbc4d346d
MD5 71ede035b0e440c4a0a6a35811bea475
BLAKE2b-256 95b2a7694416e962799b8a5c03d68f775dd25527c55464fd546ef9fe1f94df82

See more details on using hashes here.

File details

Details for the file formualizer-0.3.4-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

  • Download URL: formualizer-0.3.4-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
  • Upload date:
  • Size: 4.8 MB
  • Tags: CPython 3.10+, manylinux: glibc 2.17+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for formualizer-0.3.4-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 f7b0ffc7a1d95f9230ba47f0cfe65468f1459e8f59166682cd0fec8a3a3ddff6
MD5 4c999802f347fb31c6f38ff96c6fd358
BLAKE2b-256 3a741eb0dbab35a01cfd4d442c8d7b44cb84d021713cea32a3f0d01adc4e7870

See more details on using hashes here.

File details

Details for the file formualizer-0.3.4-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

  • Download URL: formualizer-0.3.4-cp310-abi3-macosx_11_0_arm64.whl
  • Upload date:
  • Size: 4.3 MB
  • Tags: CPython 3.10+, macOS 11.0+ ARM64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for formualizer-0.3.4-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e418b3ac362c6242df144e2147fb4e20de68da3d0ed3259db9fc7242b12451f7
MD5 f4fdb204e26a620a8512d5d2853778d7
BLAKE2b-256 730563d3e66eff7a6bf7da427c1f4f3563d037643885348b53f00ee01cb53236

See more details on using hashes here.

File details

Details for the file formualizer-0.3.4-cp310-abi3-macosx_10_12_x86_64.whl.

File metadata

  • Download URL: formualizer-0.3.4-cp310-abi3-macosx_10_12_x86_64.whl
  • Upload date:
  • Size: 4.4 MB
  • Tags: CPython 3.10+, macOS 10.12+ x86-64
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.10.2 {"installer":{"name":"uv","version":"0.10.2","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for formualizer-0.3.4-cp310-abi3-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 c0671c5584f9fa9f3b9988ed2a5e93e9e1a160aae5ebbea6bee611f44d842a92
MD5 d606c4c9503647308f9fd60ca1731eda
BLAKE2b-256 37df227c831ba66642837a0c3d5130ebb709099ebddcc2453fcf358ac18c396b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page