mirror of
https://github.com/storytold/craft-libs.git
synced 2026-11-12 08:52:32 +00:00
* 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.
38 lines
2.0 KiB
Markdown
38 lines
2.0 KiB
Markdown
# 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 `Sheet`s in document order. Each sheet has its
|
||
`table:name` as written, its non-blank `Cell`s 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.
|