Skip to content

customprops

customprops

Custom element classes for the custom document properties part.

Stored as /docProps/custom.xml, this is the third and last of the document-properties parts, after the Dublin-Core properties in core.xml and the application properties in app.xml. It holds arbitrary named values, which is what document-management systems, contract tooling and mail-merge pipelines use to carry their own keys, and what a DOCPROPERTY field in the document body refers to.

CT_Property

Bases: BaseOxmlElement

<property> element, one custom document property.

The value is carried by a single child element from the vt: variant namespace, whose tag names the type. Writing the wrong variant for a value produces a file Word refuses to open, so the mapping is deliberate and narrow.

value property writable

value: str | int | float | bool | datetime | None

The Python value of this property, or None for an empty or null variant.

A variant this library does not model — a vector, array or blob — reads as the raw text of the element, so nothing in a document is silently dropped, but such a property cannot be written back through a Python value.

CT_CustomProperties

Bases: BaseOxmlElement

<Properties> element, the root of the custom document properties part.

new classmethod

Return a new, empty <Properties> element.

Source code in src/docx/oxml/customprops.py
@classmethod
def new(cls) -> CT_CustomProperties:
    """Return a new, empty `<Properties>` element."""
    return cast(CT_CustomProperties, parse_xml(cls._Properties_tmpl))

add_named_property

add_named_property(name: str, value: object) -> CT_Property

Return a new <property> element for name, appended to this part.

Source code in src/docx/oxml/customprops.py
def add_named_property(self, name: str, value: object) -> CT_Property:
    """Return a new `<property>` element for `name`, appended to this part."""
    # -- compute the pid before adding; the new element has none yet and the scan
    # -- would trip over it --
    pid = self.next_pid()
    property = self.add_property()
    property.fmtid = FMTID_USER_DEFINED
    property.pid = pid
    property.name = name
    property.value = cast("str | int | float | bool | dt.datetime | None", value)
    return property

get_by_name

get_by_name(name: str) -> CT_Property | None

The <property> element named name, or None if there is none.

Source code in src/docx/oxml/customprops.py
def get_by_name(self, name: str) -> CT_Property | None:
    """The `<property>` element named `name`, or |None| if there is none."""
    for property in self.property_lst:
        if property.name == name:
            return property
    return None

next_pid

next_pid() -> int

The property id to give the next property added.

One greater than the highest in use. Gaps left by deleted properties are not reused and existing properties are never renumbered: a pid need only be unique, and rewriting them would churn the file for no gain.

Source code in src/docx/oxml/customprops.py
def next_pid(self) -> int:
    """The property id to give the next property added.

    One greater than the highest in use. Gaps left by deleted properties are not
    reused and existing properties are never renumbered: a `pid` need only be
    unique, and rewriting them would churn the file for no gain.
    """
    pids = [property.pid for property in self.property_lst]
    return max(pids) + 1 if pids else _FIRST_PID