Form fields and content controls¶
Word has two mechanisms for "a place in the document where someone fills something in", from two different eras. Both are read here; which one a document uses depends on which Word feature built it.
- Legacy form fields (
w:fldCharwithw:ffData) — the text input, check box and drop-down from the old Forms toolbar. Values are read and written. - Content controls (
w:sdt, "structured document tags") — the modern replacement, and also what a mail-merge or template tool typically inserts. Read-only here.
Legacy form fields¶
Document.form_fields returns every one in the
body, and Paragraph.form_fields those of a
single paragraph:
from docx import Document
document = Document("form.docx")
for field in document.form_fields:
print(field.name, field.type, field.value)
Surname WD_FORM_FIELD_TYPE.TEXT 'Lovelace'
Agreed WD_FORM_FIELD_TYPE.CHECK_BOX True
Department WD_FORM_FIELD_TYPE.DROP_DOWN 'Engineering'
FormField.value reads and writes:
field.value = "Babbage" # a text input
field.value = True # a check box
field.value = "Finance" # a drop-down, by entry text
What value means follows the field type:
| Type | Value |
|---|---|
TEXT |
the result text Word last rendered |
CHECK_BOX |
a bool |
DROP_DOWN |
the selected entry, "" when nothing is selected |
Warning
Word renders an empty text field as filler — five spaces or similar — and that
filler is what value returns, because it is what the document actually contains.
Test against default rather than against ""
when you need to know whether a field was filled in.
The other properties describe how Word presents the field:
field.name # the bookmark name Word gives it
field.default
field.enabled
field.help_text
field.status_text
field.max_length # text inputs
field.text_type # WD_TEXT_FORM_FIELD_TYPE: REGULAR_TEXT, NUMBER_TEXT, DATE_TEXT, ...
field.items # drop-down entries
field.calc_on_exit
Content controls¶
A w:sdt wraps content rather than standing in for it, which has one consequence worth
knowing: text inside a content control is ordinary document text. Before 2.0.0 it was
invisible to the API — a document built from a template could read back as empty.
Document.content_controls and
Paragraph.content_controls give you
the controls themselves:
tag— the machine-readable name, which is what a template tool keys onalias— the title Word shows the usertype— rich text, plain text, date picker, and so ontext— everything inside, paragraphs separated by newlines, as for a table cellshowing_placeholder— whether what you are reading is the grey prompt text rather than a real valueis_block_level— whether it wraps whole paragraphs and tables, or sits inline within a paragraph
Reach the content through
runs,
paragraphs,
tables or
iter_inner_content():
To change the text in a control, edit those runs, or use
replace_text(), which reaches inside content
controls like any other text. See Finding and replacing text.