# truecalc-core
[](https://crates.io/crates/truecalc-core)
[](https://docs.rs/truecalc-core)
[](LICENSE)
Formula engine with exact Google Sheets semantics — stateless, embeddable, bring your own data model.
484 functions with exact Google Sheets semantics. Ground-truth conformance validated case by case against real Google Sheets — not a spec interpretation. Stateless and embeddable: bring your own data model, no workbook required. Also available as a [WebAssembly npm package](https://www.npmjs.com/package/@truecalc/core) and as an [MCP server](https://crates.io/crates/truecalc-mcp) for AI assistants.
```rust
let result = Engine::sheets().evaluate("=SUM(A1,B1)", &vars);
// => Value::Number(300.0)
```
## Install
```toml
[dependencies]
truecalc-core = "0.9"
```
Or via cargo:
```sh
cargo add truecalc-core
```
## Quick start
```rust
use std::collections::HashMap;
use truecalc_core::{Engine, Value};
let engine = Engine::sheets();
let mut vars = HashMap::new();
vars.insert("A1".to_string(), Value::Number(100.0));
vars.insert("B1".to_string(), Value::Number(200.0));
let result = engine.evaluate("=SUM(A1,B1)", &vars);
assert_eq!(result, Value::Number(300.0));
```
## Usage
### Evaluate a formula
```rust
use std::collections::HashMap;
use truecalc_core::{Engine, Value};
let engine = Engine::sheets();
let mut vars = HashMap::new();
vars.insert("A1".to_string(), Value::Number(100.0));
vars.insert("B1".to_string(), Value::Number(200.0));
let result = engine.evaluate("=SUM(A1, B1)", &vars);
assert_eq!(result, Value::Number(300.0));
```
### Pattern match on the result
```rust
use std::collections::HashMap;
use truecalc_core::{Engine, Value};
let mut vars = HashMap::new();
vars.insert("score".to_string(), Value::Number(85.0));
match Engine::sheets().evaluate("=IF(score >= 60, \"pass\", \"fail\")", &vars) {
Value::Text(s) => println!("{s}"), // "pass"
Value::Number(n) => println!("{n}"),
Value::Bool(b) => println!("{b}"),
Value::Error(e) => eprintln!("formula error: {e}"),
Value::Empty => println!("(empty)"),
Value::Array(_) => println!("(array)"),
}
```
### Validate without evaluating
```rust
use truecalc_core::Engine;
match Engine::sheets().validate("=SUM(A1, B1)") {
Ok(_) => println!("valid"),
Err(e) => eprintln!("parse error at position {}: {}", e.position, e.message),
}
```
### Parse to an AST
```rust
use truecalc_core::Engine;
let expr = Engine::sheets().parse("=1 + 2 * 3").expect("valid formula");
// expr is an Expr tree you can walk yourself
```
### Evaluate with a Resolver (workbook integration)
For workbook-backed evaluation where references should be resolved against a
live cell grid, implement the [`Resolver`](https://docs.rs/truecalc-core/latest/truecalc_core/eval/trait.Resolver.html) trait:
```rust
use truecalc_core::{Engine, ErrorKind, Ref, Resolver, Value};
struct OneSheet;
impl Resolver for OneSheet {
fn resolve(&mut self, r: &Ref) -> Value {
match r {
Ref::Cell { sheet: Some(s), .. } if s == "Data" => Value::Number(10.0),
Ref::Cell { sheet: Some(_), .. } => Value::Error(ErrorKind::Ref),
_ => Value::Empty,
}
}
}
let engine = Engine::sheets();
assert_eq!(engine.evaluate_with_resolver("=Data!A1", &mut OneSheet), Value::Number(10.0));
```
For a full workbook implementation, see [`truecalc-workbook`](https://docs.rs/truecalc-workbook).
## Engine flavors
The engine flavor controls formula semantics and the date serial system:
| `Engine::sheets()` | Google Sheets | Day 0 = 1899-12-30, no 1900 leap bug |
| `Engine::excel()` | Excel | Serial 1 = 1900-01-01, Lotus leap-year bug |
> **Note:** Excel evaluation is not yet implemented. `Engine::excel().evaluate()` returns
> `#UNSUPPORTED!`. `parse()` and `validate()` work for both flavors.
## Types
### `Value`
| `Number(f64)` | Finite numeric value (never NaN or infinity) |
| `Text(String)` | String value |
| `Bool(bool)` | Boolean value |
| `Error(ErrorKind)` | Formula error (e.g. `#DIV/0!`) |
| `Empty` | Missing/blank cell reference |
| `Array(Vec<Value>)` | Array of values |
### `ErrorKind`
| `DivByZero` | `#DIV/0!` |
| `Value` | `#VALUE!` |
| `Ref` | `#REF!` |
| `Name` | `#NAME?` |
| `Num` | `#NUM!` |
| `NA` | `#N/A` |
| `Null` | `#NULL!` |
## Available functions
Covers math, logical, text, financial, and statistical categories. For the full list with signatures and descriptions, query the live registry:
```rust
use truecalc_core::Registry;
let registry = Registry::new();
for (name, meta) in registry.list_functions() {
println!("{} ({}): {}", name, meta.category, meta.description);
}
```
## Migration from 0.6.x
See [`MIGRATION.md`](MIGRATION.md) for the full guide.
**Summary:** The free `evaluate()` function and `Engine::google_sheets()` constructor
were deprecated in 0.7.0. Replace them with `Engine::sheets().evaluate()`.
## Related crates
- [`truecalc-workbook`](https://crates.io/crates/truecalc-workbook): full workbook layer with
engine-locked workbook, worksheet, cell mutation, and recalc.
## Documentation
[docs.truecalc.app](https://docs.truecalc.app)
## License
MIT