Repository navigation
Description
Styles.copy_style_from() (#87) moves one style between documents, resolving its w:basedOn / w:next / w:link closure and carrying numbering across. That is the hard part and it is done. What is missing is everything built on it.
Two operations, both currently written by hand by anyone doing document generation from a corporate template:
Import
document.styles.import_from("house-template.dotx") # everything
document.styles.import_from(other_document, names=["Quote", "Caption"])
document.styles.import_from(tmpl, overwrite=True) # replace same-namedStyles.import_from(source, names=None, *, overwrite=False, include_latent=False)sourceaccepting a path, a file-like object or an openDocument— a.dotxis the common case and already opensnames=Nonemeaning every style defined in the sourceoverwrite=Falseskipping names already present,Truereplacing them; returning what it did either way, because "why is my heading still the wrong colour" is otherwise unanswerable
The naive loop over copy_style_from() is O(n) full closure resolutions with repeated work and repeated numbering imports. Bulk import should resolve the whole closure once.
Extract
document.styles.extract("styles-only.docx", names=["Quote", "Caption"])
xml = document.styles.extract_xml(names=[...])Write the selected styles, with their closure, to a standalone document — a styles-only .docx or .dotx that is a valid Word template. That makes the round trip work: pull the styles you like out of a document someone sent you, keep them as a template, apply them to everything you generate.
extract_xml() returning the styles.xml bytes covers the case where the caller wants to diff or version-control them.
Why this matters here
It is the practical answer to the part of #23 that needs Word. If a caller has any Word-authored document containing the styles they need, import_from() gets those authentic definitions into their document without anyone hand-authoring w:style elements or guessing at Word's default spacing values.
The same trick applies to the library's own gap: the repo already contains Word-authored definitions of Hyperlink, CommentText and CommentReference in features/steps/test_files/comments-rich-para.docx — see #117.
Watch out for
w:styleIdcollisions between source and destination when the names differ — two documents can each have aStyle1meaning different things. Remap ids on import; do not assume they are stable.- Numbering: importing a style whose
w:pPr/w:numPrnames anumIdrequires importing thew:numand itsw:abstractNum, renumbered into the destination's id space.copy_style_from()does this for one style; make sure the bulk path does not double-import shared abstract numbering. - Theme-dependent values. A style specifying
w:asciiTheme="minorHAnsi"renders with the destination's theme after import, which may not be what the caller saw in the source. Worth a documented note; resolving it properly needs Expose the theme part and resolve theme typefaces to real font names #96. include_latentdefaulting toFalse: importing the source'sw:latentStylesblock wholesale changes which styles appear in Word's gallery for the destination, which is rarely what was asked for.
Activity
toxicphreAK commentedon Aug 5, 2026
Landed in #139.
Styles.import_from(),Styles.extract()andStyles.extract_xml().import_from()takes a path, a stream or an openDocumentand reportsadded/replaced/skippedper name. The extract prunes the bundled template's own styles first, or the result would be mostly those.include_latentdefaults toFalse. The theme-font caveat is documented on the method.