Architecture
Useful background when you are reasoning about performance, about what is modelled versus preserved, or about why an API is shaped the way it is.
Layers
┌─────────────────────────────────────────────────────────────┐
│ API Java │
├─────────────────────────────────────────────────────────────┤
│ FFI JNI bridge (libaxyra_jni) │
├─────────────────────────────────────────────────────────────┤
│ I/O ooxml · xls · csv · json · html · render │
├─────────────────────────────────────────────────────────────┤
│ Eval formula — parser, evaluator, 500+ functions │
├─────────────────────────────────────────────────────────────┤
│ Format format — number and date format codes │
├─────────────────────────────────────────────────────────────┤
│ Model model — Book · Sheet · Cell · Range · Style · │
│ Chart · PivotTable │
└─────────────────────────────────────────────────────────────┘
Each layer depends only on layers below it, with no cycles. The consequence you can rely on: the model does not know about file formats, and the formula engine does not know about rendering. A bug in XLSX writing cannot change how a formula evaluates.
The engine
Rust, organised as a Cargo workspace:
| Crate | Responsibility |
|---|---|
axyra-sheets-model |
The workbook model — sheets, cells, ranges, styles, charts, pivot tables. Includes both the row-oriented and columnar storage backends. |
axyra-sheets-formula |
Formula parsing and evaluation, the function library, dependency tracking, spill |
axyra-sheets-format |
Number and date format codes, parsing user input |
axyra-sheets-ooxml |
XLSX / XLSM / XLSB reading and writing; ODS; encryption |
axyra-sheets-xls |
Legacy BIFF8 .xls |
axyra-sheets-csv |
CSV import with type sniffing, and export |
axyra-sheets-json |
JSON import and export of sheet data as row objects |
axyra-sheets-html |
HTML export |
axyra-sheets-render |
Page layout, PDF, images, SVG, fonts, chart drawing |
axyra-sheets-signature |
OPC package digital signatures |
axyra-sheets-license |
Signed license tokens and enforcement |
axyra-sheets-ffi-jni |
The JNI bridge the Java library binds to |
Book is the model’s hub — the type nearly everything else reaches through, and
the reason Workbook is the root of the Java API too.
The JNI boundary
This is the part with practical consequences.
The Java API is a thin, typed layer. A Workbook holds a native handle;
Sheet, Range, and Cell are lightweight views that carry coordinates, not
data. Nothing is mirrored on the Java side.
That means:
- Every call crosses the boundary. A crossing is cheap but not free, so a
loop over 100,000 cells makes 100,000 crossings.
Range.values()makes one. This is why the bulk accessors exist and why they are usually several times faster — see Cells and Ranges. - Structured values cross as JSON. Styles, charts, pivot definitions, and filters are serialised rather than mapped field by field, which is why the library depends on Jackson. It also means these objects are cheap to cache on the Java side and comparatively expensive to set in a tight loop.
- Views are only valid while the workbook is open. Closing a workbook frees
the native model; using a derived
Sheet,Range, orCellafterwards throwsIllegalStateException. - Native memory sits outside the JVM heap, so
-Xmxdoes not bound it and the garbage collector does not reclaim it. Closing workbooks is not optional.
Modelled versus preserved
The engine distinguishes two kinds of content, and the distinction shows up throughout the documentation:
Modelled content is parsed into the model, computed where applicable, adjusted by structural edits, written back, and rendered. Formulas, styles, charts, pivot tables, conditional formats, and drawings are modelled.
Preserved content is carried through a round trip byte-for-byte without being interpreted. VBA projects, ActiveX controls, custom XML parts, OLE embeddings, and unknown extension lists are preserved.
Preservation is what lets a .xlsm keep its macros, and what lets a workbook
using an Excel feature newer than your build survive a round trip. It is not the
same as support: a preserved part will not be recalculated, rendered, or adjusted
when you insert a row. If a feature matters to your application logic, confirm
that it is modelled.
Correctness methodology
Behaviour is derived from measurement rather than from specification reading. The
engine’s test suite compares its output against Microsoft Excel’s actual
behaviour on generated cases, and the derived rules are what the implementation
targets. This is why the documentation prefers Functions.list() over a printed
function list, and why the honest answer to “does it handle X exactly like
Excel?” is a test against your files.
Relationship to Keikai Spreadsheet
Keikai Spreadsheet, the browser UI component, uses Axyra Sheets as its engine
since Keikai 7.0.0-Beta. Its own API (io.keikai.api.*) is unchanged and
remains supported. See
Axyra Sheets vs. Keikai Spreadsheet.