Skip to content

Read OpenDocument spreadsheets (.ods) #13

Description

@vaceslav

After the first release, once it is stable. OpenDocument is the native format of LibreOffice/OpenOffice and is increasingly required in public administration across Germany and the EU, so files will arrive in it.

It fits the architecture as one more cursor behind ITabularCursor; analysis, mapping and import do not change. Rough size: a day or two including tests.

Why it is simpler than xlsx

  • Types are explicit per cell: office:value-type (float, percentage, currency, date, time, boolean, string) with office:value / office:date-value (ISO) / office:boolean-value — no number-format guessing, no styles lookup, no 1900/1904 epoch.
  • No shared-string table: text is inline in the cell.
  • Detected from content like the others: a zip whose first entry mimetype reads application/vnd.oasis.opendocument.spreadsheet.
  • SheetScanner already strips prefixes (table:, office:); its kept-attribute set (today r, t, s) needs to become configurable.

The traps

  • Repeat attributes. table:number-columns-repeated / table:number-rows-repeated — LibreOffice writes "the next 1,048,000 rows are empty" as one element. Never expand literally: represent empty repeats lazily, drop trailing empty repeats, and add a bound to the guide's Bounds table (it is also an attack vector).
  • All sheets live in one content.xml. Reading sheet 3 means scanning past 1 and 2; forward reading is fine, there is no random access per sheet.
  • Cell text assembly: text:p paragraphs (joined with a line break), nested text:span, text:s c="n" (n spaces), text:tab, text:line-break; annotations (office:annotation) excluded from the value.
  • Covered cells of merges (table:covered-table-cell) count as empty cells in their position.
  • Formulas: use the cached value, as for xlsx.
  • Hidden sheets/rows, table:table-header-rows, flat ODS (.fods) — decide in or out.
  • TabularFormat.Ods, TabularFile.Detect/Open, docs and README format list.

How to verify

Differential, as in #8: convert xlsx fixtures and other readers' corpora to ods with LibreOffice (soffice --headless --convert-to ods), read both through TriasDev.Tabular and compare cell by cell; add hand-built minimal fixtures for each trap above. Benchmark on the large fixtures converted to ods (peak memory must stay flat despite content.xml holding every sheet).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions