【実務・中級編】【初心者向け】検索結果の「前後の文字列」を取得して文脈を判定する – Word VBA解析バイブル

スポンサーリンク

「ただの検索」で終わるツールは、現場ではゴミ同然だ。

Word VBAの世界へようこそ。私はこの領域のアーキテクトとして、数えきれないほどの「動かないマクロ」や「保守不能なスパゲッティコード」を葬り去ってきた。

初心者が最初に陥る罠がある。それは「`Find`オブジェクトで目的の単語が見つかれば、業務は完了する」という思い込みだ。実務はそんなに甘くない。見つかった「価格」という単語が、見積書の項目なのか、規約の但し書きなのか、あるいは前後の文脈から判断して「改定前」のものなのか――これらを判別できなければ、自動化の価値は半減する。

今日は、検索結果の「前後」を鮮やかに切り出し、文脈を掌握するための極限のテクニックを伝授しよう。

—

1. なぜ `Selection` ではなく `Range` なのか

まず、三流のエンジニアは `Selection.Find` を使う。画面がチラつき、ユーザーの操作を阻害し、何より遅い。
プロは必ず `Range` オブジェクトを操作する。メモリ上で静かに、かつ高速に処理を完遂させるためだ。

検索でヒットした箇所を起点に「前後」を見る際、最も重要なのは Rangeのライフサイクル管理 である。ヒットした瞬間のRangeをそのまま拡張してはいけない。なぜなら、検索の「次を探す」ためのカーソル位置が破壊されるからだ。

—

2. 核心:`Duplicate` メソッドによる「探索用プロキシ」の生成

ヒットした箇所の前後を取得する際、鉄則となるのが `Duplicate`(複製)だ。

1. `Find` でターゲットを見つける。
2. 見つかった `Range` を `Duplicate` で別変数にコピーする。
3. コピーした `Range` を `MoveStart` / `MoveEnd` で伸縮させ、文脈を取得する。

この「探索用プロキシ」を立てる設計こそが、無限ループを防ぎ、堅牢なロジックを構築する唯一の道だ。

—

3. 実戦配備:文脈判定ロジックを組み込んだプロダクションコード

以下のコードは、特定のキーワード(例:「重要」)を検索し、その前後の20文字を取得して「特定の文言が含まれる場合のみ」処理を行う、実戦的なテンプレートだ。

Option Explicit

”’

”’ 特定のキーワードを検索し、その前後の文脈から判定を行ってハイライトする
”’

Public Sub ContextualSearchAutomation()
Dim targetDoc As Document
Set targetDoc = ActiveDocument

Dim searchRange As Range
Set searchRange = targetDoc.Content ‘ 文書全体をターゲットにする

Dim keyword As String
keyword = “重要” ‘ 検索したいキーワード

‘ Findオブジェクトの設定
With searchRange.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = keyword
.Forward = True
.Wrap = wdFindStop ‘ 検索が末尾に達したら停止
.Format = False
.MatchCase = False
.MatchWholeWord = False
End With

‘ ———————————————————
‘ 検索実行ループ
‘ ———————————————————
Do While searchRange.Find.Execute
‘ ヒットしたRangeを破壊しないよう、複製して「文脈解析用Range」を作る
Dim contextRange As Range
Set contextRange = searchRange.Duplicate

‘ — 文脈の取得ロジック —
‘ ヒット箇所の前20文字、後ろ20文字まで範囲を広げる
‘ MoveStartは負の値で「前」へ、MoveEndは正の値で「後ろ」へ動く
contextRange.MoveStart Unit:=wdCharacter, Count:=-20
contextRange.MoveEnd Unit:=wdCharacter, Count:=20

‘ 取得したテキストのクリーニング(改行コードなどを除去して判定しやすくする)
Dim contextText As String
contextText = Replace(contextRange.Text, vbCr, ” “)

‘ — インテリジェントな判定 —
‘ 例えば、前後の文脈に「機密」という言葉が含まれている場合のみ処理する
If InStr(contextText, “機密”) > 0 Then
‘ 判定に合格した箇所だけ書式を変更する
searchRange.HighlightColorIndex = wdYellow

‘ ここでログ出力やデータベース連携(ADODB)の呼び出しを行うのが定石
Debug.Print “Found with context: ” & contextText
End If

‘ 次の検索のために、Rangeの開始点をヒット箇所の直後に移動させる
‘ これを忘れると無限ループに陥るリスクがある
searchRange.Collapse Direction:=wdCollapseEnd
Loop

MsgBox “解析が完了しました。”, vbInformation
End Sub

アーキテクトの視点:なぜこのコードは「堅牢」なのか

1. `wdFindStop` の採用: デフォルトの `wdFindContinue` は文書の先頭に戻って検索を続ける。これは意図しない無限ループの温床だ。プロは必ず制御を自分で行う。
2. `Collapse` メソッド: `searchRange.Collapse wdCollapseEnd` を実行することで、検索のポインタを「見つかった単語のすぐ後ろ」へ移動させている。これにより、検索範囲が確実に前進する。
3. 負の `MoveStart`: `MoveStart` にマイナスの値を渡すことで、Rangeの開始点を文書の先頭方向へ押し戻している。これはWord VBA独自の挙動であり、習得必須のテクニックだ。

—

4. 外部データ(CSV/DB)連携への拡張

実務レベルのツールでは、検索キーワードをソースコードにベタ書きすることはない。

  • CSV連携: `Open` ステートメントや `FileSystemObject` でキーワードリストを読み込み、配列に格納してループさせる。
  • DB連携: `ADODB.Connection` を使い、SQLで判定基準(前後の除外キーワードなど)を取得する。

ここで注意すべきは、「Wordのオブジェクトモデル操作」と「外部データアクセス」を分離することだ。文脈判定ロジックを `Function` として切り出し、引数に `contextText` を渡して `Boolean` を返す設計にせよ。

—

5. 運用上の注意点と限界

このテクニックを用いる際、避けては通れない壁がある。

1. 文書の境界: 文書の先頭付近で `MoveStart -20` を行うと、Rangeは自動的に文書の先頭(Start=0)で止まる。エラーにはならないが、取得できる文字数が少なくなる点は考慮せよ。
2. パフォーマンス: 数千ページの文書でこれを行う場合、Rangeの生成コストが積み重なる。必要に応じて、セクション単位やパラグラフ単位で検索範囲を限定するチューニングが必要だ。
3. ワイルドカード(正規表現)との併用: Wordの `MatchWildcards = True` は強力だが、VBAの `RegExp` オブジェクト(Microsoft VBScript Regular Expressions 5.5)ほど柔軟ではない。複雑な文脈判定が必要なら、一度Rangeからテキストを吸い出し、VBA側の正規表現エンジンで判定を行う方が保守性は高まる。

—

結論

Word VBAをマスターするとは、単にメソッドを暗記することではない。「Rangeという名のポインタを、いかに文書構造の中で精密に踊らせるか」を理解することだ。

`Duplicate` で分身を作り、`MoveStart/End` で周囲を索敵し、条件に合致したときのみトリガーを引く。この一連の動作が、あなたのツールを「初心者レベル」から「プロダクトレベル」へと昇華させる。

このコードをベースに、自社の業務に合わせた最強の検閲・校正・抽出ツールを構築してほしい。健闘を祈る。

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