Files
craft-libs/crates/ods/README.md
Dylan M. Taylor 0d68632c9b Add craft-ods: OpenDocument spreadsheet tables on craft-odf (#990)
* 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-ods: OpenDocument spreadsheet tables on craft-odf

read() checks the spreadsheet mimetype, refuses an encrypted package, and reads the
tables of content.xml into sheets of cells that keep the file's terms: value type,
the raw value, displayed text, formula text, style name, covered cells, with
repeats expanded and merged ranges. Cell::value() gives the shown value, dates and
durations as serial numbers.

From GridCraft crates/xlsx/src/ods.rs and its tests (7e0d96d7), split from
GridCraft's document model and moved onto craft-odf and craft-xml's pull reader.
Options::only_sheet covers WordCraft's reader of one chosen sheet.
2026-11-11 20:16:51 -05:00

2.0 KiB
Raw Permalink Blame History

craft-ods

OpenDocument spreadsheets (.ods, .ots): the tables of content.xml (ODF 1.3 Part 3, section 9), on craft-odf for the package. Clean-room. No unsafe.

read(bytes, &Options) gives a Workbook of Sheets in document order. Each sheet has its table:name as written, its non-blank Cells by position (repeated rows and columns expanded) and its merged ranges. A cell keeps the file's terms:

Field From
value_type office:value-type, or calcext:value-type="error"
raw, currency the value attribute for the type, office:currency
text, paragraphs the displayed paragraphs, white space collapsed as ODF says, annotations left out
formula table:formula as written (of:=…), not translated
style table:style-name
covered a table:covered-table-cell

Cell::value() gives the shown value: numbers, booleans, strings, dates as serial numbers in the 1900 date system (date_serial) and durations in days (duration_days). It is None when the type's value is missing or unreadable, or for a formula without a cached result, so the caller chooses what to show.

read_content reads a content.xml on its own (a flat .fods goes through craft_odf::flat::to_package first). An encrypted package is Error::Encrypted; decrypt it with craft_odf::crypt::decrypt and read the result.

Hostile input

Options bounds the package (craft-odf), cells (1,000,000), merged ranges (100,000), text (64 MiB, repeats counted) and one cell's text or attribute (1 MiB), all over the whole workbook. Repeats and spans are checked against the 1,048,576 × 16,384 grid before anything is expanded; blank padding past the grid's edge is clipped, data past it is an error. The XML is read strictly (unbalanced markup, a document type declaration or an undefined entity fails the read), with craft-xml's depth and attribute limits. At most 1024 tables.

Options::only_sheet keeps one sheet's cells and lists the others by name.