xlsx/preserve-workbook-filter-database

Excel and LibreOffice both persist the active AutoFilter range as a defined-name of the reserved name _xlnm._FilterDatabase scoped to the owning sheet. python-xlsx's DefinedNameList.from_tree strips all names whose owner is the reserved _xlnm. prefix, so the AutoFilter range is lost and Excel re-inserts a different one (or none) on reopen.

Library verdicts: python-xlsx: — xlsxjs: —

Metadata

Feature idxlsx/preserve-workbook-filter-database
Formatxlsx
Categoryround-trip
Spececma-376-5-part-1 § 18.2.5 definedName

XPath assertions

ID / partPredicateXPathpython-xlsxxlsxjs
filter-database-defined-name-preserved
xl/workbook.xml
exist
The _xlnm._FilterDatabase definedName must survive round-trip — it is the durable record of the sheet's active AutoFilter range.
//x:workbook/x:definedNames/x:definedName[@name='_xlnm._FilterDatabase']
filter-database-scope-preserved
xl/workbook.xml
exist
The localSheetId attribute must survive — a workbook-scoped filter range applies to a different UI affordance than a sheet-scoped one.
//x:workbook/x:definedNames/x:definedName[@name='_xlnm._FilterDatabase']/@localSheetId
filter-database-range-preserved
xl/workbook.xml
match = Sheet1!\$A\$1:\$A\$3351
The cell reference inside the definedName must survive verbatim. Any rewriting invalidates the AutoFilter range.
//x:workbook/x:definedNames/x:definedName[@name='_xlnm._FilterDatabase']

Render assertions

No render assertions declared.

Manifest (expanded)

{
  "$schema": "../manifest.schema.json",
  "id": "xlsx/preserve-workbook-filter-database",
  "title": "Preserve <definedName name=\"_xlnm._FilterDatabase\"> across round-trip",
  "format": "xlsx",
  "category": "round-trip",
  "summary": "Excel and LibreOffice both persist the active AutoFilter range as a defined-name of the reserved name _xlnm._FilterDatabase scoped to the owning sheet. python-xlsx's DefinedNameList.from_tree strips all names whose owner is the reserved _xlnm. prefix, so the AutoFilter range is lost and Excel re-inserts a different one (or none) on reopen.",
  "roles": [
    "authoring"
  ],
  "spec": {
    "source": "ecma-376-5-part-1",
    "clause": "18.2.5",
    "element": "definedName",
    "rnc_reference": "spec/ecma-376-5/part-1/rnc/SpreadsheetML.rnc",
    "xsd_reference": "spec/ecma-376-5/part-1/xsd/sml.xsd",
    "notes": "ECMA-376 Part 1 clause 18.2.5 (definedName) and 18.2.6 (definedNames) cover the workbook-level defined-name table. Clause 18.2.6 lists the reserved _xlnm.* names — _xlnm.Print_Area, _xlnm.Print_Titles, _xlnm.Criteria, _xlnm._FilterDatabase, _xlnm.Extract — every one of which is user-observable through a different UI affordance in Excel (print area, print-title rows, advanced-filter criteria, AutoFilter range, advanced-filter output). python-xlsx's src/xlsx/workbook/defined_name.py treats all _xlnm names as internal and filters them out of the round-trip, which silently breaks those UI affordances. Code: src/xlsx/workbook/defined_name.py::DefinedNameList (idx_base / from_tree filter logic)."
  },
  "fixtures": {
    "machine": "xlsx/preserve-workbook-filter-database"
  },
  "round_trip": {
    "library": "python-xlsx",
    "source_fixture": "xlsx/preserve-workbook-filter-database",
    "notes": "Source is a copy of python-xlsx's own bundled mac_date.xlsx test fixture — a small LibreOffice-authored workbook carrying a localSheetId=\"0\" _xlnm._FilterDatabase definedName pointing at Sheet1!$A$1:$A$3351."
  },
  "assertions": [
    {
      "id": "filter-database-defined-name-preserved",
      "part": "xl/workbook.xml",
      "namespaces": {
        "x": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
      },
      "xpath": "//x:workbook/x:definedNames/x:definedName[@name='_xlnm._FilterDatabase']",
      "must": "exist",
      "description": "The _xlnm._FilterDatabase definedName must survive round-trip — it is the durable record of the sheet's active AutoFilter range."
    },
    {
      "id": "filter-database-scope-preserved",
      "part": "xl/workbook.xml",
      "namespaces": {
        "x": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
      },
      "xpath": "//x:workbook/x:definedNames/x:definedName[@name='_xlnm._FilterDatabase']/@localSheetId",
      "must": "exist",
      "description": "The localSheetId attribute must survive — a workbook-scoped filter range applies to a different UI affordance than a sheet-scoped one."
    },
    {
      "id": "filter-database-range-preserved",
      "part": "xl/workbook.xml",
      "namespaces": {
        "x": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
      },
      "xpath": "//x:workbook/x:definedNames/x:definedName[@name='_xlnm._FilterDatabase']",
      "must": "match",
      "value": "Sheet1!\\$A\\$1:\\$A\\$3351",
      "description": "The cell reference inside the definedName must survive verbatim. Any rewriting invalidates the AutoFilter range."
    }
  ]
}

Fixture

Download preserve-workbook-filter-database.xlsx (4.8 KB)

Reference preview

No rendered reference is available for this case.

Spec notes

ECMA-376 Part 1 clause 18.2.5 (definedName) and 18.2.6 (definedNames) cover the workbook-level defined-name table. Clause 18.2.6 lists the reserved _xlnm.* names — _xlnm.Print_Area, _xlnm.Print_Titles, _xlnm.Criteria, _xlnm._FilterDatabase, _xlnm.Extract — every one of which is user-observable through a different UI affordance in Excel (print area, print-title rows, advanced-filter criteria, AutoFilter range, advanced-filter output). python-xlsx's src/xlsx/workbook/defined_name.py treats all _xlnm names as internal and filters them out of the round-trip, which silently breaks those UI affordances. Code: src/xlsx/workbook/defined_name.py::DefinedNameList (idx_base / from_tree filter logic).