Files
craft-libs/crates/xlsx/README.md
Dylan M. Taylorandkiwi4boy 119415f46f Add craft-xlsx: XLSX and XLSB part layer (workbook, strings, styles, streamed rows) (#976)
* Add craft-sheet: the cell positions, values and tables the spreadsheet formats share

craft-xls carried its own CellRef, Range, Value, CellError, Visibility, sheet-name
quoting, built-in number format table and indexed palette. craft-xlsx and craft-ods
need the same ones, so they move to a crate with no dependencies and craft-xls
re-exports them: an application gets one Value and one CellRef whichever file it read.

Added on the way: A1 parsing (CellRef::parse, Range::parse), Range::count and a1,
CellError::parse and the newer error values SpreadsheetML stores as text,
builtin_format_id for writers.

* Add craft-xlsx: the part layer of XLSX and XLSB workbooks

Package::open finds the workbook part through craft-opc and reads the workbook
part, shared strings (runs and phonetic readings), the styles tables as indexed
tables, and a worksheet's rows one at a time with the rest of the part as a tree.
Binary workbooks give the same workbook, strings, rows and merged cells from their
records. Every other part stays reachable through Package::opc.

From GridCraft crates/xlsx (7e0d96d7): read.rs, sheet_read.rs, styles.rs, xml.rs
(string items, xstring escapes), xlsb.rs and its tests, split from GridCraft's
document model.

* craft-xlsx: XLSB opens up to 4 million cells, records counted once over the workbook

Binary workbooks over 1 million cells were refused, a quarter of what .xls allows,
and an allowance of 5 million records per part refused ordinary files: Excel writes
four records per non-empty row besides the cells, and one BrtCellBlank for every
formatted empty cell. Cells are now 4 million over the workbook (also the most
shared strings), text 256 MiB, and records 40 million for every part together, as
in craft-xls.

Ported from storytold/gridcraft#3807.

---------

Co-authored-by: kiwi4boy <kiwi4boy@gmail.com>
2026-11-11 19:32:04 -05:00

42 lines
2.5 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# craft-xlsx
Excel workbooks: `.xlsx`, `.xlsm`, `.xltx`, `.xltm` (SpreadsheetML in an OPC package,
transitional and strict) and `.xlsb` (the same package with binary parts). Clean-room, from
ECMA-376 Part 1 (SpreadsheetML), [MS-XLSB] and observed files. No `unsafe`.
This is the part layer. `Package::open` opens the container through `craft-opc` and reads:
| Call | Gives |
|---|---|
| `workbook()` | `Workbook`: sheets in tab order (name, id, visibility, kind, part), the 1904 date flag, defined names, the active tab, and the whole part as a tree |
| `shared_strings()` | `StringItem`s: text, formatted runs, phonetic readings |
| `styles()` | `Styles`: number formats, fonts, fills, borders, cell and cell-style formats, named styles, differential formats, the indexed palette, as indexed tables |
| `sheet(entry, each)` | each `Row` of `Cell`s to a callback, then a `SheetPart`: the rest of the worksheet as a tree, its relationships, columns and merged cells |
| `opc()`, `read_xml()`, `optional_xml()`, `rels()` | any other part |
A cell keeps the file's terms: a shared-string index, a format index, the formula text as the
file spells it, value and cell metadata indexes. `CellValue::resolve` gives the value it shows.
Shared formulas are not expanded and formulas are not parsed: that needs a formula grammar.
A binary workbook gives the same `Workbook`, strings, rows and merged cells, with saved values
only: its formulas are token streams that are not decoded, and its styles are not read (each
cell keeps its format index).
## Hostile input
- `Limits.package`: ZIP entries, bytes per part and in all (`craft-opc`).
- `Limits.xml`: one XML part. Rows and shared strings are streamed, so this bounds one row, one
string and what is left of a part, not a sheet's length.
- `Limits.binary_records`, `binary_cells`, `binary_text`: a binary workbook, over all its parts
(40 million records, 4 million cells and as many shared strings, 256 MiB of text, as
`craft-xls` allows). Fixed caps: 1024 sheets, 100,000 merged ranges per sheet, 64 nested
extension blocks.
- Cells and rows outside the 1,048,576 × 16,384 grid are dropped and counted.
SpreadsheetML is read leniently: a damaged optional part is a warning, a damaged worksheet keeps
the rows before the damage. A binary part that does not parse fails the read, since skipping a
record would lose data without a trace.
Shared with `craft-xls` and `craft-ods` through `craft-sheet`: `CellRef`, `Range`, `Value`,
`CellError`, `Visibility`, sheet-name quoting, built-in number formats and the palette.