03
Locating what to edit
find_paragraphs(contains, regex, style, startswith, ignore_case, include_tables) find_paragraph(...) exactly one, or raises find_text(needle, regex, ignore_case, limit) text_of(paragraph) the view every other method uses
examples/03_finding_text.py โ ran in 0.23s ยท exit 0
Console output
============================================================================
03 ยท Finding what to edit
============================================================================
--- one filter at a time ---
contains : 23 paragraphs
regex : 42 numbered sub-clauses
style : 16 Heading 1
startswith : 7 starting '12.'
ignore_case: 24 case-insensitive
no tables : 1 vs 3 with
--- filters are ANDed ---
contains='Termination' AND regex='^4.' -> ['4. Term, Renewal, and Termination', '4.3 Termination for Cause. Either', '4.4 Effect of Termination. Upon e']
--- find_paragraph โ exactly one, or it raises ---
ok : 3.3 Late Payment. Amounts not paid when due shall
raises: no paragraph matched {'contains': 'does not appear anywhere'}
--- find_text โ character spans, not paragraphs ---
[159:175] 'thirty (30) days' in 3.2 Invoicing. Provider shall invoice...
[161:177] 'thirty (30) days' in 4.3 Termination for Cause. Either Par...
[179:195] 'thirty (30) days' in 4.4 Effect of Termination. Upon expir...
regex : 8 percentages
limit=2 : 2 capped
--- text_of โ insertions included, deletions excluded ---
python-docx Paragraph.text : for accounts more than past due, upon prior written notice.
rl.text_of(paragraph) : e than thirty (30) days past due, upon prior written notice.
Source
"""03 ยท Locating what to edit.
find_paragraphs(contains, regex, style, startswith, ignore_case, include_tables)
find_paragraph(...) exactly one, or raises
find_text(needle, regex, ignore_case, limit)
text_of(paragraph) the view every other method uses
"""
from _shared import banner, fresh, section
from docx_redline import RedlineError
banner("03 ยท Finding what to edit")
rl = fresh()
section("one filter at a time")
print("contains :", len(rl.find_paragraphs(contains="Provider")), "paragraphs")
print("regex :", len(rl.find_paragraphs(regex=r"^\d+\.\d+\s")), "numbered sub-clauses")
print("style :", len(rl.find_paragraphs(style="Heading 1")), "Heading 1")
print("startswith :", len(rl.find_paragraphs(startswith="12.")), "starting '12.'")
print(
"ignore_case:",
len(rl.find_paragraphs(contains="PROVIDER", ignore_case=True)),
"case-insensitive",
)
print(
"no tables :",
len(rl.find_paragraphs(contains="Signature", include_tables=False)),
"vs",
len(rl.find_paragraphs(contains="Signature")),
"with",
)
section("filters are ANDed")
both = rl.find_paragraphs(contains="Termination", regex=r"^4\.")
print("contains='Termination' AND regex='^4.' ->", [rl.text_of(p)[:34] for p in both])
section("find_paragraph โ exactly one, or it raises")
print("ok :", rl.text_of(rl.find_paragraph(contains="Late Payment"))[:50])
try:
rl.find_paragraph(contains="does not appear anywhere")
except RedlineError as exc:
print("raises:", exc)
section("find_text โ character spans, not paragraphs")
for match in rl.find_text("thirty (30) days", limit=3):
print(f" [{match.start}:{match.end}] {match.text!r} in {rl.text_of(match.paragraph)[:38]}...")
print("regex :", len(rl.find_text(r"\b\d+\.\d+%", regex=True)), "percentages")
print("limit=2 :", len(rl.find_text("Provider", limit=2)), "capped")
section("text_of โ insertions included, deletions excluded")
para = rl.find_paragraph(contains="Late Payment")
rl.replace_text("fifteen (15) days", "thirty (30) days")
print("python-docx Paragraph.text :", para.text[-60:])
print("rl.text_of(paragraph) :", rl.text_of(para)[-60:])
What it wrote
This example prints its result rather than saving a document โ read the
console output beside it.