Skip to content

feat: open and save .docm, .dotx and .dotm files - #1644

Open
BenoitMarchand wants to merge 2 commits into
python-openxml:masterfrom
BenoitMarchand:feat/212-363-docm-dotx-dotm
Open

BenoitMarchand wants to merge 2 commits into
python-openxml:masterfrom
BenoitMarchand:feat/212-363-docm-dotx-dotm

Conversation

@BenoitMarchand

Copy link
Copy Markdown

Summary

Open and save macro-enabled documents (.docm), templates (.dotx) and macro-enabled templates (.dotm). The package kind is preserved on save and the VBA project is carried along byte for byte.

Fixes #212, fixes #363. Addresses the file-format part of #284 (macros are preserved, not readable or editable).

Why another PR on this

Several PRs make the same code change (#673, #716, #1378, #1407). On #673 you said it could not be accepted without analysis documentation and tests, and that the analysis should cover how macros are stored in the package, document experiments showing they are preserved on save, and discuss where the approach may be insufficient or have unintended consequences. This PR adds those:

  • Analysis page docs/dev/analysis/features/document-kinds.rst:
    • how the four kinds differ (only the main document part content type),
    • how macros are stored (vbaProject.bin, vbaData.xml, relationships, optional signature, keymap and ActiveX parts) and why they round-trip: they load as generic Part objects,
    • the experiments and their results,
    • limits: macros are opaque, no conversion between kinds, extension/content-type mismatch, signatures, parts reachable only by relationship, templates edited in place.
  • Unit tests: docx.Document() is parametrized over the four content types.
  • Acceptance tests in api-open-document.feature:
    • open each kind,
    • save and reload, checking the content type is unchanged and vbaProject.bin is byte-identical.
    • The .docm/.dotm fixtures carry a real VBA project saved by Word.
  • User docs (documents.rst) and a HISTORY entry.

Change

  • opc/constants.py: add WML_DOCUMENT_MACRO_MAIN, WML_TEMPLATE_MAIN and WML_TEMPLATE_MACRO_MAIN.
  • __init__.py: map those content types to DocumentPart.
  • api.py: accept the four main-document content types.

No new public API. Behaviour for .docx is unchanged.

Experiments (summary; details on the analysis page)

Word-made .docm, .dotx and .dotm files covering most python-docx features (tables, images in 5 formats, comments, 4 sections with headers and footers) were used. The macro files contain a VBA module with a probe macro. Results:

  • python-docx 1.2.0 (PyPI): the .docx opens; the other three raise ValueError: ... is not a Word file.
  • This branch, after load, edit and save:
    • content type is unchanged;
    • no parts are lost or added;
    • vbaProject.bin and every image are byte-identical;
    • the VBA relationships are intact;
    • the VBA source extracted with oletools still contains the macros.
  • Back in Word: the saved files open without a repair prompt, and the probe macro runs and detects the paragraph added by python-docx.

Checks

  • pytest: 1612 passed
  • behave: 656 scenarios passed
  • ruff check and ruff format --check: clean
  • pyright: no new errors

🤖 Generated with Claude Code

BenoitMarchand and others added 2 commits November 9, 2026 23:31
Accept the main-document content types of macro-enabled documents (.docm),
templates (.dotx) and macro-enabled templates (.dotm) in addition to .docx.
They share the .docx package structure; only the content type of the main
document part differs. The package kind is preserved on save and the VBA
project part is carried along unchanged.

- add CONTENT_TYPE.WML_DOCUMENT_MACRO_MAIN, WML_TEMPLATE_MAIN and
  WML_TEMPLATE_MACRO_MAIN
- register DocumentPart for those content types
- accept them in docx.Document()
- unit tests, acceptance scenarios (open, save/reload, VBA part kept),
  user docs, analysis page, HISTORY entry

Fixes python-openxml#212, python-openxml#363. Addresses the file-format part of python-openxml#284 (macros are
preserved, not editable).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- analysis page: how macros are stored in the package, implementation,
  experiments showing macros are preserved on save, limits and unintended
  consequences
- doc-default.docm/.dotm fixtures now carry a real VBA project made by Word
  (PythonDocxCheck macro) instead of placeholder bytes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feature: can open .dotx files and perhaps change type Support for '.docm' OOXML format?

1 participant