Skip to content

document

document

DocumentPart and closely related objects.

DocumentPart

DocumentPart(
    partname: PackURI,
    content_type: str,
    element: BaseOxmlElement,
    package: Package,
)

Bases: StoryPart

Main document part of a WordprocessingML (WML) package, aka a .docx file.

Acts as broker to other parts such as image, core properties, and style parts. It also acts as a convenient delegate when a mid-document object needs a service involving a remote ancestor. The Parented.part property inherited by many content objects provides access to this part object for that purpose.

Source code in src/docx/opc/part.py
def __init__(
    self, partname: PackURI, content_type: str, element: BaseOxmlElement, package: Package
):
    super(XmlPart, self).__init__(partname, content_type, package=package)
    self._element = element

custom_xml_parts property

custom_xml_parts: tuple[CustomXmlPart, ...]

The custom XML data store items related from this document part.

In relationship-id order, which is the order Word writes them and the order the itemN.xml numbering follows.

vba_project property writable

vba_project: bytes | None

The bytes of word/vbaProject.bin, or None when there is no macro project.

has_macros property

has_macros: bool

True when this document carries a VBA project.

comments property

comments: Comments

Comments object providing access to the comments added to this document.

footnotes property

footnotes: Footnotes

Footnotes object providing access to the footnotes of this document.

endnotes property

endnotes: Endnotes

Endnotes object providing access to the endnotes of this document.

has_endnotes_part property

has_endnotes_part: bool

True when this document already has an endnotes part.

The endnote counterpart of has_footnotes_part, and used the same way.

has_footnotes_part property

has_footnotes_part: bool

True when this document already has a footnotes part.

Reading footnotes creates the part when it is absent, so code that only wants to look at footnotes that exist — a document-wide search, say — asks this first rather than adding /word/footnotes.xml to every document it touches.

core_properties property

core_properties: CoreProperties

A CoreProperties object providing read/write access to the core properties of this document.

document property

document

A Document object providing access to the content of this document.

Raises StrictOoxmlNotSupportedError if the package is an ISO Strict document.

has_numbering_part property

has_numbering_part: bool

True when this document already has a numbering part.

Reading numbering_part creates one when it is absent, so code that only wants to look at numbering that exists asks this first rather than adding an empty /word/numbering.xml to every document it touches.

settings property

settings: Settings

A Settings object providing access to the settings in the settings part of this document.

theme property

theme: Theme | None

A Theme object for this document, or None when it has no theme part.

Unlike the styles and settings parts, a theme part is not created on demand. A theme is a design a document was authored against; synthesising an empty one would answer "what typeface is this actually in" with a fiction.

styles property

styles

A Styles object providing access to the styles in the styles part of this document.

The collection is told which document part it belongs to, so a style taken out of it can find its own numbering definitions when copied into another document.

add_alt_chunk_part

add_alt_chunk_part(blob: bytes, content_type: str) -> str

Return the rId of a newly-created alt-chunk part holding blob.

Each call adds a new part; alt-chunk content is not deduplicated the way image content is, because two embedded documents with identical bytes are rare and Word rewrites them independently on import.

Source code in src/docx/parts/document.py
def add_alt_chunk_part(self, blob: bytes, content_type: str) -> str:
    """Return the rId of a newly-created alt-chunk part holding `blob`.

    Each call adds a new part; alt-chunk content is not deduplicated the way image
    content is, because two embedded documents with identical bytes are rare and
    Word rewrites them independently on import.
    """
    alt_chunk_part = AltChunkPart.new(self.package, blob, content_type)
    return self.relate_to(alt_chunk_part, RT.A_F_CHUNK)

add_custom_xml_part

add_custom_xml_part(
    xml: str | bytes,
    schema_refs: tuple[str, ...] = (),
    *,
    item_id: str | None = None,
) -> CustomXmlPart

Add a custom XML data store item holding xml and return its part.

Creates the customXml/itemN.xml part, its itemPropsN.xml sidecar carrying the item GUID, and both relationships. item_id is that GUID; one is generated at random when it is omitted. See Document.add_custom_xml_part.

Source code in src/docx/parts/document.py
def add_custom_xml_part(
    self,
    xml: str | bytes,
    schema_refs: tuple[str, ...] = (),
    *,
    item_id: str | None = None,
) -> CustomXmlPart:
    """Add a custom XML data store item holding `xml` and return its part.

    Creates the `customXml/itemN.xml` part, its `itemPropsN.xml` sidecar carrying the
    item GUID, and both relationships. `item_id` is that GUID; one is generated at
    random when it is omitted. See :meth:`.Document.add_custom_xml_part`.
    """
    package = self.package
    assert package is not None

    blob = xml.encode("utf-8") if isinstance(xml, str) else xml
    item_partname = package.next_partname("/customXml/item%d.xml")
    # -- the props part takes its number from its item rather than being numbered
    # -- independently; Word pairs the two by number --
    props_partname = PackURI(str(item_partname).replace("/item", "/itemProps"))

    item_part = CustomXmlPart.new(package, item_partname, parse_xml(blob))
    props_part = CustomXmlPropertiesPart.new(
        package,
        props_partname,
        item_id if item_id is not None else "{%s}" % str(uuid.uuid4()).upper(),
        schema_refs,
    )
    item_part.relate_to(props_part, RT.CUSTOM_XML_PROPS)
    self.relate_to(item_part, RT.CUSTOM_XML)
    return item_part

remove_vba_project

remove_vba_project() -> int

Remove the VBA project and its vbaData.xml sibling; return how many parts went.

The main part's content type is switched back to the non-macro-enabled form, so the document does not claim to carry macros it no longer has — Word warns the user about those.

Source code in src/docx/parts/document.py
def remove_vba_project(self) -> int:
    """Remove the VBA project and its `vbaData.xml` sibling; return how many parts went.

    The main part's content type is switched back to the non-macro-enabled form, so
    the document does not claim to carry macros it no longer has — Word warns the
    user about those.
    """
    removed = 0
    for reltype in (RT.VBA_PROJECT, RT.VBA_DATA):
        for rId in [rId for rId, rel in self.rels.items() if rel.reltype == reltype]:
            self.drop_rel(rId)
            removed += 1
    if removed:
        self.content_type = _plain_content_type(self.content_type)
    return removed
add_footer_part()

Return (footer_part, rId) pair for newly-created footer part.

Source code in src/docx/parts/document.py
def add_footer_part(self):
    """Return (footer_part, rId) pair for newly-created footer part."""
    footer_part = FooterPart.new(self.package)
    rId = self.relate_to(footer_part, RT.FOOTER)
    return footer_part, rId

add_header_part

add_header_part()

Return (header_part, rId) pair for newly-created header part.

Source code in src/docx/parts/document.py
def add_header_part(self):
    """Return (header_part, rId) pair for newly-created header part."""
    header_part = HeaderPart.new(self.package)
    rId = self.relate_to(header_part, RT.HEADER)
    return header_part, rId

drop_header_part

drop_header_part(rId: str) -> None

Remove related header part identified by rId.

Source code in src/docx/parts/document.py
def drop_header_part(self, rId: str) -> None:
    """Remove related header part identified by `rId`."""
    self.drop_rel(rId)

footer_part

footer_part(rId: str)

Return FooterPart related by rId.

Source code in src/docx/parts/document.py
def footer_part(self, rId: str):
    """Return |FooterPart| related by `rId`."""
    return self.related_parts[rId]

get_style

get_style(
    style_id: str | None, style_type: WD_STYLE_TYPE
) -> BaseStyle

Return the style in this document matching style_id.

Returns the default style for style_type if style_id is None or does not match a defined style of style_type.

Source code in src/docx/parts/document.py
def get_style(self, style_id: str | None, style_type: WD_STYLE_TYPE) -> BaseStyle:
    """Return the style in this document matching `style_id`.

    Returns the default style for `style_type` if `style_id` is |None| or does not
    match a defined style of `style_type`.
    """
    return self.styles.get_by_id(style_id, style_type)

get_style_id

get_style_id(style_or_name, style_type)

Return the style_id (str) of the style of style_type matching style_or_name.

Returns None if the style resolves to the default style for style_type or if style_or_name is itself None. Raises if style_or_name is a style of the wrong type or names a style not present in the document.

Source code in src/docx/parts/document.py
def get_style_id(self, style_or_name, style_type):
    """Return the style_id (|str|) of the style of `style_type` matching
    `style_or_name`.

    Returns |None| if the style resolves to the default style for `style_type` or if
    `style_or_name` is itself |None|. Raises if `style_or_name` is a style of the
    wrong type or names a style not present in the document.
    """
    return self.styles.get_style_id(style_or_name, style_type)

header_part

header_part(rId: str)

Return HeaderPart related by rId.

Source code in src/docx/parts/document.py
def header_part(self, rId: str):
    """Return |HeaderPart| related by `rId`."""
    return self.related_parts[rId]

floating_shapes

floating_shapes()

The FloatingShapes instance containing the anchored shapes in the document.

Source code in src/docx/parts/document.py
@lazyproperty
def floating_shapes(self):
    """The |FloatingShapes| instance containing the anchored shapes in the document."""
    return FloatingShapes(self._element.body, self)

inline_shapes

inline_shapes()

The InlineShapes instance containing the inline shapes in the document.

Source code in src/docx/parts/document.py
@lazyproperty
def inline_shapes(self):
    """The |InlineShapes| instance containing the inline shapes in the document."""
    return InlineShapes(self._element.body, self)

numbering_part

numbering_part() -> NumberingPart

A NumberingPart object providing access to the numbering definitions for this document.

Creates an empty numbering part if one is not present.

Source code in src/docx/parts/document.py
@lazyproperty
def numbering_part(self) -> NumberingPart:
    """A |NumberingPart| object providing access to the numbering definitions for this document.

    Creates an empty numbering part if one is not present.
    """
    try:
        return cast(NumberingPart, self.part_related_by(RT.NUMBERING))
    except KeyError:
        numbering_part = NumberingPart.new()
        self.relate_to(numbering_part, RT.NUMBERING)
        return numbering_part

save

save(path_or_stream: str | PathLike[str] | IO[bytes])

Save this document to path_or_stream, which can be either a path to a filesystem location (a string or os.PathLike) or a file-like object.

Source code in src/docx/parts/document.py
def save(self, path_or_stream: str | os.PathLike[str] | IO[bytes]):
    """Save this document to `path_or_stream`, which can be either a path to a
    filesystem location (a string or ``os.PathLike``) or a file-like object."""
    if isinstance(path_or_stream, os.PathLike):
        path_or_stream = os.fspath(path_or_stream)
    self.package.save(path_or_stream)