75_Pythonによるオフィス業務の自動化:WordとPDF

Pythonによるオフィス業務の自動化:Word文書とPDF処理の実践

目次

  • Pythonによるオフィス業務の自動化:Word文書とPDF処理の実践
    • はじめに
    • 一、python-docx:Word文書の作成と編集
    • 二、既存のWord文書の読み込みと修正
    • 三、実践:Word契約書のバッチ生成
    • 四、PyPDF2:PDFの結合、分割、抽出
    • 五、PDFテキストとメタデータの抽出
    • [✅ ポイントまとめ](#✅ ポイントまとめ)
    • 適用シーン
    • 拡張の方向性

はじめに

日常業務において、Word文書の作成・編集や、PDFファイルの結合・分割・抽出は極めて一般的なニーズです。契約書の自動生成、レポートテンプレートのバッチ編集、スキャンしたPDFの整理など、手作業では時間がかかり労力もかかる上、ミスも起こりやすくなります。Pythonのpython-docxおよびPyPDF2ライブラリを使用すれば、プログラミングによってこれらのタスクを効率的に完了させ、真の「ワンクリック自動化」を実現できます 。本記事では、これら2つのライブラコアの核心的な使い方を体系的に学び、初心者から実戦的な応用までを網羅します。

学習のアドバイス:オフィス業務の自動化における核心的な考え方は「テンプレート+データ入力」です。まず文書の固定フォーマット(Wordテンプレート)を設計し、Pythonプログラムを使って変動するデータを動的に入力します。この方法の効率は、毎回ゼロから文書全体を作成するよりもはるかに高いものです。効率を追求する開発者にとって、これは費用対効果が極めて高いスキルです。

一、python-docx:Word文書の作成と編集

python-docxは、Office Open XML形式(.docx)を操作するための純粋なPythonライブラリです。Windows上のWordソフトウェアに依存せず、あらゆるプラットフォームのサーバー上で実行可能です---- ――つまり、作成した自動化スクリプトをLinuxサーバーに直接デプロイして、ドキュメントの一括処理を行うことができます。

pip install python-docx

インストール時の注意点 :python-docxは.docx形式(Office 2007以降のバージョン)を処理しますが、旧式の.doc形式には対応していません。.docファイルを処理する必要がある場合は、textractライブラリの使用、または.docを事前に手動で.docxに変換することをお勧めします。

オブジェクトモデルの理解:Document(文書) → Paragraph(段落) → Run(テキスト断片)。Runはpython-docxにおける最小のスタイル単位です。――同じ段落内で、前半が通常のテキストで、後半を太字で表示したい場合、これら2つの部分を別々のRunに配置する必要があります。これは初心者が最も混同しやすい概念であり、面接でもよく問われる知識ポイントです。

以下のコードは、ドキュメントの作成から、見出し、段落、表、画像の追加に至るまでの完全な流れを示しています:

from docx import Document
from docx.shared import Inches, Pt, RGBColor
from docx.enum.text import WD_ALIGN_PARAGRAPH

doc = Document()

# 見出しの追加
doc.add_heading(「プロジェクト計画書」, level=1)
doc.add_heading(「一、プロジェクトの背景」, level=2)

# 段落の追加
paragraph = doc.add_paragraph(「これはPythonによるオフィス業務の自動化に関する」)
run = paragraph.add_run(「サンプルプロジェクト」)
run.bold = True
run.font.size = Pt(14)
run.font.color.rgb = RGBColor(0x42, 0x7C, 0xC4)

# スタイル付きテキストの追加
doc.add_paragraph(「プロジェクト目標:オフィス業務プロセスの自動化を実現する」, style="List Bullet")
doc.add_paragraph(「予定期間:3ヶ月」, style="List Bullet")

# 表の追加
table = doc.add_table(rows=4, cols=3, style="Light Grid Accent 1")
headers = [「フェーズ」, 「タスク」, 「担当者」]
for i, header in enumerate(headers):
    table.rows[0].cells[i].text = header

data = [
    [「要件分析」, 「要件ドキュメントの収集・整理」, 「張三」],
    [「開発・実装」, 『コーディングと単体テスト』, 「李四」],
    
[「テスト・本番リリース」, 『統合テストとデプロイ』, 「王五」],
]
for i, row_data in enumerate(data, 1):
    for j, value in enumerate(row_data):
        table.rows[i].cells[j].text = value

# 画像の追加
doc.add_picture(「logo.png」, width=Inches(2.0))

doc.save(「プロジェクト計画書.docx」)

コード解説Document() は、空白のドキュメントオブジェクトを作成します。これは、Wordソフトウェアの「新しい空白ドキュメント」に相当します。add_heading() 見出しを追加します。levelパラメータは0から9までで、それぞれ異なる見出しレベルに対応します。add_paragraph() Paragraphオブジェクトを返します。その add_run() メソッドを使用すると、段落の後に異なる書式のテキストを追加できます。add_table(rows=4, cols=3) 4行3列の表を作成します----- -ここで、行数と列数を事前に把握しておく必要があります。その後、表オブジェクトの add_row() メソッドを使用して、動的に行を追加することができます。
よくある落とし穴 :ドキュメントを保存する際、対象ファイルが他のプログラム(Wordなど)によって開かれている場合、 PermissionError が発生します。保存前に、ファイルが使用されていないことを必ず確認してください。また、画像のパスについては絶対パスを使用するか、相対パスがスクリプトの実行ディレクトリ内で正しく解決されることを確認することをお勧めします。

2. 既存のWord文書の読み込みと編集

実際の業務では、ゼロから作成するよりも、既存の文書テンプレートを基に修正を行う場合がほとんどです。python-docxは、文書を読み込み、その内容を走査するための包括的な機能を提供しています:

from docx import Document

doc = Document(「プロジェクト計画書.docx」)

# すべての段落を走査
for para in doc.paragraphs:
    print(f「[{para.style.name}] {para.text}」)

# 表の読み込み
for table in doc.tables:
    for row in table.rows:
        cells = [cell.text for cell in row.cells]
        print(「\\t」.join(cells))

# 内容の変更と保存
doc.paragraphs[1].text = 「(更新版)プロジェクトの背景」
doc.save(「プロジェクト計画書_改訂版.docx」)

反復処理のコツdoc.paragraphs は、見出し、本文、空白段落など、ドキュメント内のすべての段落のリストを返します。注意すべき点は、表内のテキストは doc.paragraphs には含まれておらず、別途 doc.tables を通じて反復処理する必要があることです。これは初心者が内容を検索する際によく陥る落とし穴でもあります――表にテキストがあるのは明らかなのに、段落を反復処理しても見つからないという状況です。
実際の応用 :テンプレート文書を修正する際、一般的な手法として、テンプレート内にプレースホルダー(例: {``{甲方}}{``{金額}})を配置し、すべての段落と表のセルを走査して、str.replace() を使用してプレースホルダーの内容を置換します。これにより、テンプレートの設計とデータの入力は完全に分離され、技術者でない人でもテンプレートのスタイルを独自に調整できるようになります。

3. 実践:Word契約書のバッチ生成

これは、オフィス業務の自動化において最も典型的な活用シーンの一つです。数十社、あるいは数百社もの取引先に対して、書式が統一された契約書を生成する必要があると仮定します。手作業では時間がかかるだけでなく、漏れやミスが生じやすくなります。以下のコードは、Pythonを使用してバッチ生成を行う方法を示しています:

from docx import Document

contracts = [
    {「甲方」: 「会社A」, 「乙方」: 「会社X」, 「金額」: 50000},
    {「甲方」: 「会社B」, 「乙方」: 『会社Y』, 「金額」: 80000},
    
{「甲方」: 「会社C」, 「乙方」: 「会社Z」, 『金額』: 120000},
]

for contract in contracts:
    doc = Document()
    doc.add_heading(「提携契約書」, level=1)
    
doc.add_paragraph(f「甲方:{contract[『甲方』]}」)
    doc.add_paragraph(f「乙方:{contract[『乙方』]}」)
    doc.add_paragraph(f「契約金額:{contract[『金額』]:,}元」)
    
doc.add_paragraph(「一、協力内容」)
    doc.add_paragraph(「双方は互恵・共栄の原則に基づき、技術開発プロジェクトに関して以下の協力契約を締結する...」)

    filename = f「契約_{contract[『甲』]}_{contract[『乙』]}.docx」
    doc.save(filename)
    
print(f「生成済み: {filename}」)

パフォーマンスに関する推奨事項 :契約書の数が非常に多い場合(例えば数千件など)、1件ごとに Document() を行い、その後 save() を行う処理コストは小さくない。最適化の方法は2つあります。1つは、毎回ゼロから作成するのではなく、テンプレートをファイルとしてコピーして開いて修正することです。もう1つは、マルチプロセスによる並列処理を行い、マルチコアCPUを十分に活用することです。ただし、実際のプロジェクトでは、数百件以内であれば単一プロセスでも数秒から1~2分程度で完了します。
実際の課題:契約書の内容に複雑な表のネストや特定のレイアウトが含まれている場合、Python-docxのみを使用して作成するのは困難です。この場合、より良い解決策は、まずWordでテンプレートファイルを設計し、Pythonではテンプレートの開く、プレースホルダーの置換、新しいファイルとして保存のみを担当させることです。これは面接でもよく聞かれる質問です:「複雑な形式のWord文書を効率的に一括生成するにはどうすればよいか?」

4. PyPDF2:PDFの結合、分割、抽出

Wordの操作とは異なり、PDFは「読み取り専用」のフォーマットです。主に配布や表示を目的としており、編集には適していません。PythonでPDFを処理するライブラリは、主に「PDFの作成」と「既存のPDFの操作」の2種類に分類されます。PyPDF2は後者に属し、既存のPDFファイルの結合、分割、回転、メタデータ抽出などの操作に特化しています。

pip install PyPDF2

ライブラリの選択 :PythonのPDFライブラリのエコシステムは比較的複雑です。PyPDF2 は基本的な結合・分割に適しています;pdfplumber は表データの抽出に長けています;reportlab はゼロからPDFを作成するために使用されます;fpdf2 もPDFの作成に使用されますが、APIはよりシンプルです。どのライブラリを選ぶかは具体的なニーズ次第ですが、1つのライブラリですべてを行おうとしないでください。

複数のPDFファイルを結合する:

from PyPDF2 import PdfMerger

merger = PdfMerger()
pdf_files = [「レポート_第1部.pdf」, 「レポート_第2部.pdf」, 「レポート_第3部.pdf」]

for pdf in pdf_files:
    
merger.append(pdf)

merger.write(「結合後の完全なレポート.pdf」)
merger.close()
print(「PDFの結合が完了しました!」)

重要な詳細merger.append() はPDFファイルを結合リストに追加します。この順序が、最終的な出力ファイルのページ順序を決定します。merger.close() は省略できません――これは出力ファイルへの書き込みとリソースの解放を担当します。close() の呼び出しを忘れると、出力されるPDFファイルが不完全になったり破損したりする可能性があります。これは最も一般的なバグの一つです。
高度な使い方merger.merge () メソッドを使用すると、特定の位置にPDFページを挿入できます。例えば、100ページのレポートの「5ページ目」の後に表紙を1ページ挿入したい場合、merger.merge(5, cover_pdf) を使用することで、正確なページ挿入を実現できます。

PDFの分割(指定したページ範囲の抽出):

from PyPDF2 import PdfReader, PdfWriter

reader = PdfReader(「結合後の完全なレポート.pdf」)
total_pages = len(reader.pages)
print(f「ドキュメントは合計 {total_pages} ページです」)

# 最初の5ページを抽出して新しいファイルとして保存
writer = PdfWriter()
for i in range(min(5, total_pages)):
    writer.add_page(reader.pages[i])

with open(「最初の5ページの抜粋.pdf」, 「wb」) as f:
    writer.write(f)

# ページ番号ごとにグループ分けして分割
for start in range(0, total_pages, 10):
    writer = PdfWriter
 ()
    end = min(start + 10, total_pages)
    for i in range(start, end):
        writer.add_page(reader.pages[i])
    with open(f「分割_第{start+1}-{end}ページ.pdf」, 「wb」) as f:
        writer.write(f)

分割のシナリオ:実際の業務において、PDFの分割には2つの意味があります――ページ番号の範囲による分割(コードに示されている通り)と、内容による分割(「請求書番号に基づいて、結合されたスキャンPDFを個別の請求書に分割する」など)です。後者にはOCRやテキスト抽出が必要であり、PyPDF2だけでは実現できません。
メモリに関する注意点reader.pages を実行すると、PDF全体のページオブジェクトがメモリに読み込まれます。数百ページ程度の大きなPDFであればメモリ消費は許容範囲内ですが、数千ページに及ぶ巨大なPDFを処理する場合は、ストリーム処理やブロック単位での読み込みを検討することをお勧めします。実際のプロジェクトでは、100ページ以内のPDFであればPyPDF2を使用しても全く問題ありません。

5. PDFのテキストとメタデータの抽出

from PyPDF2 import PdfReader

reader = PdfReader(「結合後の完全なレポート.pdf」)

# メタデータの抽出
meta = reader.metadata
print(f「タイトル: {meta.title}」)
print(f「著者: {meta.author}」)
print(f「ページ数: {len(reader.pages)}」)

# ページごとのテキスト抽出
for i, page in enumerate(reader.pages):
    text = page.extract_text()
    
print(f「\\n--- {i+1}ページ ---」)    print(text[:200]) # 最初の200文字を出力してプレビュー

テキスト抽出の限界extract_text() で抽出されるテキストの品質は、PDF自体の生成方法に依存します。PDFがWordやテキストから変換されたものである場合、抽出効果は良好ですが、スキャンデータから生成された画像形式のPDFの場合、extract_text()では文字を一切抽出できません------この場合は、OCR技術(Tesseractライブラリなど)をPyPDF2と組み合わせて、画像を編集可能なテキストに変換する必要があります。
面接のシナリオ:「大量のPDFから重要な情報を一括で抽出するにはどうすればよいか?」------この面接問題は、まずPyPDF2を使用してPDFページを順に処理してテキストを抽出し、次に正規表現を用いてテキストから日付、金額、契約番号などの重要なフィールドを抽出、最後にExcelに集約するという総合的な能力を問うものです。これはオフィス業務の自動化において非常に典型的なETLプロセスです。

python-docxのAPI設計は直感的で、段落、Run、表などのコアオブジェクトを使用するだけでWord文書の作成と編集が可能です。一方、PyPDF2は、PDFの結合、分割、テキスト抽出など、基本的かつ実用的な機能を提供しています。これらを組み合わせることで、文書自動処理の完全なループを実現できます。実際の業務では、テンプレート文書を事前に設計しておき、Pythonにはデータの入力と生成のみを担当させることをお勧めします。そうすることで、効率が最も高まり、出力の品質も最も安定します。

✅ ポイントまとめ

  • python-docxの中核となるオブジェクトモデル:Document → Paragraph → Run。階層が明確で理解しやすい
  • Wordテンプレートのデータ埋め込み:プレースホルダーの置換により、契約書、報告書、通知書の大量生成を実現
  • PyPDF2のPDF結合、分割、回転、メタデータ抽出機能は、日常的なPDF操作のニーズを網羅
  • 表の操作、画像の挿入、書式設定などの高度な機能により、報告書類の生成ニーズを満たす

適用シーン

  • 契約書・合意書の大量生成:Pythonでデータテーブルを読み込み、Wordテンプレートに自動入力して数百件の契約書を生成
  • レポートの自動化:データベースからデータを抽出し、グラフや分析文を含む月次・年次レポートのWord文書を生成
  • PDF ドキュメント管理:スキャンしたファイルを結合、全文検索用に PDF からテキストを抽出、ページ単位で分割・エクスポート

拡張の方向性

  • reportlab ライブラリを学習し、純粋な Python コードで高品質な PDF ドキュメントを生成(Word テンプレート不要)
  • pdfplumber ライブラリを調査し、PyPDF2よりも強力なPDF表データ抽出機能を実現する
  • python-pptx ライブラリと組み合わせて、PowerPointプレゼンテーションの自動生成をさらに実現する