【入門編】Word VBAで『文書比較ツール』を作成する:2つの文書の差分を色付けして抽出するロジック – Word VBA解析バイブル

スポンサーリンク

こんにちは!Word VBAの世界へようこそ。

「契約書の改訂版が届いたけれど、どこが変わったのか探すのが大変…」
「マクロの自動記録を使ってWordを操作してみたけれど、コードが複雑すぎて修正できない…」

そんな悩みを抱えていませんか?

Excel VBAに慣れている方でも、Word VBAに足を踏み入れようとすると「セルの概念がない世界」に戸惑うことがよくあります。しかし、安心してください。Word VBAには「オブジェクトモデル」という明確なルールと、Wordならではの非常に強力な組み込み機能(比較機能)が存在します。

この記事では、マクロの記録を卒業し、2つのWord文書の差分を自動抽出し、変更箇所を美しく色分け(ハイライト)する「プロ仕様の文書比較ツール」を作成します。

ここをクリアすれば、Word VBAの基本構造(Application / Document / Range)はバッチリマスターできますよ!私と一緒に、1ステップずつ紐解いていきましょう。

1. Word VBAの心臓部「3大オブジェクト」を理解しよう

コードを書く前に、Word VBAを操作する上での「3大要素」を整理しておきます。ここが頭に入っていると、エラーが起きたときの原因特定が劇的に早くなります。

[ Application ] (Wordというアプリケーション全体)

└── [ Document ] (開いている個別の文書ファイル)

└── [ Range ] (文書内の「特定の範囲・文字列」)

  • Application

Word全体を指す最上位のオブジェクト。画面更新の停止(`ScreenUpdating`)やファイル選択ダイアログの表示など、環境全体を制御します。

  • Document

開かれた1つのWordファイルです。文章全体、見出し、ヘッダー、そして「変更履歴(Revisions)」などを管理します。

  • Range

Word VBAで最も重要な概念です。 文書内の「特定の開始位置から終了位置までの範囲」を指します。文字、単語、段落、あるいは文書全体もすべて「Range」として操作します。

Excelが「行と列(Range(“A1”))」で位置を特定するのに対し、Wordは「先頭からの文字数(インデックス)」で位置を特定します。この違いを意識することが、脱初心者への第一歩です。

2. なぜ `Compare` メソッドを使うのか?

2つの文書の差分をとる際、文字を1文字ずつ比較するループ処理を書くのはナンセンスです。処理が非常に重くなり、Wordがフリーズしてしまいます。

そこで登場するのが、Wordが標準で持っている比較エンジンをVBAから呼び出す `Application.CompareDocuments` メソッド です。

‘ 概念イメージ
Set docDiff = Application.CompareDocuments( _
Original:=docOriginal, _ ‘ 元の文書
Revised:=docRevised, _ ‘ 修正版の文書
CompareTarget:=wdCompareTargetNew _ ‘ 新規文書として生成
)

このメソッドを実行すると、Wordは2つの文書を解析し、差分を「変更履歴(Revisions)」として保持した「新しいドキュメント」を裏側で一瞬で作成してくれます。

私たちは、生成された新しいドキュメント内の `Revisions`(変更履歴コレクション)を走査し、`Range` を使って好きな色を塗るだけでOKなのです。

3. 実践!『文書比較&自動色付けツール』の完全コード

それでは、実用的なVBAコードを記述していきましょう。
新しい標準モジュール(`挿入` > `標準モジュール`)を作成し、以下のコードを貼り付けてみてください。

Option Explicit

‘ ==============================================================================
‘ 機能:2つのWord文書を比較し、差分を新規文書に抽出して色付け(ハイライト)する
‘ ==============================================================================
Public Sub CompareAndHighlightDocuments()

Dim appWord As Word.Application
Dim docOriginal As Word.Document
Dim docRevised As Word.Document
Dim docDiff As Word.Document

Dim strPathOriginal As String
Dim strPathRevised As String
Dim rev As Word.Revision
Dim countChanges As Long

‘ — ① 比較するファイルのフルパスを指定 —
‘ ※環境に合わせてテスト用ファイルのパスに変更してください
strPathOriginal = “C:\VBA_Test\Original.docx”
strPathRevised = “C:\VBA_Test\Revised.docx”

‘ ファイルの存在チェック
If Dir(strPathOriginal) = “” Or Dir(strPathRevised) = “” Then
MsgBox “指定されたファイルが存在しません。パスを確認してください。”, vbExclamation, “エラー”
Exit Sub
End If

‘ — ② パフォーマンス最適化(画面描画を停止) —
Set appWord = Word.Application
appWord.ScreenUpdating = False

On Error GoTo ErrorHandler

‘ — ③ 文書を非表示で開く —
‘ (ユーザーの画面を散らかさず、処理速度を限界まで上げるテクニックです)
Set docOriginal = appWord.Documents.Open(FileName:=strPathOriginal, Visible:=False)
Set docRevised = appWord.Documents.Open(FileName:=strPathRevised, Visible:=False)

‘ — ④ 文書比較の実行 —
‘ CompareDocumentsメソッドにより、比較結果を持つ新しいDocumentオブジェクトが生成されます
Set docDiff = appWord.CompareDocuments( _
Original:=docOriginal, _
Revised:=docRevised, _
Destination:=wdCompareDestinationNew, _
Granularity:=wdGranularityWordLevel, _ ‘ 単語単位で比較
CompareFormatting:=False, _ ‘ 書式変更は無視(純粋なテキスト差分に集中)
CompareCaseChanges:=True) ‘ 大文字・小文字の違いを区別

‘ 原本文書はもう使わないため、メモリ解放のために静かに閉じます
docOriginal.Close SaveChanges:=wdDoNotSaveChanges
docRevised.Close SaveChanges:=wdDoNotSaveChanges
Set docOriginal = Nothing
Set docRevised = Nothing

‘ — ⑤ 比較結果文書の変更履歴(Revisions)をループ処理 —
countChanges = 0

‘ 変更履歴の追跡機能を一時的にオフ(ハイライト塗りが「変更」と捉えられないようにする)
docDiff.TrackRevisions = False

For Each rev In docDiff.Revisions
countChanges = countChanges + 1

‘ 変更の種類(挿入か削除か)に応じて色分け処理を行う
Select Case rev.Type

Case wdRevisionInsert
‘ 追加された箇所:明るい緑色(wdBrightGreen)でハイライト
rev.Range.HighlightColorIndex = wdBrightGreen

Case wdRevisionDelete
‘ 削除された箇所:ピンク色(wdPink)でハイライト
‘ ※削除箇所は文字が消えているため、Rangeの扱いに注意(後述の解説を参照)
rev.Range.HighlightColorIndex = wdPink

Case Else
‘ その他の変更(属性変更など)は黄色でハイライト
rev.Range.HighlightColorIndex = wdYellow

End Select
Next rev

‘ — ⑥ 画面の描画を再開し、結果を表示 —
appWord.ScreenUpdating = True
docDiff.Activate
appWord.Visible = True

‘ ユーザーへの完了報告
MsgBox “比較が完了しました!” & vbCrLf & _
“検出された差分件数: ” & countChanges & ” 件”, vbInformation, “完了”

ExitSub:
‘ 後処理:オブジェクト変数の安全な解放
On Error Resume Next
appWord.ScreenUpdating = True
Set rev = Nothing
Set docDiff = Nothing
Set docOriginal = Nothing
Set docRevised = Nothing
Exit Sub

ErrorHandler:
MsgBox “予期せぬエラーが発生しました: ” & Err.Description, vbCritical, “エラー発生”

‘ エラー時も開いてしまったファイルを放置しないスマートな処理
If Not docOriginal Is Nothing Then docOriginal.Close SaveChanges:=wdDoNotSaveChanges
If Not docRevised Is Nothing Then docRevised.Close SaveChanges:=wdDoNotSaveChanges

Resume ExitSub
End Sub

4. コードの解説:ここがプロのポイント!

このコードには、マクロの記録では絶対に生成されない「現場で使えるエンジニアリング」が詰まっています。ポイントを詳しく噛み砕きますね。

ポイント1:`Visible:=False` で裏側処理

`Documents.Open` の引数に `Visible:=False` を渡しています。
画面に文書が一瞬チラつくのを防ぎ、処理スピードを数倍〜数十倍に引き上げるプロの常套手段です。

ポイント2:`CompareDocuments` の返り値を受け取る

`Application.CompareDocuments` メソッドは、比較結果を格納した 新しい `Document` オブジェクト を返します。
変数 `docDiff` でそれを受け取ることにより、元のファイルを一切傷つけずに「差分専用の文書」に対して安全に操作を行えます。

ポイント3:`Revisions` コレクションと `Range` オブジェクトの連携

ここが一番面白いところです!
比較結果の文書には、差分がある場所全てに `Revision` オブジェクトが自動作成されます。

For Each rev In docDiff.Revisions
‘ rev.Range は「差分が発生しているその現場(範囲)」をピンポイントで指している!
rev.Range.HighlightColorIndex = wdBrightGreen
Next rev

`rev.Range` というプロパティを呼び出すだけで、差分が存在する「テキストの範囲」を正確に捕捉できます。あとはその `Range` に対して `HighlightColorIndex`(蛍光ペン機能)を適用するだけで、一瞬でカラフルな差分表が完成します。

5. 陥りやすい「3つの罠」と回避策

Word VBAを勉強し始めた方が必ずと言っていいほどハマる罠があります。先輩エンジニアとして、回避方法をこっそり教えますね。

罠1:削除(`wdRevisionDelete`)された箇所のテキストが見えない?

Wordの仕様上、文字が「削除」された履歴は、画面の「表示モード」によっては隠れて見えなくなってしまいます。

  • 対策: もし削除された文字も画面上に可視化して色付けしたい場合は、比較結果を表示した後に Wordの表示設定を 「すべての変更履歴/コメント」 に切り替えるコードを1行追加します。

‘ 変更履歴をインラインで全表示させる設定
docDiff.ActiveWindow.View.RevisionsFilter.Markup = wdRevisionsMarkupAll

罠2:ハイライト処理自体が「新しい変更履歴」として記録されてしまう

`docDiff` は変更履歴モードがONになった状態で生成されます。その状態で `rev.Range.HighlightColorIndex = …` を実行すると、「色を塗った」という操作自体が新たな変更履歴としてカウントされてしまうことがあります。

  • 対策: コード内にある通り、色塗りルーチンに入る直前で `docDiff.TrackRevisions = False` を指定し、変更履歴の追跡をOFFにしてください。

罠3:エラー時にWordのプロセス(ゴースト)が残る

ファイルが開けなかった等のエラーが起きると、裏で `Visible:=False` にしたWord文書が開きっぱなしになり、PCのメモリを圧迫します。

  • 対策: `On Error GoTo ErrorHandler` を設置し、万が一途中でエラーが起きても `ErrorHandler` 内で必ず `docOriginal.Close` などの終了処理が走るように「安全網」を張っておくことが極めて重要です。

まとめ:Word VBAの基本は「Rangeを制すること」

今回は、`Application.CompareDocuments` を使って差分を生成し、`Revisions` から `Range` を取得してハイライトを適用するロジックを解説しました。

本記事のポイントを復習しましょう。

1. Application / Document / Range の親子関係を常に意識する
2. 重い比較処理はWord組み込みの `CompareDocuments` に任せる
3. 差分範囲は `Revision.Range` でスマートに特定できる
4. ファイルを開くときは `Visible:=False` で高速化する

一見難しそうに見えるWord VBAですが、「テキストの特定範囲(Range)を掴んで、色や書式を変える」という本質さえ理解してしまえば、契約書の自動チェック、レポートの自動生成、表記揺れの自動修正など、あらゆる業務を劇的に効率化できます。

ここをクリアできれば、Word VBAの基本はバッチリですよ!
ぜひお手元のWordファイルで試して、その圧倒的なスピードを体感してみてくださいね。応援しています!

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