python-docxを使ってdocxファイルを書き換える


はじめに

毎週作成が必要な週報を自動生成するための検討です。

  • 前提
    • 週報はdocxファイルである
    • しかもテンプレートが決まっている
    • 自分以外も更新する
    • 更新した箇所は赤文字にしなければならない

調べたところ、python-docxを使えば、
文字だけ置き換えられることが分かりました。
また、paragraphごとに文字色を変えられることも分かりました。
これなら行けそうです。

paragraph.text = paragraph.text.replace("before","after")
paragraph.runs[0].font.color.rgb = RGBColor(204, 0, 0)

python_docのDocumentの構造

構造を見ると、paragraphはDocument直下にあるだけでなく、tablesの中にもあることが分かり、
すべてのparagraphのtextを置換するためには、それぞれのpragraphを置換する必要があります。

Document直下のparagraph
document.paragraphs[0].text

tables内のparagraph
document.tables[0].rows[0].cells[0].paragraphs[0].text

また、文字色を設定する場合はruns[0]を使います。なぜ[0]が付くのかは分かりません。
paragraph.runs[0].font.color.rgb = RGBColor(204, 0, 0)

書き換えのサンプルコード

paragraphtablesしか書き換えしていないので、
それ以外の図形や、ヘッダー・フッターの書き換えも必要であれば
追加の実装が必要です。

from docx import Document
from docx.shared import RGBColor
from docx.enum.text import WD_COLOR_INDEX

def replace_text(paragraph):
    replaced_text = paragraph.text.replace("before","after")
    if paragraph.text != replaced_text:
        paragraph.text = replaced_text
        paragraph.runs[0].font.color.rgb = RGBColor(204, 0, 0)
        paragraph.runs[0].font.highlight_color = WD_COLOR_INDEX.YELLOW

document = Document("original.docx")

for paragraph in document.paragraphs:
    replace_text(paragraph)

paragraphs = (paragraph
              for table in document.tables
              for row in table.rows
              for cell in row.cells
              for paragraph in cell.paragraphs)

for paragraph in paragraphs:
    replace_text(paragraph)

document.save("output_new.docx")

以上で置き換え完了です

参考