Word VBAの「暴走」を止める。選択範囲(Selection)を制する検索・置換術
こんにちは。VBAの世界へようこそ。
マクロの記録でコードを書き始めた皆さんが、次に直面するのが「検索と置換の制御」という壁です。
「特定の段落だけ変えたいのに、なぜか文書全体が書き換わってしまった……」
「置換したはずなのに、カーソル位置が勝手に飛んでいく……」
そんな経験はありませんか?
今日は、Word VBAにおける `Find` オブジェクトの「特性」を理解し、「選択範囲(Selection)内だけで安全に処理を完結させる」ための極意を伝授します。ここをクリアすれば、あなたのマクロは「初心者向け」から「業務自動化ツール」へと確実に進化します。
—
1. なぜ「文書全体」が書き換わってしまうのか?
Wordの `Find` オブジェクトは、デフォルトでは「文書の末尾まで検索し、見つからなければ文書の先頭に戻ってループする」という設計になっています。
マクロの記録で生成されるコードは、この強力すぎるパワーをそのまま引き継いでしまいます。これを「選択範囲だけに限定」するには、`Find` オブジェクトの `Wrap` プロパティを正しく制御する必要があります。
—
2. 安全な置換を実現する「魔法のテンプレート」
まずは、こちらのコードをご覧ください。これが、誤置換を防ぐための最も標準的かつ安全な書き方です。
Sub SafeReplaceInSelection()
‘ 選択範囲がない場合は即座に終了するガード節
If Selection.Type = wdSelectionIP Then
MsgBox “文字を選択してから実行してください。”, vbExclamation
Exit Sub
End If
‘ Findオブジェクトへの参照をスマートに取得
With Selection.Find
.ClearFormatting ‘ 検索条件の書式をリセット
.Replacement.ClearFormatting ‘ 置換後の書式をリセット
.Text = “古い文字列” ‘ 検索する文字列
.Replacement.Text = “新しい文字列” ‘ 置換後の文字列
.Forward = True ‘ 前方(カーソル位置から後ろ)に向かって検索
.Wrap = wdFindStop ‘ 【重要】選択範囲の末尾で停止する(全体検索を防ぐ)
.Format = False ‘ 書式設定を無視
.MatchCase = False ‘ 大文字小文字の区別をしない
.MatchWholeWord = False ‘ 単語の一部でもヒットさせる
‘ 置換実行(wdReplaceAll: 一括置換)
.Execute Replace:=wdReplaceAll
End With
MsgBox “選択範囲内の置換が完了しました。”, vbInformation
End Sub
このコードの「本質」を理解する
- `Wrap = wdFindStop`: これが今回の主役です。`wdFindContinue`(文書全体を循環)ではなく `wdFindStop` を指定することで、検索の範囲を「選択範囲の終わり」で強制的に打ち止めにします。
- `.ClearFormatting`: これを忘れると、前回検索した時の「太字」や「赤字」といった設定が残ったままになり、意図しない検索結果を生む原因になります。検索前には必ずリセットするのがプロの嗜みです。
- ガード節: `If Selection.Type = wdSelectionIP` は、カーソルが「点」として存在している(=何も選択していない)場合にマクロを止めます。不要な誤爆を防ぐための安全装置です。
—
3. 陥りやすい「罠」と解決策
罠その1:置換後に選択範囲が解除される
`Execute Replace:=wdReplaceAll` を実行すると、Wordの仕様で選択範囲(Selection)が置換後の文字列の末尾に移動したり、解除されたりすることがあります。
もし「置換後も元の範囲を選択し続けたい」場合は、処理の前後で `Range` オブジェクトを使って開始位置と終了位置を記憶しておくテクニックが必要です。
罠その2:非表示の「制御文字」に注意
Word文書には、スペースやタブ、改行などの制御文字が隠れています。`MatchWildcards = True`(ワイルドカード使用)を使う場合は、これらを意識しないと検索にヒットしません。「まずは通常の検索で確実に動かす」のが、デバッグの近道です。
—
4. ステップアップのためのアドバイス
今回のコードをマスターしたら、次は 「Rangeオブジェクト」 を使った処理に挑戦してみてください。
`Selection` は「画面上でユーザーが見ているカーソル」を操作するため、処理のたびに画面がチラついたり、動作が遅くなったりします。一方で `Range` は「画面上のカーソルとは無関係に、文書の裏側でメモリ上に操作範囲を定義する」ため、より高速で堅牢なツールが作れます。
今日のまとめ
1. `Wrap = wdFindStop` を設定し、検索の暴走を止める。
2. `ClearFormatting` で検索条件を常にクリーンに保つ。
3. 「何も選択されていない状態」を想定したガード節を書く。
この3つを守るだけで、あなたのVBAは劇的に「信頼できるコード」に変わります。焦る必要はありません。一つひとつのオブジェクトが何をしているのかを意識しながら、ぜひ自分のエディタに書き写してみてくださいね。
また次の講義で、さらに深いVBAの世界を覗いていきましょう!
