Workbooks
Table of Contents
The xlsx plugin of getkalem/plugins opens Excel workbooks as
themselves: the file is a ZIP package of SpreadsheetML parts, and the
plugin reads, edits and writes those parts, never a conversion of
them. Kalem shows each sheet as a grid, through the plugin API's grid
interface, and draws the charts, pictures, sparklines and slicers the
plugin describes (see Plugins). The plugin is installed from the plugin list, or when a workbook is
first opened; its README and its work list (plugins/xlsx/xlsx_todo.md) are kept with
it, and Kalem's own lists of what an everyday Excel user reaches for
are docs/history/excel_todo.md, excel_todo2.md and
docs/excel_todo3.md.
1. The standard and the oracle
- The standard is ECMA-376 part 1, SpreadsheetML, with the parts
Excel 2010 and later add (sparklines, slicers, threaded comments,
the newer functions'
_xlfn.prefixes) read and written as Excel writes them. - The oracle is Excel itself: "as Excel writes it" is how each edit is written, and Excel refusing an edit (inside a merged cell, part of an array formula, a locked cell of a protected sheet) refuses it in Kalem too. Excel opening edited files without a repair prompt is checked by hand.
- LibreOffice Calc is the second oracle, by hand:
soffice --convert-to csvshows the results of recalculated files. LibreOffice does not recalculate on open, which is why Kalem writes the new results of the formulas an edit changes. - The corpus is made by
tests/corpus/make.py: workbooks written by openpyxl and the same saved again by LibreOffice Calc, as.xlsx,.odsand.xls. The tests check that each.xlsxsaves back byte for byte, that the.odsand.xlsread as the same workbook, which parts and cells an edit changes, values through their formats, and the formula engine.
2. Which files
.xlsx, .xlsm, .xltx and .xltm are opened and edited as
themselves. A workbook encrypted with a password to open (Excel 2007's
standard encryption, Excel 2010's agile one) asks for it. .xls,
.xlsb and .ods are read through calamine and shown. An .ods is
converted to a workbook as it opens, and Kalem asks before saving it
back as .ods. An .xls or .xlsb is shown read only: the plugin
never writes them, and Save As .xlsx or .ods makes a new workbook
to edit.
3. What is read
- Cells: values, shared and inline strings, formulas (shared
formulas expanded), number formats (dates and times, percent,
currency, fractions, scientific, sections and conditions; the
colors they give,
[Red]and[Color10]), fonts, fills (solid, pattern, gradient), borders, alignment, indent and rotation, theme colors, cell styles by name. - Sheets: merged cells, frozen and split panes, zoom, column widths, row heights, hidden rows, columns and sheets, outline levels, tab colors, the sheet view's gridlines and headings, page setup and its breaks.
- The workbook: defined names, tables with their styles and total rows, conditional formats (rules, data bars, color scales, icon sets), data validation, AutoFilter and sorts, notes and threaded comments, hyperlinks, protection, calculation options, scenarios.
- Objects: charts (column, bar, line, area, pie and doughnut, scatter, radar, bubble, stock, combinations on a secondary axis, trendlines, error bars, histograms and waterfalls), pivot tables and their caches, slicers, sparklines, pictures, shapes and text boxes, chart sheets.
- Macros: the VBA project's module sources ([MS-OVBA]); the project part is never rewritten.
4. What is shown
Each sheet is a tab of the grid, its cells drawn with their fonts,
fills, borders and alignment, notes and comments marked, frozen panes
kept still; charts, pictures and slicers float over the cells where
their anchors put them. The formula bar shows the cell as entered;
the status bar names the sheet and the selection, and sums a
selection of several cells: Average, Count and Sum, the Numerical
Count when some values are not numbers, then Min and Max (only the
Count when none is a number). The menus have
the workbook's commands where Excel has them (Format, Insert, the
menus Data, Formulas and Chart), the toolbar (in the window)
Excel's Home buttons and Insert Chart, and a right click on a cell what is there: a note's, a
link's, a list's, a table's or a pivot table's items. In the terminal
the grid is drawn with box lines, a number too wide for its column as
#.
5. What is edited
Every edit is the plugin's, written as Excel writes it, and undoes in
one step; the commands are the viewer.grid.* of the palette, F10
lists them by menu.
- Cells: typed as in Excel (
=starts a formula,'forces text,1,234.5,50%,2026-10-03and14:30are numbers given the format Excel would give them), filled down, right, as a series or by Flash Fill, cut, copied and pasted (Paste Special's values, formats, formulas, operations, Skip Blanks, transposed, linked), cleared, moved by dragging, found and replaced. - Formats: the font, the fill, alignment, wrapping, indent, rotation, borders and their lines, number formats, cell styles and the theme, Format Painter, Clear Formats.
- Rows, columns and sheets: inserted and deleted with every reference to them moved, as in Excel; hidden, grouped, sized (a height or width typed, fitted, stepped); sheets inserted, deleted, renamed, moved, copied (into another workbook too), hidden, colored.
- Data: sorts by values, colors and custom lists; AutoFilter's rules and Advanced Filter; Remove Duplicates, Text to Columns, validation, Subtotal, tables, Goal Seek, data tables and scenarios.
- Formulas: names defined, managed and created from a selection; precedents and dependents traced, formulas evaluated step by step, errors checked, the Watch Window.
- Objects: charts made and changed (kind, titles, legend, labels, axes, colors, trendlines, error bars, templates, moved to a chart sheet); pivot tables made, grouped, filtered and laid out; slicers, sparklines, pictures, shapes; notes and threaded comments; hyperlinks; protection of sheets and of the workbook's structure.
6. What is computed
The formula engine is IronCalc, in getkalem's fork, inside the plugin.
It is trusted cell by cell: before an edit it computes the whole
workbook, and only the cells whose result equals the one the file
stores get new results after an edit; the others an edit changed lose
their stored result, to be computed by Excel or LibreOffice when they open the
file. NOW() and TODAY() are computed in the local time zone.
Calculation is automatic, automatic except data tables, or manual, as
the workbook says; circular references are found, or computed
iteratively when the workbook asks. Since xlsx 0.0.10 a
formula calling a function the engine lacks (GETPIVOTDATA,
AGGREGATE, WEBSERVICE) enters the engine as its stored result, so
that the formulas reading it are computed from that result, and
HYPERLINK shows its friendly name.
7. Macros
A macro runs inside the plugin when it is asked for by name (Run
Macro, Alt+F8); event handlers are listed and never run by themselves.
The interpreter has VBA's language (procedures and functions, ByRef
and ByVal, optional, named and ParamArray arguments, arrays,
If, For, For Each, Do, Select Case, With, On Error) and
about 120 of its library functions, and Excel's object model for data:
Range, Cells, Rows, Columns, Offset, Resize, End,
CurrentRegion, Find, Copy, every worksheet function through
WorksheetFunction, Collection and Scripting.Dictionary, MsgBox
and InputBox as the editor's questions. A run undoes in one step.
Files, the network, Shell and other workbooks stop the macro with a
message naming the call and the line (a Declare is set aside and
listed in the run's report, and a call of what it declares stops the
macro); a budget of steps
and time stops an endless loop. Since xlsx 0.0.10 macros
also format cells (Font, Interior, Borders, NumberFormat,
alignment, widths, merging), rename and hide sheets, use Resume and
Resume Next in their handlers, and read and write FormulaR1C1.
8. What is written
A save without edits returns the file byte for byte. After an edit
only the edited parts are written; every other entry of the ZIP
archive (charts, pivot caches, drawings, pictures, the VBA project,
external links, printer settings, custom XML) is copied with its local
header. Within a sheet part only the cells, rows and elements an edit
changed are written again. An edit of a workbook that has formulas
sets calcPr fullCalcOnLoad, so that Excel computes the formulas
when it opens the file, and writes
the new results of the formulas the edit changed (the engine's, where
it is trusted) or drops their stored results; the calculation chain is
dropped when a formula is removed, as the standard allows and Excel
rebuilds it. A workbook opened with a password is saved encrypted
again with it.
9. Export and conversion
- Save As another workbook kind (
.xlsmas.xlsxdrops the VBA project, which a.xlsxmay not hold) or as.ods, written by the plugin; an encrypted workbook saved as.odsis not encrypted, as the message after the save says. - Save Sheet as CSV writes the sheet shown as Excel's CSV UTF-8 does; Export as CSV or Text writes Excel's other text types (semicolons, tabs, Windows-1254 and Windows-1252), the sheet shown or every visible sheet to its own file.
- Export to PDF and printing go through LaTeX, charts drawn as TikZ.
10. Known differences
- Rotated text is drawn slanted in the graphical editor and level in the terminal.
- A drawing prints whole on the page of its first cell.
- Histograms and waterfalls are drawn, not made; treemaps, sunbursts, funnels and box plots are placeholders.
- A pivot table's field is grouped one way (by months or by years, not both), and a pivot table has one column field.
- Rich text in a cell is shown in the cell's font, its runs joined; an edit of such a cell writes plain text.
- A workbook on the 1904 date system is not recalculated; dynamic array results are not recalculated and their anchor is not edited.
- A long macro or a full recalculation of a million cells runs in the editor's thread.
11. Not implemented
- Dynamic arrays spilling (
FILTER,SORT,UNIQUE,SEQUENCE,A1#),LETandLAMBDAresults that spill. - Links to other workbooks updated or broken; 3D references computed.
- The Accounting format's fill to the cell's width; Office 2016 charts made.
- Cells inserted on part of a row as an edit of its own (Kalem moves the cells below), grouped sheets, Allow Users to Edit Ranges.
- Macros adding, deleting and moving sheets, sorting and filtering, class modules, UserForms and events.
- Excel opening every edited file without a repair prompt, checked by hand.
12. Limits and performance
The plugin asks for 4 GB, the most a component can address: a sheet of a million rows of ten cells needs about 2. The undo history keeps the last hundred edits, as Excel does, sharing the sheets an edit leaves alone (since xlsx 0.0.10; fewer when they would hold more than a gigabyte).
Measured on 2026-10-10 on an Apple M1 Max, with the plugin's library
in a release build (tests/speed.rs): 100,000 cells are pasted in
0.39 s and cleared in 0.11 s; 3,000 rows are sorted in 0.28 s, and a
row inserted above them in 0.28 s. A sheet of a million cells (4.8 MB
as saved) is saved in 0.88 s, opened and read in 0.56 s and
recalculated in 1.0 s; a cell typed there takes 0.4 s, the engine
computing the workbook again. The component, run by Kalem, is slower
than the library by its WebAssembly.
13. Code and tests
- The plugin:
plugins/xlsxofgetkalem/plugins:workbook.rsandworkbook/(the workbook and its edits),sheet.rs,styles.rs,numfmt.rs,formula.rs(references moved),calc.rs(the engine),chart.rs,pivot.rs,conditional.rs,validation.rs,legacy.rs(calamine),macros/(the interpreter),viewer.rs(the plugin as Kalem's viewer); the Office layer it shares with the Word plugin incrates/ooxml. - Its tests:
tests/workbook.rs,tests/conformance.rs,tests/macros.rs,tests/legacy.rs, the measurements oftests/speed.rs, and each module's own. - Kalem's half: the interface in
crates/kalem-plugin/wit/grid.wit, the contract incrates/kalem-viewer, the grid's state and commands incrates/kalem-core/src/viewer.rs, its menus inmenus.rs, the grid drawn in both editors'viewer.rs; its tests in both editors'tests/workbook.rs.