Skip to content

Compatibility Matrix

Last rendered: 2026-09-29 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) are stable identifiers for tracked compatibility work.

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

To try the supported rows on your own workbook, install WolfXL with the quickstart. openpyxl alternatives, measured compares WolfXL with openpyxl and four other Python Excel libraries on committed benchmark receipts.

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.