docx_plus.styles.modify¶
Style creation, modification, application, removal, and reconciliation.
Field names for **properties kwargs match ResolvedFormatting
so cascade output round-trips back through the modifier without
translation.
Schema-strict child ordering for w:style, w:pPr, and w:rPr is
enforced internally — see ARCHITECTURE.md §3.
The Phase 3.5 remap surface — find_matching_style, remap_styles, and
ensure_style(match_existing=True) — is documented in
ARCHITECTURE.md §4.
docx_plus.styles.modify ¶
Style creation, modification, application, deletion — Word-native workflow.
The companion to :mod:docx_plus.styles.inspect. Where inspect reads the
cascade, this module writes the styles that drive it. The intent is to push
formatting changes through style definitions rather than scattering direct
formatting; SPEC §5 calls this the "Word-native" workflow.
Property kwargs accepted by :func:create_style and :func:modify_style use
the same field names as :class:~docx_plus.styles.inspect.ResolvedFormatting
so a value resolved by the inspector can be round-tripped back through the
modifier without translation. Schema-strict child ordering for CT_Style,
CT_PPr, and CT_RPr is enforced internally so the produced styles.xml
matches what Word writes.
StyleProxy ¶
Lightweight live wrapper around a <w:style> element.
The proxy holds a reference to the live element rather than a snapshot —
reads always reflect current state. Mutating methods delegate to
:func:modify_style so child-element ordering and toggle semantics stay
consistent. The :attr:element attribute is an escape hatch for callers
that need direct lxml access (SPEC §5).
Wrap an existing <w:style> element in doc.
Source code in docx_plus/styles/modify.py
style_type
property
¶
The style's w:type (paragraph/character/table/numbering).
next_style
property
¶
The style id Word applies to the paragraph after one styled with this.
linked_style
property
¶
The companion character style id from w:link, if any.
ui_priority
property
¶
The Word style-gallery sort priority from w:uiPriority.
modify ¶
delete ¶
StyleInfo
dataclass
¶
StyleInfo(
style_id: str,
name: str,
style_type: StyleType,
based_on: str | None = None,
is_default: bool = False,
is_latent: bool = False,
)
Lightweight summary of a style for :func:list_styles.
Attributes:
| Name | Type | Description |
|---|---|---|
style_id |
str
|
The |
name |
str
|
The |
style_type |
StyleType
|
|
based_on |
str | None
|
The id of the parent style in the basedOn chain, if any. |
is_default |
bool
|
True if the style carries |
is_latent |
bool
|
True only for entries returned with
|
StyleExistsError ¶
Bases: DocxPlusError
Raised by :func:create_style when the style id is already defined.
StyleNotFoundError ¶
Bases: DocxPlusError
Raised when an operation references a style id that does not exist.
StyleInUseError ¶
Bases: DocxPlusError
Raised by :func:delete_style when the style is referenced and force=False.
UnknownStylePropertyError ¶
Bases: DocxPlusError, TypeError
Raised when a property kwarg is not a recognised style property.
create_style ¶
create_style(
doc: Document,
style_id: str,
*,
style_type: StyleType = "paragraph",
name: str | None = None,
based_on: str | None = None,
next_style: str | None = None,
linked_style: str | None = None,
ui_priority: int = 99,
q_format: bool = False,
custom: bool = True,
**properties: Any,
) -> StyleProxy
Define a new style in doc.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc
|
Document
|
The python-docx :class: |
required |
style_id
|
str
|
Machine identifier ( |
required |
style_type
|
StyleType
|
|
'paragraph'
|
name
|
str | None
|
Display name. Defaults to |
None
|
based_on
|
str | None
|
Parent style id in the basedOn chain. |
None
|
next_style
|
str | None
|
Style applied to the paragraph that follows one styled
with this style (e.g. |
None
|
linked_style
|
str | None
|
Companion character style for a paragraph style (Word's
|
None
|
ui_priority
|
int
|
Sort priority in Word's style gallery (lower = higher). |
99
|
q_format
|
bool
|
Show in Word's quick-style gallery if True. |
False
|
custom
|
bool
|
Mark as a custom style ( |
True
|
**properties
|
Any
|
Any field name from :class: |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
StyleProxy
|
class: |
Raises:
| Type | Description |
|---|---|
StyleExistsError
|
If |
UnknownStylePropertyError
|
If |
Source code in docx_plus/styles/modify.py
modify_style ¶
modify_style(
doc: Document,
style_id: str,
*,
if_missing: Literal["raise", "create"] = "raise",
**properties: Any,
) -> StyleProxy
Update an existing style's properties in place.
Pass only the properties to change; others are preserved. Per SPEC §5,
toggle properties (bold, italic, …) treat True/False as
explicit settings (writing w:val="true"/"false") and None as
"clear the setting so XOR with the parent resumes". Non-toggle properties
treat None as "remove this property".
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc
|
Document
|
The document containing the style. |
required |
style_id
|
str
|
Identifier of the style to modify. |
required |
if_missing
|
Literal['raise', 'create']
|
|
'raise'
|
**properties
|
Any
|
Any field name from :class: |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
StyleProxy
|
class: |
Raises:
| Type | Description |
|---|---|
StyleNotFoundError
|
If |
UnknownStylePropertyError
|
If |
Source code in docx_plus/styles/modify.py
apply_style ¶
Apply a style by id to a paragraph, run, or cell.
Resolves the style id against the target's owning document and writes the
appropriate w:pStyle (paragraph), w:rStyle (run), or — for cells —
sets w:pStyle on every paragraph in the cell.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
target
|
Paragraph | Run | _Cell
|
A python-docx :class: |
required |
style_id
|
str
|
The id of an already-defined style. |
required |
Raises:
| Type | Description |
|---|---|
StyleNotFoundError
|
If |
Source code in docx_plus/styles/modify.py
delete_style ¶
Remove a style definition from doc.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc
|
Document
|
Document containing the style. |
required |
style_id
|
str
|
Identifier of the style to remove. |
required |
force
|
bool
|
If False (default), refuse to delete a style referenced by any
paragraph, run, table, or other style. If True, delete anyway —
Word will fall back to |
False
|
Raises:
| Type | Description |
|---|---|
StyleNotFoundError
|
If |
StyleInUseError
|
If |
Source code in docx_plus/styles/modify.py
ensure_style ¶
ensure_style(
doc: Document,
style_id: str,
*,
match_existing: bool = False,
**defaults_if_creating: Any,
) -> StyleProxy
Idempotent style materialisation.
If style_id is already defined, return a proxy without modifying it.
If it names a known built-in (Heading1, Title, ListParagraph, …),
materialise it from the built-in table — Word's defaults, not
defaults_if_creating. Otherwise create a custom style with
defaults_if_creating as the initial properties.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc
|
Document
|
Document to ensure the style on. |
required |
style_id
|
str
|
Identifier to ensure. |
required |
match_existing
|
bool
|
If True, before falling back to creation, search for
an existing style whose |
False
|
**defaults_if_creating
|
Any
|
Properties to use when creating a custom style. Ignored when materialising a known built-in (the user asked for the built-in; Word's defaults are what matters). |
{}
|
Returns:
| Name | Type | Description |
|---|---|---|
A |
StyleProxy
|
class: |
Source code in docx_plus/styles/modify.py
find_matching_style ¶
find_matching_style(
doc: Document, target_id: str, *, style_type: StyleType | None = None
) -> str | None
Find an existing style that fulfils the role of target_id.
Matches case/space-insensitively against both the w:styleId and
w:name of every defined style. Useful when a document uses a renamed
or differently-cased version of a built-in style ("Heading 1" with a
space, "heading1" lower-case, …).
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc
|
Document
|
Document to search. |
required |
target_id
|
str
|
The id you want to map onto (e.g. |
required |
style_type
|
StyleType | None
|
If given, only consider styles of this |
None
|
Returns:
| Name | Type | Description |
|---|---|---|
The |
str | None
|
attr: |
str | None
|
|
|
str | None
|
defined exactly and (when |
|
str | None
|
type, returns |
Source code in docx_plus/styles/modify.py
remap_styles ¶
remap_styles(
doc: Document,
*,
targets: list[str] | None = None,
mapping: dict[str, str] | None = None,
create_missing: bool = False,
) -> dict[str, str]
Reconcile a doc's styles against a set of canonical ids.
For each id in targets, resolve it to an existing style by:
- Exact match — the id is already defined in
styles.xml. - The supplied
mappingif it names this target. - :func:
find_matching_style(case/space-insensitive on id and name). - If
create_missing=Trueand the target is in the known built-ins table, materialise it from the table — which declaresbasedOn="Normal"so the new style inherits the doc's customised Normal (fonts, colours, …) automatically.
Body references (w:pStyle, w:rStyle, w:tblStyle) pointing at
the original target id are rewritten in place to the resolved id, so a
subsequent :func:apply_style works without further translation. The
rewrite spans every part that can carry such references — main body,
headers, footers, footnotes, endnotes, comments — and each target is
rewritten only through the ref tag that matches the resolved style's
type, so a paragraph style is never wired into a w:rStyle slot. Refs
between styles in styles.xml (basedOn, next, link) are
left untouched — this keeps the remap a non-destructive rewrite.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc
|
Document
|
Document to remap. |
required |
targets
|
list[str] | None
|
Ids to reconcile. Defaults to every entry in the known-built-ins table. |
None
|
mapping
|
dict[str, str] | None
|
Optional explicit |
None
|
create_missing
|
bool
|
If True, fall back to materialising from the built-ins table when nothing else matches. Only works for ids that have a built-in entry. |
False
|
Returns:
| Type | Description |
|---|---|
dict[str, str]
|
|
dict[str, str]
|
|
dict[str, str]
|
created. Targets unresolved after all four steps are omitted. |
Raises:
| Type | Description |
|---|---|
StyleNotFoundError
|
If |
Source code in docx_plus/styles/modify.py
625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 | |
list_styles ¶
list_styles(
doc: Document,
*,
style_type: StyleType | None = None,
include_latent: bool = False,
) -> list[StyleInfo]
List defined styles in doc.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
doc
|
Document
|
Document to inspect. |
required |
style_type
|
StyleType | None
|
If given, restrict to styles of this |
None
|
include_latent
|
bool
|
If True, also yield built-ins from the known-built-ins
table that aren't materialised in |
False
|
Returns:
| Type | Description |
|---|---|
list[StyleInfo]
|
A list of :class: |
list[StyleInfo]
|
entries (if requested) afterwards. Order within each group is the |
list[StyleInfo]
|
order they appear in |