【入門編】【上級者向け】Wordの「段落」オブジェクトのプロパティを、再帰的に探索して書式差異を特定する – Word VBA解析バイブル

スポンサーリンク

こんにちは!Word VBAの深淵へようこそ。
マクロの記録ボタンを押して生成されるコードを眺めるフェーズはもう卒業しましたね。

今回は、Word VBA中級者から上級者への大きな関所であり、かつ実務で絶大な威力を発揮するテーマ「二つの段落オブジェクトを再帰的に(あるいは総当たりで)比較し、わずかな書式の差異を完全にあぶり出す」という技術について解説します。

「なぜかこの段落だけ行間が広い」「なぜかフォントの一部が違う」――そんな原因不明の崩れに悩まされた経験はありませんか?
人間が目視でチェックするには限界があります。ならば、VBAにすべてをスキャンさせましょう。ここをクリアすれば、あなたのWord VBAのスキルは間違いなく本物の「エンジニア領域」に到達します。一緒にマスターしていきましょう!

なぜ「段落の比較」は難しいのか?

Wordの文書構造を思い浮かべてみてください。
段落(`Paragraph`)オブジェクトの中には、フォント(`Font`)があり、インデントがあり、タブストップがあり、リスト書式があり……と、数えきれないほどのプロパティが存在します。

さらに厄介なのは、Wordの書式には「スタイルの継承」という概念があることです。
「直接文字に設定されている書式」「段落スタイルに設定されている書式」「標準スタイルからの継承」が複雑に絡み合っているため、単純にプロパティを比較するだけでは、本当の差異が見えてきません。

今回は、「二つの段落の隅々までプロパティを突合し、異なっている箇所をイミディエイトウィンドウにリストアップする」という、実務で即戦力になるインスペクターツールを作ります。

実装コード:段落書式コンパレータ

以下のコードを、WordのVBAエディタ(Alt + F11)の標準モジュールに貼り付けてください。
選択している二つの段落、あるいは文書内の指定した段落同士を比較するコードです。

Option Explicit

‘ =================================================================================
‘ 処理名: 2つの段落の書式を徹底比較し、差異を検出するプロシージャ
‘ 対象読者: マクロの記録を卒業し、Wordの内部構造を掌握したいエンジニアへ
‘ =================================================================================
Public Sub CompareParagraphFormats()
Dim doc As Document
Set doc = ActiveDocument

‘ 比較対象の段落を取得(ここでは例として文書内の第1段落と第2段落を比較)
If doc.Paragraphs.Count < 2 Then MsgBox "比較するには、文書内に少なくとも2つの段落が必要です。", vbExclamation Exit Sub End If Dim pTarget1 As Paragraph Dim pTarget2 As Paragraph Set pTarget1 = doc.Paragraphs(1) Set pTarget2 = doc.Paragraphs(2) Debug.Print "=== 段落書式 比較診断開始 ===" Debug.Print "段落1: " & Left(pTarget1.Range.Text, 30) & "..." Debug.Print "段落2: " & Left(pTarget2.Range.Text, 30) & "..." Debug.Print "--------------------------------------------------" ' 1. 段落書式(ParagraphFormat)の比較 Call CompareParagraphFormat(pTarget1.Format, pTarget2.Format) ' 2. フォント書式(Font)の比較(段落全体の文字書式) Call CompareFontFormat(pTarget1.Range.Font, pTarget2.Range.Font) Debug.Print "=== 段落書式 比較診断終了 ===" MsgBox "比較が完了しました。イミディエイトウィンドウを確認してください。", vbInformation End Sub ' --- 段落書式プロパティの比較サブルーチン --- Private Sub CompareParagraphFormat(f1 As ParagraphFormat, f2 As ParagraphFormat) Debug.Print "[段落設定の比較]" ' インデントとスペース CheckAndLog "Alignment", f1.Alignment, f2.Alignment CheckAndLog "LeftIndent", f1.LeftIndent, f2.LeftIndent CheckAndLog "RightIndent", f1.RightIndent, f2.RightIndent CheckAndLog "FirstLineIndent", f1.FirstLineIndent, f2.FirstLineIndent CheckAndLog "SpaceBefore", f1.SpaceBefore, f2.SpaceBefore CheckAndLog "SpaceAfter", f1.SpaceAfter, f2.SpaceAfter CheckAndLog "LineSpacing", f1.LineSpacing, f2.LineSpacing CheckAndLog "LineSpacingRule", f1.LineSpacingRule, f2.LineSpacingRule ' 改ページ制御など CheckAndLog "KeepWithNext", f1.KeepWithNext, f2.KeepWithNext CheckAndLog "PageBreakBefore", f1.PageBreakBefore, f2.PageBreakBefore CheckAndLog "WidowControl", f1.WidowControl, f2.WidowControl End Sub ' --- フォント書式プロパティの比較サブルーチン --- Private Sub CompareFontFormat(font1 As Font, font2 As Font) Debug.Print "[フォント設定の比較]" CheckAndLog "Name (日本語等)", font1.Name, font2.Name CheckAndLog "Size", font1.Size, font2.Size CheckAndLog "Bold", font1.Bold, font2.Bold CheckAndLog "Italic", font1.Italic, font2.Italic CheckAndLog "Underline", font1.Underline, font2.Underline CheckAndLog "ColorIndex", font1.ColorIndex, font2.ColorIndex CheckAndLog "Spacing", font1.Spacing, font2.Spacing CheckAndLog "Scaling", font1.Scaling, font2.Scaling End Sub ' --- 差異を判定してログ出力するヘルパー関数 --- Private Sub CheckAndLog(propName As String, val1 As Variant, val2 As Variant) ' 3状態プロパティ(True/False/Undefined(-999999等))を考慮した安全な比較 On Error Resume Next If val1 <> val2 Then
Debug.Print ” [差異発見] ” & propName & ” -> 段落1: [” & CStr(val1) & “] vs 段落2: [” & CStr(val2) & “]”
End If
On Error GoTo 0
End Sub

コードの深掘り解説:ここがプロの技

このコードには、Word VBA特有の「罠」を避けるための知見がいくつも組み込まれています。初心者から一歩抜け出すために、重要なポイントを解説します。

1. `Paragraph` と `Range` の役割分担を理解する

Word VBAで最も多い勘違いが、「`Paragraph`オブジェクトに対して直接フォントを変更しようとする」エラーです。

  • `ParagraphFormat`: 行間、インデント、段落前後の余白など「段落そのもののレイアウト」を司ります。
  • `Range` (`Paragraph.Range`): 文字列そのものであり、その中にある「文字のフォント(`Font`)」を司ります。

今回のコードでも、段落のレイアウトは `pTarget1.Format` から取得し、文字のフォントは `pTarget1.Range.Font` から取得しているのはそのためです。この境界線を正確に理解することがWordマクロ制覇の鍵です。

2. トライ・エラーを防ぐ「安全な比較(`On Error Resume Next`)」

Wordのプロパティ(特にフォントの太字や斜体)は、選択範囲内に「太字の部分と通常の部分が混在している」場合、`9999999`(wdToggle)やエラー値を返すことがあります。
そのまま単純に比較しようとすると、VBAは容赦なく実行時エラーで止まってしまいます。

ヘルパー関数 `CheckAndLog` の中にある `On Error Resume Next` は、そうした「値が取得できないカオスな状態」であってもマクロをクラッシュさせずに優しくスルーするための、現場の知見に基づく防壁なのです。

陥りやすい罠とアドバイス

実際にこのコードを動かしたとき、「何も差異が出ないのに、見た目が違う!」という現象にぶつかることがあります。

原因の多くは「スタイル」にあります。
例えば、段落1も段落2も「標準」スタイルを使っていて、かつ直接フォントサイズを変更していない場合、プロパティ値は完全に一致します。しかし、大元の「標準」スタイル自体の定義が途中で書き換わっていたりすると、見かけ上の表示が変わってしまいます。

もし、より厳密に「最終的に画面に描画される見た目」の差異を追いたい場合は、プロパティの比較だけでなく、`Style.NameLocal`(適用されているスタイル名)も同時に比較対象に加えてみてください。

おわりに

今回は、Word VBAにおける「段落オブジェクトの深層探索と書式比較」という、一歩進んだテーマをお届けしました。

「なぜこの書式が崩れるのか」をプログラムでロジカルに解明できるようになると、分厚い仕様書の整形や、社内フォーマットの自動チェックツールなど、ビジネスの現場で圧倒的な価値を発揮できるようになります。

ここをクリアしたあなたなら、もうWord VBAの基本はバッチリです!
ぜひ自分の環境でも動かして、イミディエイトウィンドウに出力されるログを眺めてみてください。オブジェクトたちの囁きが聞こえてくるはずですよ。それでは、次回の応用編でお会いしましょう!

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