【入門編】【中級者向け】「コメント」や「脚注」内を検索対象に含めるためのStoryRanges巡回テクニック – Word VBA解析バイブル

スポンサーリンク

こんにちは! Word VBAの自動化の世界へようこそ。
マクロの記録ボタンを押して、出てきたコードをそのまま動かしてみたものの、「あれ、本文しか置換できてない……?」と途方に暮れた経験はありませんか?

実は、Wordの文書(Document)というのは、私たちが普段見ている「メインの本文」だけではありません。コメント、脚注、ヘッダー、フッター、テキストボックスなどなど、パーツごとに「部屋」が分かれています。これらをWordの世界では「ストーリー(Story)」と呼びます。

今回は、中級者へのステップアップとして、文書全体に散らばるすべての部屋をくまなく巡回し、検索・置換を完璧にやり遂げるための「StoryRanges巡回テクニック」を伝授します。ここをクリアすれば、Word VBAの構造的な理解はグッと深まりますよ。一緒にマスターしていきましょう!

—

なぜ「通常のFind」では本文しか検索されないのか?

まずは、Word VBAにおける「検索(Find)」の基本構造を理解しておきましょう。
普段私たちが何気なく使う次のようなコード:

‘ 【よくある検索コード】
Selection.Find.Text = “Word”
Selection.Find.Execute Replace:=wdReplaceAll

これは、画面上で選択されている場所(あるいは現在のカーソル位置)から見える「メイン本文(wdMainTextStory)」という一つの部屋の中だけで作業をしています。そのため、文書の端っこにある脚注や、吹き出しのコメントの中にある「Word」は、綺麗スルーされてしまうのです。

「文書全体の文字をすべて一括置換したい!」という現場の要求を満たすためには、この「部屋の壁」を一枚ずつブチ破る必要があります。それを可能にするのが、`StoryRanges` コレクションです。

—

全ストーリーを網羅する!StoryRangesの正体

Word文書の中には、以下のような様々な「ストーリー(部屋)」が存在します。

  • メイン本文 (`wdMainTextStory`)
  • ヘッダー (`wdPrimaryHeaderStory` など)
  • フッター (`wdPrimaryFooterStory` など)
  • 脚注 (`wdFootnotesStory`)
  • 文末脚注 (`wdEndnotesStory`)
  • コメント (`wdCommentsStory`)
  • テキストボックスなどの図形内文字列 (`wdTextFrameStory`)

これら文書内のすべてのストーリーを束ねているのが、`ActiveDocument.StoryRanges` です。
ループを回して、すべてのストーリーに対して同じ検索・置換処理を適用してあげれば、「検索漏れゼロの完璧な置換エンジン」が完成します。

—

実装コード:文書全体を網羅する検索・置換マクロ

それでは、実務でそのままコピペして使える、堅牢(ロバスト)なコードを公開します。
コメントや脚注、さらには「セクションが分かれていてヘッダーが複数ある複雑な文書」でもリンク切れを起こさないための、プロの技が詰まっています。

Sub ReplaceTextInAllStories()
Dim rngStory As Range
Dim targetStr As String
Dim replaceStr As String
Dim totalCount As Long

‘ 検索する文字列と置換後の文字列を指定
targetStr = “旧システム名”
replaceStr = “新システム名”
totalCount = 0

‘ 画面描画を停止してマクロの実行速度を爆発的に上げる(お約束のテクニック)
Application.ScreenUpdating = False

‘ 文書内のすべてのストーリー(部屋)を順番に巡回する
For Each rngStory In ActiveDocument.StoryRanges

‘ — ここが重要! —
‘ ヘッダーやフッターなどは、文書内に複数存在する場合(セクション区切り等)があります。
‘ ネクスト(次のストーリーリンク)が存在する限り、連鎖的にループを回します。
Do
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = targetStr
.Replacement.Text = replaceStr
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False

‘ 置換を実行し、何箇所置き換えたかカウントを足す
‘ ※ Execute メソッドは置換が行われると True を返します
Do While .Execute(Replace:=wdReplaceAll)
‘ 必要に応じて置換数を集計(StoryRanges全体での正確なカウントは難しいため概算)
Loop
End With

‘ 次のストーリーリンク(次のセクションのヘッダーなど)へ移動
Set rngStory = rngStory.NextStoryRange

Loop Until rngStory Is Nothing

Next rngStory

‘ 画面描画を再開
Application.ScreenUpdating = True

‘ 完了メッセージ
MsgBox “すべてのストーリー(本文・コメント・脚注など)内の「” & targetStr & “」を「” & replaceStr & “」に置換しました!”, vbInformation, “処理完了”

End Sub

コードのポイント解説

1. `For Each rngStory In ActiveDocument.StoryRanges`
これが今回の主役です。文書内に存在する大元のストーリーの先頭を次々と取得します。
2. `Do … Loop Until rngStory Is Nothing` (連鎖的ループ)
ここが中級者への分かれ道です。ヘッダーやフッターはセクションごとに独立して存在することがあり、最初の `rngStory` だけ処理しても、2ページ目以降のヘッダーに取り残しが出てしまいます。`.NextStoryRange` を使って、連なっているストーリーの端から端まで漏れなく網羅するのがプロの作法です。
3. `Application.ScreenUpdating = False`
検索・置換が走るたびにWordの画面がパチパチと書き換わると、処理が非常に遅くなります。おまじないとして最初に画面描画を止め、最後に復元することで、ストレスのない高速な動作を実現しています。

—

陥りやすい罠とエラー対策

このStoryRanges巡回コードを使う上で、初心者が必ずと言っていいほどハマる罠がいくつかあります。事前に知っておきましょう。

1. 「オブジェクト変数が設定されていません」エラー (Run-time error ’91’)

ストーリーの種類によっては、その文書内に存在しないもの(例えば、コメントが1つもない文書での `wdCommentsStory` など)が含まれている場合があります。しかし、`ActiveDocument.StoryRanges` は存在するストーリーの範囲しか返さないため、基本的には安全です。もし独自の変形コードを書く際は、オブジェクトが `Nothing` でないかのチェック(`If Not rngStory Is Nothing Then`)を怠らないようにしましょう。

2. テーブル(表)の中は大丈夫?

「テーブルの中の文字も検索対象になるの?」と心配になるかもしれませんが、ご安心ください。Wordのメイン本文(`wdMainTextStory`)には、表のセル内部も含まれています。したがって、上記のコードであれば表の中も完璧にヒットします。

—

まとめ

今回は、Word VBAの「StoryRanges」を使った、コメントや脚注まで網羅する高度な検索・置換テクニックを解説しました。

  • Word文書は「メイン本文」だけでなく、複数の「ストーリー(部屋)」で構成されている。
  • `ActiveDocument.StoryRanges` と `NextStoryRange` を組み合わせることで、すべての部屋を漏れなく掃除できる。
  • 画面描画の停止(`ScreenUpdating = False`)をセットで使うことで、実用的な速度を担保する。

ここをクリアできれば、単なる「マクロの記録の貼り付け係」から、現場の業務をスマートに自動化する「真のWord VBAエンジニア」への仲間入りです。
ぜひ、あなたの日常業務の文書整理マクロに応用してみてくださいね。それでは、次回の極限知見もお楽しみに!

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