【実務・中級編】【上級者向け】「変更履歴」を維持したまま置換を行い、差分を自動生成する – Word VBA解析バイブル

スポンサーリンク

Word VBAの「Find」を使いこなすな、制御せよ。変更履歴を維持した高度な置換術

Word VBAで `Find.Execute Replace:=wdReplaceAll` を使うのは、初心者にとっての入り口であり、プロにとっては「地雷」の始まりだ。

なぜか? `ReplaceAll` はWordの内部エンジンに処理を丸投げするブラックボックスだからだ。変更履歴(Track Changes)を有効にした状態でこれを叩くと、意図しない範囲まで修正マークがついたり、あるいは逆に、置換したはずなのに履歴が残らなかったりという「制御不能な挙動」に遭遇する。

真に自動化を極めるならば、WordのFindオブジェクトを「操作」するのではなく、「探索」し、「履歴を保持したまま書き換える」という、エンジニアリングとしての規律が必要になる。

—

なぜ「ReplaceAll」を使ってはいけないのか

業務ツールとして「変更履歴を確実に残したい」という要件がある場合、`wdReplaceAll` は以下の点で致命的だ。

1. アトミック性の欠如: 置換対象が連続している場合、Wordはそれらを一つの変更履歴として纏めてしまうことがある。レビュー時に「どこを直したのか」が追えなくなる。
2. 書式情報の破壊: 置換後に元のフォント情報やスタイルが欠落するケースがある。
3. Undoの肥大化: 大規模文書で `ReplaceAll` を回すと、WordのUndoスタックが溢れ、VBAがクラッシュするリスクがある。

我々が目指すべきは、「イテレータによる一意な制御」である。

—

実装の指針:Findオブジェクトを「ポインタ」として扱う

Find処理を `Range` オブジェクトのループで制御する。これにより、置換の直前に履歴の有効状態を明示的に制御し、置換のたびに処理を確定させる設計とする。

プロダクションコード:TrackedReplace

このコードは、単なる置換ではなく、Wordの変更履歴エンジンを能動的に叩く設計になっている。

‘ @description 変更履歴を維持したまま、安全かつ確実に置換を行うための基盤クラス的関数
Public Sub TrackedReplace(targetRange As Range, findText As String, replaceText As String)
Dim rng As Range
Set rng = targetRange.Duplicate

‘ 変更履歴の記録を強制的にONにする
If Not ActiveDocument.TrackRevisions Then ActiveDocument.TrackRevisions = True

With rng.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = findText
.Replacement.Text = replaceText
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False

‘ イテレーションによる逐次置換
Do While .Execute
‘ ここで置換を実行
‘ 逐次実行することで、各変更が個別の履歴として記録される
rng.Text = replaceText

‘ 次の検索開始位置を置換後の末尾にセット
rng.Collapse Direction:=wdCollapseEnd
Loop
End With
End Sub

—

現場で差をつける「3つの鉄則」

1. 「Duplicate」によるメモリ保護

`targetRange` をそのまま `rng` に代入してはいけない。`Set rng = targetRange` と書くと、検索が進むたびに元のRangeオブジェクトまで移動してしまう。必ず `.Duplicate` を使用し、親のRangeオブジェクトを保護せよ。

2. 検索範囲の明確な定義

大規模文書において `ActiveDocument.Content` を指定するのは避けるべきだ。処理すべきセクションや、テーブル内のみ、あるいは特定のブックマーク内など、検索範囲を最小化することがパフォーマンスの鍵となる。

3. データベース連携時の正規化

外部(CSVやExcel)から取得した文字列を置換する場合、必ず「特殊文字」をエスケープせよ。特に `^p` (段落記号) や `^t` (タブ) が含まれる場合、Wordの検索エンジンは暴走する。置換前に文字列をサニタイズ(Cleanメソッド等で不要な制御文字を除去)する層を一段噛ませるのが、伝説のアーキテクトの流儀だ。

—

結論:自動化は「効率」ではなく「品質」のためにある

単に「置換して終わり」ならば、Wordの「置換」機能を使えばいい。我々がVBAを書く理由は、「人間が手作業でやるよりも、むしろ高い精度で履歴を残し、誰がいつ何を変更したかのエビデンスを自動生成する」ためだ。

この `TrackedReplace` をベースに、置換ログを別ファイルのCSVに書き出す処理を追加すれば、社内のドキュメント管理プロセスは劇的に改善する。

ツールは、使う者の知性レベルにしか育たない。コードをコピーするだけでなく、なぜWordがその挙動をするのかという「オブジェクトの深淵」に思いを馳せてほしい。健闘を祈る。

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