Skip to content

Compatibility Matrix

Last rendered: 2026-07-07 from docs/migration/_compat_spec.py. Do not edit this file by hand; run python scripts/render_compat_matrix.py.

This page is the public scoreboard for wolfxl's openpyxl-API compatibility. Each row maps an openpyxl idiom to its wolfxl equivalent and the current implementation status. Gap IDs (e.g. G11) correspond to rows in the internal Plans/openpyxl-parity-program.md, where the work to close them is sequenced into sprints.

Status legend

Symbol Meaning
โœ… Supported Implemented and covered by tests / fixtures.
๐ŸŸก Partial Common case works; edge cases tracked under a gap ID.
โŒ Not Yet Not implemented; tracked under a gap ID.
โ›” Out of Scope Explicitly excluded from the roadmap.

Totals

  • โœ… Supported: 76 / 83
  • ๐ŸŸก Partial: 0 / 83
  • โŒ Not Yet: 0 / 83
  • โ›” Out of Scope: 7 / 83

Workbook + Worksheet

openpyxl wolfxl Status Gap Notes
Workbook() wolfxl.Workbook() โœ… Supported Write-mode default.
load_workbook(path) wolfxl.load_workbook(path) โœ… Supported
load_workbook(path, data_only=True) wolfxl.load_workbook(path, data_only=True) โœ… Supported
Implicit (full DOM rewrite) wolfxl.load_workbook(path, modify=True) โœ… Supported Surgical patcher; faster than DOM rewrite.
load_workbook(path, read_only=True) wolfxl.load_workbook(path, read_only=True) โœ… Supported Streaming reads (auto-engages > 50k rows).
wb.save(path) wb.save(path) โœ… Supported Eager workbooks can be edited and saved repeatedly; write_only=True remains consumed-on-save like openpyxl.
wb["Sheet"], wb.active, wb.sheetnames wb["Sheet"], wb.active, wb.sheetnames โœ… Supported
wb.create_sheet(title) wb.create_sheet(title) โœ… Supported
wb.create_sheet(title, index=...) on loaded workbook wb.create_sheet(title, index=...) on modify=True workbook โœ… Supported Modify-mode blank sheet creation updates workbook.xml, workbook rels, content-types, tab order, and accepts cell edits before save.
wb.remove(ws) on loaded workbook wb.remove(ws) on modify=True workbook โœ… Supported Modify-mode sheet removal prunes the workbook tab, workbook rel, worksheet part, local defined-name indexes, and reachable sheet subgraph parts.
ws.title = 'Renamed' on loaded workbook ws.title = 'Renamed' on modify=True workbook โœ… Supported Modify-mode sheet title changes update workbook.xml and subsequent queued sheet mutations target the renamed tab.
wb.copy_worksheet(ws) wb.copy_worksheet(ws) โœ… Supported Diverges from openpyxl in 5 documented ways (always more preservation).

Cell + style API

openpyxl wolfxl Status Gap Notes
ws["A1"].value, ws.cell(r, c).value ws["A1"].value, ws.cell(r, c).value โœ… Supported
cell.font / fill / border / alignment / number_format cell.font / fill / border / alignment / number_format โœ… Supported All five attributes (plus protection and border) round-trip together on one cell. Python flush layer merges format and border keys into a single dict so the native writer interns one combined xf record, instead of minting two ids that overwrite each other.
Border(diagonal=Side(...), diagonalUp=True) Border(diagonal=Side(...), diagonalUp=True) โœ… Supported Round-trips through both write mode and modify mode; diagonalUp/diagonalDown attrs and the child of persist via the patcher's BorderSpec and the writer's intern path.
cell.protection = Protection(...) cell.protection = Protection(...) โœ… Supported Round-trips through wolfxl reload; locked/hidden flags persist via child of with applyProtection="1".
NamedStyle(name=...) + wb.add_named_style(...) NamedStyle(name=...) + wb.add_named_style(...) โœ… Supported cell.style binds a registered NamedStyle and round-trips through cellStyleXfs/cellStyles + the xfId attr on ; reader resurfaces the name via cell.style.
GradientFill(stop=(...)) GradientFill(stop=(...)) โœ… Supported GradientFill round-trips: writer emits with type/degree/path attrs and ordered stops; reader parses gradient back into Python GradientFill via the format dict's gradient sub-dict.

Charts

openpyxl wolfxl Status Gap Notes
BarChart / LineChart / PieChart / DoughnutChart BarChart / LineChart / PieChart / DoughnutChart โœ… Supported
AreaChart / ScatterChart / BubbleChart / RadarChart AreaChart / ScatterChart / BubbleChart / RadarChart โœ… Supported
BarChart3D / LineChart3D / PieChart3D / AreaChart3D BarChart3D / LineChart3D / PieChart3D / AreaChart3D โœ… Supported
SurfaceChart / SurfaceChart3D / StockChart / ProjectedPieChart SurfaceChart / SurfaceChart3D / StockChart / ProjectedPieChart โœ… Supported
ws.add_chart / remove_chart / replace_chart ws.add_chart / remove_chart / replace_chart โœ… Supported Covers pending charts plus source-loaded worksheet chart removal, replacement, and title edits in modify mode.
wb.create_chartsheet(...).add_chart(chart) wb.create_chartsheet(...).add_chart(chart) โœ… Supported Chartsheet authoring emits chartsheet, drawing, chart, rels, and content-type parts that openpyxl reloads; existing chartsheet tabs load back as workbook.chartsheets rather than worksheets.
bar + line on shared category axis with secondary value axis bar + line on shared category axis with secondary value axis โœ… Supported Combination charts ship as a multi-family <plotArea> (RFC-069 ยง6) for real Excel/LibreOffice rendering, plus per-family standalone shadow chartspaces parked at row 1048576 so openpyxl's reader exposes each family as a distinct ws._charts entry without the shadows visually overlapping the real combo. Secondary value axis (right side) honored when line.y_axis.crosses='max' and line.y_axis.axId is set. Closes G15.
data label + axis label rich-text runs data label + axis label rich-text runs โœ… Supported G10 Data label <c:txPr> runs and axis-title rich text round-trip end-to-end (G10).
pivot chart with per-point overrides pivot chart with per-point overrides โœ… Supported Per-point <c:dPt> overrides round-trip through openpyxl on pivot-source charts (G16). Bar/line/scatter all share the same dict bridge: Series.dPt -> data_points -> Rust DataPoint -> <c:dPt> with <c:spPr>. Pivot vs non-pivot only differ in the chart-level <c:pivotSource> block.

Pivot tables

openpyxl wolfxl Status Gap Notes
PivotCache + PivotTable construction wolfxl.pivot.PivotCache + PivotTable โœ… Supported v2.0 ships pre-aggregated records emit (no refresh-on-open required).
chart.pivot_source = pt chart.pivot_source = pt โœ… Supported
edit existing pivot's source range, field order, etc. edit existing pivot source + layout fields โœ… Supported Source-range mutation is supported; layout edits that change cache semantics stamp refresh-on-open rather than regenerating pivot cache records.
edit existing pivot row/column fields PivotTableHandle.row_fields / column_fields โœ… Supported Mutates existing pivot table layout XML and marks the linked cache refresh-on-open.
edit existing pivot page field filter PivotTableHandle.page_fields / set_filter โœ… Supported
edit existing pivot data-field aggregation PivotTableHandle.data_fields / set_aggregation โœ… Supported
copy_worksheet of pivot-bearing sheet (drops in openpyxl) copy_worksheet of pivot-bearing sheet (deep-clone) โœ… Supported

Images + drawings

openpyxl wolfxl Status Gap Notes
Image("logo.png") + ws.add_image(img, "B5") Image("logo.png") + ws.add_image(img, "B5") โœ… Supported
ws.replace_image / remove_image ws.replace_image / remove_image โœ… Supported

Worksheet structural ops

openpyxl wolfxl Status Gap Notes
ws.insert_rows / delete_rows ws.insert_rows / delete_rows โœ… Supported
ws.insert_cols / delete_cols ws.insert_cols / delete_cols โœ… Supported
ws.move_range(range, rows, cols) ws.move_range(range, rows, cols) โœ… Supported

Modify-mode mutations

openpyxl wolfxl Status Gap Notes
wb.properties.title = ... wb.properties.title = ... โœ… Supported
wb.defined_names[name] = DefinedName(...) wb.defined_names[name] = DefinedName(...) โœ… Supported
ws.add_table(Table(...)) ws.add_table(Table(...)) โœ… Supported
ws.data_validations.append(...) ws.data_validations.append(...) โœ… Supported

Read-side parity

openpyxl wolfxl Status Gap Notes
load_workbook(path) load_workbook(path) โœ… Supported
not supported in openpyxl native BIFF12; values, cached formulas, read-side styles โœ… Supported
not supported in openpyxl calamine; value-only, styles raise โ›” Out of Scope Style accessors raise; values + formulas read. openpyxl does not support this surface; tracked as a wolfxl-extra roadmap item, not an openpyxl-parity gap.
not supported in openpyxl not supported (out of scope) โ›” Out of Scope G27

Utility functions

openpyxl wolfxl Status Gap Notes
openpyxl.utils.get_column_letter wolfxl.utils.cell.get_column_letter โœ… Supported
openpyxl.utils.column_index_from_string wolfxl.utils.cell.column_index_from_string โœ… Supported
openpyxl.utils.range_boundaries wolfxl.utils.cell.range_boundaries โœ… Supported
openpyxl.utils.coordinate_to_tuple wolfxl.utils.cell.coordinate_to_tuple โœ… Supported

Streaming write (write_only=True)

openpyxl wolfxl Status Gap Notes
Workbook(write_only=True) wolfxl.Workbook(write_only=True) โœ… Supported Bounded-memory streaming append-only path (G20 / RFC-073). Per-sheet temp files splice into the <sheetData> slot; row data scales O(rows on disk), not O(rows in RAM). SST and styles still grow in-memory as in openpyxl's lxml.xmlfile model.

Protection

openpyxl wolfxl Status Gap Notes
ws.protection = SheetProtection(...) ws.protection = SheetProtection(...) โœ… Supported Round-trips through openpyxl reload (sheet flag, formatCells override, password hash).
wb.security = WorkbookProtection(...) wb.security = WorkbookProtection(...) โœ… Supported camelCase aliases (lockStructure, workbookPassword, etc.) accepted alongside snake_case; round-trips through openpyxl reload.
openpyxl wolfxl Status Gap Notes
wb._external_links + xl/externalLinks/* parts wb._external_links + xl/externalLinks/* parts โœ… Supported Inspection (target / sheet_names / cached_data), opaque modify-mode preservation when unchanged, and append/remove/edit authoring. keep_links=False strips preserved source links, and file-like/bytes-backed xlsx reads expose the same collection.
append/remove/edit external workbook links wb._external_links append/remove/update_target โœ… Supported Authoring emits externalLink parts, workbook rels/references, content-types, and per-link rels. Cached data is preserved when provided but linked workbooks are not dereferenced.

VBA macros

openpyxl wolfxl Status Gap Notes
.xlsm preserved on read+write .xlsm preserved on modify-mode save โœ… Supported
workbook.vba_archive (read-only inspection) workbook.vba_archive (read-only inspection) โœ… Supported v1.0: modify-mode loads only; returns raw xl/vbaProject.bin bytes. No authoring API (tracked under G28).
not supported in openpyxl macro authoring from Python โ›” Out of Scope G28 Decision-gated (S11). openpyxl does not support this surface; tracked as a wolfxl-extra roadmap item, not an openpyxl-parity gap.

Legacy formats (.xlsb / .xls / .ods)

openpyxl wolfxl Status Gap Notes
not supported write.xlsb`` โ›” Out of Scope G25 Decision-gated (S9). openpyxl does not support this surface; tracked as a wolfxl-extra roadmap item, not an openpyxl-parity gap.
not supported write.xls`` โ›” Out of Scope G26 Decision-gated (S9). openpyxl does not support this surface; tracked as a wolfxl-extra roadmap item, not an openpyxl-parity gap.
not supported read+write.ods`` โ›” Out of Scope G27 Decision-gated (S10). openpyxl does not support this surface; tracked as a wolfxl-extra roadmap item, not an openpyxl-parity gap.

Comments

openpyxl wolfxl Status Gap Notes
cell.comment = Comment(text, author) cell.comment = Comment(text, author) โœ… Supported
threaded comment write + modify (xl/threadedComments) threaded comment write + modify (xl/threadedComments) โœ… Supported

Rich text

openpyxl wolfxl Status Gap Notes
cell.value = CellRichText(...) cell.value = CellRichText(...) โœ… Supported
ws.oddHeader / oddFooter rich-text runs ws.oddHeader / oddFooter rich-text runs โœ… Supported

Conditional formatting

openpyxl wolfxl Status Gap Notes
cellIs / containsText / expression / colorScale (basic) cellIs / containsText / expression / colorScale (basic) โœ… Supported
IconSetRule (3 / 4 / 5 icons + percentile / number ladders) IconSetRule (3 / 4 / 5 icons + percentile / number ladders) โœ… Supported
DataBarRule (gradient + solid; min / max / percent / formula) DataBarRule (gradient + solid; min / max / percent / formula) โœ… Supported Round-trips through openpyxl reload; secondary probes cover cfvo edge cases and minLength/maxLength.
DataBarRule with percent / num / formula cfvo + showValue=False DataBarRule with percent / num / formula cfvo + showValue=False โœ… Supported
ColorScaleRule with 3-stop, percentile / formula / number cfvo ColorScaleRule with 3-stop, percentile / formula / number cfvo โœ… Supported
stopIfTrue + explicit priority + dxf integration stopIfTrue + explicit priority + dxf integration โœ… Supported

Defined names

openpyxl wolfxl Status Gap Notes
wb.defined_names + DefinedName(name=, value=) wb.defined_names + DefinedName(name=, value=) โœ… Supported
full ECMA-376 ยง18.2.5 attribute surface (13 attrs) full ECMA-376 ยง18.2.5 attribute surface (13 attrs) โœ… Supported
openpyxl wolfxl Status Gap Notes
ws.print_options / page_setup / page_margins / print_title_rows ws.print_options / page_setup / page_margins / print_title_rows โœ… Supported
full PageSetup / PrintOptions surface (~30 attrs) full PageSetup / PrintOptions surface (~30 attrs) โœ… Supported

Array + data-table formulas

openpyxl wolfxl Status Gap Notes
ArrayFormula(ref, text) ArrayFormula(ref, text) โœ… Supported Round-trips through openpyxl reload (ref + text preserved as openpyxl ArrayFormula).
DataTableFormula(...) DataTableFormula(...) โœ… Supported
Worksheet.array_formulae + DataTableFormula del flags Worksheet.array_formulae + DataTableFormula del flags โœ… Supported openpyxl 3.1.5 exposes array/spill ranges via Worksheet.array_formulae; formula_attributes is not part of the supported reference surface.

Calc chain

openpyxl wolfxl Status Gap Notes
calcChain rebuild on modify calcChain rebuild on modify โœ… Supported
cross-sheet calc-chain ordering, deleted-cell pruning cross-sheet calc-chain ordering, deleted-cell pruning โœ… Supported Rebuild scans post-mutation sheet XML across tab order, prunes stale refs, and preserves a source calcChain extLst when emitting a non-empty chain.

Slicers

openpyxl wolfxl Status Gap Notes
Slicer + SlicerCache wired to a PivotCache Slicer + SlicerCache wired to a PivotCache โœ… Supported
Slicer outside pivot context (table-driven, etc.) Slicer outside pivot context (table-driven, etc.) โ›” Out of Scope G21 openpyxl 3.1.5 exposes no public slicer modules/classes or table-driven slicer authoring API; tracked as a possible wolfxl-extra, not an openpyxl parity gap.

How this page is maintained

This file is generated from _compat_spec.py. To update a row, edit the spec module and run:

python scripts/render_compat_matrix.py

The accompanying tests/test_openpyxl_compat_oracle.py harness imports ENTRIES from the same module and uses each entry's probe field to drive a live test. Adding a new probe means adding a new entry in the spec and a matching probe function in the harness.