Interoperability guide — Excel, ODS and Numbers

Conversions carry supported values and features through a common model. Inspect both read and write warnings before accepting a converted file.

Measured 2026-10-23T06:49:08.386839+00:00 / SwiftSheets 2.1.1 / Synthetic 48-feature whole-workbook write/read probe; library reader, not an application rendering measurement.

How to read this measurement

The kitchen-sink workbook is first saved in each format and read back to form the source file. Each source is then written to all three destinations. A feature lost before the source file was created is not counted as a loss of this conversion. A zero here is not a guarantee that arbitrary files, opaque parts or visual layout survive.

The probe detects 48 features, including presence of a formula, style, validation or print setting. It is binary: features rewritten in another shape can be absent from this profile without every aspect being dropped. For example, a Numbers pivot reads as an ordinary summary table, and a quote formula can become a cached value. One warning can describe several losses; warnings can also describe degradation without a binary loss.

See the feature matrix for separate read/write capabilities, and format support for per-feature restrictions. Charts, images and shapes have dedicated tests and are not part of this 48-feature kitchen-sink profile.

All nine directions

Source → destinationSource features detectedFeatures no longer detectedWrite warningsSuggested format
numbers → numbers23 / 4800—
numbers → ods23 / 4834xlsx
numbers → xlsx23 / 4834—
ods → numbers43 / 482321xlsx
ods → ods43 / 4801—
ods → xlsx43 / 4844—
xlsx → numbers41 / 482121xlsx
xlsx → ods41 / 4826xlsx
xlsx → xlsx41 / 4800—

Losses and warnings by direction

numbers → numbers

Features no longer detected: none.

  • No write warnings for this probe.
numbers → ods

Features no longer detected: cell controls, quote functions, several tables per sheet.

  • STOCK fetches live data and OpenFormula has no such function; the cached value is written, the way Numbers itself exports to Excel
  • 1 other table(s) not written: an ODS sheet holds a single table (write .numbers to keep them)
  • 1 other table(s) not written: an ODS sheet holds a single table (write .numbers to keep them)
  • 1 cell control(s) (checkbox, stepper, slider, rating) dropped: ODF has no cell controls — the value is kept (write .numbers to keep the control)
numbers → xlsx

Features no longer detected: cell controls, quote functions, several tables per sheet.

  • 1 cell control(s) (checkbox, stepper, slider, rating) dropped: Excel has no cell controls — the value is kept (write .numbers to keep the control)
  • 1 other table(s) not written: a worksheet holds a single grid (write .numbers to keep them)
  • 1 other table(s) not written: a worksheet holds a single grid (write .numbers to keep them)
  • STOCK fetches live data and Excel has no such function; the cached value is written, the way Numbers itself exports it
ods → numbers

Features no longer detected: CF colour scale, CF data bar, CF icon set, array formulas, auto-filter, calculation settings, consolidation, custom properties, detective arrows, filter criteria, hidden sheets, label ranges, outline groups, page breaks, pivot tables, print area, sheet defined names, sheet protection, sort state, structured tables, tab colour, workbook defined names, workbook protection.

  • 1 defined name(s) dropped: Numbers has no defined names
  • workbook protection is dropped: Numbers locks a document with a password, which this writer does not set
  • 1 custom document propert(ies) dropped: Numbers has no free-form document fields
  • 1 named table(s) dropped: every Numbers table is named, but its own header rows are not this frame
  • the auto-filter and its sort are dropped: a Numbers table filters and sorts through its own rules, which are not written
  • sheet protection is dropped: Numbers protects a whole document, not a sheet
  • 1 array formula(s) written as the anchor's formula and the covered cells' values: Numbers' own spill function does not survive its load-time recalculation, so the range is not kept (Appendix B.26)
  • the page number (&P) is drawn where Numbers draws it, in the centre of the footer
  • the print area, page breaks are dropped: Numbers prints a canvas, not a page grid
  • 1 sheet-scoped name(s) dropped: Numbers has no defined names
  • the tab colour is dropped: Numbers tabs have no colour
  • row / column grouping is dropped: Numbers groups by category, not by outline level
  • conditional format colorScale is dropped: Numbers has no rule of that kind (it drops the same ones when it imports an Excel file)
  • conditional format dataBar is dropped: Numbers has no rule of that kind (it drops the same ones when it imports an Excel file)
  • conditional format iconSet is dropped: Numbers has no rule of that kind (it drops the same ones when it imports an Excel file)
  • pivot table Summary is written as a Numbers pivot: Numbers recomputes it from the source rows, and reading the file back gives its summary as an ordinary table
  • Numbers has no hidden sheets; the sheet is visible
  • a calculation setting is dropped — a search condition is a regular expression here, and is not a regular expression there; only OpenDocument keeps it in the file
  • 1 label range(s) — headings usable in formulas is dropped: only OpenDocument has it
  • the stored consolidation definition is dropped: only OpenDocument has it
  • 1 cell(s) with tracing arrows is dropped: only OpenDocument has it
ods → ods

Features no longer detected: none.

  • pivot table Summary is written as an ODF data pilot: the layout travels, the numbers are recomputed when the file is opened
ods → xlsx

Features no longer detected: calculation settings, consolidation, detective arrows, label ranges.

  • a calculation setting is dropped — a search condition is a regular expression here, and is not a regular expression there; only OpenDocument keeps it in the file
  • 1 label range(s) — headings usable in formulas is dropped: only OpenDocument has it
  • the stored consolidation definition is dropped: only OpenDocument has it
  • 1 cell(s) with tracing arrows is dropped: only OpenDocument has it
xlsx → numbers

Features no longer detected: CF colour scale, CF data bar, CF icon set, array formulas, auto-filter, custom properties, filter criteria, hidden sheets, outline groups, page breaks, pivot tables, print area, protected ranges, scenarios, sheet defined names, sheet protection, sort state, structured tables, tab colour, workbook defined names, workbook protection.

  • 3 part(s) preserved from the xlsx file cannot be carried into Numbers
  • 1 defined name(s) dropped: Numbers has no defined names
  • workbook protection is dropped: Numbers locks a document with a password, which this writer does not set
  • 1 custom document propert(ies) dropped: Numbers has no free-form document fields
  • 1 named table(s) dropped: every Numbers table is named, but its own header rows are not this frame
  • the auto-filter and its sort are dropped: a Numbers table filters and sorts through its own rules, which are not written
  • sheet protection is dropped: Numbers protects a whole document, not a sheet
  • 1 protected range(s) dropped: Numbers has no window left open inside a protected sheet
  • 1 array formula(s) written as the anchor's formula and the covered cells' values: Numbers' own spill function does not survive its load-time recalculation, so the range is not kept (Appendix B.26)
  • 1 scenario(s) dropped: Numbers has no scenarios
  • the page number (&P) is drawn where Numbers draws it, in the centre of the footer
  • the print area, page breaks are dropped: Numbers prints a canvas, not a page grid
  • 1 sheet-scoped name(s) dropped: Numbers has no defined names
  • the tab colour is dropped: Numbers tabs have no colour
  • row / column grouping is dropped: Numbers groups by category, not by outline level
  • conditional format colorScale is dropped: Numbers has no rule of that kind (it drops the same ones when it imports an Excel file)
  • conditional format dataBar is dropped: Numbers has no rule of that kind (it drops the same ones when it imports an Excel file)
  • conditional format iconSet is dropped: Numbers has no rule of that kind (it drops the same ones when it imports an Excel file)
  • pivot table Summary is written as a Numbers pivot: Numbers recomputes it from the source rows, and reading the file back gives its summary as an ordinary table
  • pivot table Summary: its banded look is dropped; a Numbers pivot takes the document's table style
  • Numbers has no hidden sheets; the sheet is visible
xlsx → ods

Features no longer detected: protected ranges, scenarios.

  • pivot table Summary: its banded look is not carried into ODF, which has no pivot style
  • pivot table Summary is written as an ODF data pilot: the layout travels, the numbers are recomputed when the file is opened
  • 1 scenario(s) dropped: an ODF scenario is a whole shadow sheet, not a named set of input values, so it cannot be written without changing the sheet list
  • 1 protected range(s) dropped: ODF protects a whole table, with no windows left open in it
  • named table Sales written as an ODF database range: its banded-row style is not carried
  • 3 part(s) preserved from the xlsx file cannot be carried into ODS
xlsx → xlsx

Features no longer detected: none.

  • No write warnings for this probe.

Current conversion boundaries

Saving in the same format

FormatPreservation boundary
XLSX / XLSMWhole-workbook same-format saves retain uninterpreted parts byte for byte (F3). Modelled content is regenerated with equivalent meaning; VBA requires XLSM. This is not identical ZIP output.
ODSSupported content, including pictures and supported charts/shapes, is reconstructed (F2). Some opaque embedded objects remain unlinked and are reported. This is not full opaque-part preservation.
NumbersEvery save starts from the template. Supported content is regenerated; no F3 preservation.

Streaming carries values and formatting and has no opaque-part preservation.

Verification and reproducibility

CrossFormatConversionTests.everyLossIsNamedByItsOwnWarning asserts named warnings for all nine conversions. The three-generation tests check that repeated saves keep detected features and well-formed XML. The measurement collector requires a successful test run and all nine records before replacing its source.

python3 scripts/measure-interoperability.py
python3 scripts/build-interoperability-page.py
python3 scripts/build-interoperability-page.py --check
swift test --filter CrossFormatConversionTests
swift test --filter FormatSupportTests

Library round trips do not prove application rendering. Independent checks are provided by Tests/OpenpyxlParity/verify_with_openpyxl.py, Tests/NumbersParity/verify_with_numbers_parser.py and Tests/NumbersParity/verify_with_numbers_app.py; see maintenance for requirements and visual release checks. An unavailable judge is not a pass.

Historical defects and the 2026-08-27 sweep are recorded in the dated appendices of the implementation spec (B.22–B.23). They do not describe today's capability limits.