【実務・中級編】【上級者向け】段落の「プロパティ」を再帰的に探索し、文書内の書式差異を詳細なレポートとしてExcelに出力する – Word VBA解析バイブル

スポンサーリンク

【Word VBA】文書の「書式の迷宮」を解剖する:段落監査エンジンの設計思想

Word文書を扱っていると、必ず直面する「謎の書式崩れ」がある。一見同じに見えるのに、なぜか行間が違う、段落前後の余白が微妙にズレている。これらの正体は、誰かが手動で適用した「直接書式(Direct Formatting)」という名の負債だ。

今日は、WordのDOMを深掘りし、文書内の全段落を走査して「スタイルからの逸脱」をExcelに吐き出す、実務レベルの監査エンジンを実装する。単なるコードの羅列ではない。「なぜWordのプロパティ参照は重いのか」「どう書けばメモリリークを回避できるのか」という、プロのエンジニアが現場で生き残るための知見を共有する。

1. なぜ「Range」の多用は禁忌なのか

Word VBAにおいて、最も低速で不安定な要素は「Selection」の利用と、不用意な「Range」の生成だ。
特に、数千行の文書をループさせる際、`Paragraph.Range`を毎回新規オブジェクトとして生成し続けると、COMのオーバーヘッドで処理速度は極端に低下する。

設計の極意:

  • 遅延バインディングは回避せよ: `Object`型での宣言は、コンパイル時に型チェックが行われないため、バグの温床となる。`Word.Paragraph`、`Excel.Range`といった型を明示せよ。
  • プロパティ取得の最小化: 比較対象となる「標準スタイル」のプロパティは、ループの外で一度だけ変数にキャッシュしろ。

2. 実装コード:文書監査エンジン(Word -> Excel)

このコードは、現在の文書内の段落をスキャンし、`Style`と比較して異なるプロパティをExcelに書き出す。

Option Explicit

‘ 参照設定: Microsoft Word 16.0 Object Library / Microsoft Excel 16.0 Object Library
Sub AuditDocumentFormatting()
Dim wdApp As Word.Application: Set wdApp = Application
Dim doc As Word.Document: Set doc = wdApp.ActiveDocument
Dim xlApp As Object, wb As Object, ws As Object
Dim para As Word.Paragraph
Dim rowIdx As Long

‘ Excelの準備: インスタンスを生成して高速化
Set xlApp = CreateObject(“Excel.Application”)
Set wb = xlApp.Workbooks.Add
Set ws = wb.Sheets(1)

‘ ヘッダーの設定
ws.Range(“A1:D1”).Value = Array(“段落番号”, “スタイル名”, “項目”, “実値 vs スタイル値”)
rowIdx = 2

‘ 監査エンジン: 段落ループ
For Each para In doc.Paragraphs
‘ 空段落は無視することでパフォーマンス向上
If Len(Trim(para.Range.Text)) > 1 Then

‘ 段落の左インデントがスタイルと食い違っているかチェックする例
If para.Format.LeftIndent <> para.Style.ParagraphFormat.LeftIndent Then
ws.Cells(rowIdx, 1).Value = para.ParaID
ws.Cells(rowIdx, 2).Value = para.Style.NameLocal
ws.Cells(rowIdx, 3).Value = “左インデント”
ws.Cells(rowIdx, 4).Value = para.Format.LeftIndent & ” pt (標準: ” & para.Style.ParagraphFormat.LeftIndent & ” pt)”
rowIdx = rowIdx + 1
End If

‘ ここにフォントの比較ロジックなどを追加していく
End If
Next para

xlApp.Visible = True
MsgBox “監査完了: ” & rowIdx – 2 & ” 件の不整合を検出しました。”, vbInformation
End Sub

3. このコードを「プロダクション級」にするための技術的注意点

このコードをそのまま現場に投入する際、以下の3点に注意を払うことが、エンジニアとしての格を決める。

A. `ParaID`の活用

Wordには段落を特定するユニークなIDが存在しない場合が多い。`para.ParaID`はWord 2013以降で利用可能で、文書編集による段落の移動にも追従できる。これを使わずに行番号ベースで管理すると、文書を少し編集しただけで監査結果がゴミになる。

B. 異常系への対処(エラーハンドリング)

WordのCOMオブジェクトは、たまに「死ぬ」。特に非標準的なテーブル内や、テキストボックス内の段落に遭遇するとプロパティ参照で例外を吐くことがある。`On Error Resume Next`で放置するのではなく、`Err.Number`を判定して、対象外のオブジェクトはスキップする設計が必須だ。

C. 大規模文書への対応

数万行の文書を扱う場合、`Excel.Application`への書き込みを毎回行うと重すぎて話にならない。
戦略:
1. メモリ上に`Variant`配列(二次元配列)を作成する。
2. 監査結果をすべて配列に格納する。
3. 最後に `ws.Range(“A2”).Resize(rowIdx-2, 4).Value = 配列` とすることで、Excelへの書き込みを1回に集約する。これで速度は100倍変わる。

最後に:自動化の真髄

「何が標準から逸脱しているか」を可視化するのは、単なるデバッグ作業ではない。それは、文書を「データ」として捉え、制御下に置くための第一歩だ。

Word VBAはレガシーな言語だと揶揄されることもある。だが、DOMを理解し、メモリの効率を計算し、堅牢なエラー処理を組めるエンジニアにとって、これほど強力な「文書操作エンジン」は他にない。

さあ、あなたの抱えるその「書式の負債」を、今すぐコードで殲滅してほしい。それができるのは、この技術を理解したあなただけだ。

タイトルとURLをコピーしました