こんにちは! Word VBAの世界へようこそ。
マクロの記録ボタンを押して、生成されたコードを眺めてみたものの、「なんだこれ、意味がわからない……」「選んだはずの文字が置換できない……」と途方に暮れていませんか?
大丈夫です。その壁は、すべてのWord VBAエンジニアが最初に通る道です。
今日は、Word VBAにおける最大の「罠」であり、同時にここさえ突破すれば一生モノの武器になる『ストーリーの概念』と、ヘッダー・フッター・本文を網羅する一括置換の極意を伝授します。
ここをクリアすれば、あなたのWord VBAスキルは「マクロの記録の奴隷」から「ドキュメントを意のままに操るアーキテクト」へと一気に進化します。一緒にマスターしていきましょう!
—
1. なぜ「本文の置換」だけでは不十分なのか?
Excel VBAであれば、シート全体を一括置換するのは `Cells.Replace` を使えば一瞬です。だから、多くの人がWordでも同じように考えます。
‘ 【よくある誤ったアプローチ】
ActiveDocument.Content.Find.Execute FindText:=”旧社名”, ReplaceWith:=”新社名”, Replace:=wdReplaceAll
おめでとうございます。このコードを実行すると、本文(Main Document)の「旧社名」は綺麗に「新社名」に変わります。
……しかし、ヘッダーやフッター、そして表のセルや脚注に隠れている「旧社名」はそのまま残されています。
なぜでしょう?
それは、Wordの文書(Document)が、私たちが普段見ている1枚の紙のように見えて、内部構造的には「複数の独立したカンバス(=ストーリー)」の集合体として管理されているからです。
Word内部の「ストーリー」構造を理解しよう
Wordの文書は、以下のような異なる「部屋(Story)」に分かれています。
[ ActiveDocument ]
┣ 1. 本文ストーリー (wdMainTextStory)
┣ 2. ヘッダー・フッター ストーリー (wdPrimaryHeaderStory, wdFirstPageHeaderStory 等)
┣ 3. 脚注・文末脚注ストーリー (wdFootnotesStory 等)
┗ 4. コメント・テキストボックス など
Excelが「表計算のグリッド」であるのに対し、Wordは「領域のパッチワーク」です。
そのため、本文だけを対象にした `ActiveDocument.Content` や `Selection` で置換をかけても、ヘッダーの部屋には魔法が届かないのです。
—
2. すべての部屋を巡回する:`StoryRanges` ループの基礎
すべての「部屋」をもれなく掃除(置換)するためには、Wordが提供する `StoryRanges`(ストーリー範囲のコレクション) をループで回す必要があります。
先輩エンジニアとして、まず最初にあなたに知ってほしい基本のコードがこちらです。
Sub InspectStories()
Dim st As Range
‘ 文書内のすべてのストーリーを巡回する
For Each st In ActiveDocument.StoryRanges
Debug.Print “ストーリーの種類: ” & st.StoryType
Next st
End Sub
これを実行すると、イミディエイトウィンドウに「1」「5」「6」といった数値が出力されます。これがWordのストーリーの種類を表すID(`WdStoryType`列挙体)です。
「よし、じゃあこの `StoryRanges` に対してそのまま `.Find.Execute` を回せば完璧だな!」と思ったあなた……。
実は、ここにWord VBA最大の罠が潜んでいます。
—
3. 【最重要】StoryRangesループで絶対に陥る「2つの罠」
甘い罠に飛び込む前に、プロの現場で必ず問題になる2つの仕様を知っておいてください。
罠その1:リンクされたヘッダー・フッターの無視
Wordには「前のセクションと同じ」というヘッダーの連動機能があります。`StoryRanges` を単純にループさせると、文書内の最初のセクションしかヒットせず、2ページ目以降のセクションにあるヘッダー・フッターがスキップされるという冷酷な仕様があります。
罠その2:リンク切れパニック(Runtime Error 5852)
もし文書内に「前のセクションと同じではない(リンクされていない)」ヘッダーや、複数のセクションが存在する場合、単純な `For Each` ループの中で `.Next` プロパティなどを安易に操作すると、「指定されたオブジェクトは利用できません」という実行時エラー5852が一発レッドカードのように飛び出します。
—
4. すべてを解決する最適解:Range連鎖とエラーハンドリング
では、どうすればヘッダー・フッター・本文を「もれなく、安全に」一括置換できるのでしょうか?
答えは、「ストーリーの連結(`.NextStoryRange`)をたどりながら、エラーを完全にコントロールする」ことです。
以下のコードは、実務の現場で私が実際に使っている、極めて堅牢な一括置換のテンプレートです。そのままコピーして使っていただけます。
Sub UltimateReplaceAcrossStories()
Dim rngStory As Range
Dim targetText As String
Dim replaceText As String
‘ 置換する文字列の定義
targetText = “旧テキスト”
replaceText = “新テキスト”
‘ 画面描画を停止してマクロの実行速度を爆発的に上げる(お約束のテクニック)
Application.ScreenUpdating = False
‘ すべてのストーリー範囲をループ処理
For Each rngStory In ActiveDocument.StoryRanges
‘ 連結されたストーリー(セクション違いのヘッダーなど)をくまなく辿るためのループ
Do
‘ 実際の置換処理を実行
With rngStory.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = targetText
.Replacement.Text = replaceText
.Forward = True
.Wrap = wdFindContinue
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
‘ 一括置換の実行
.Execute Replace:=wdReplaceAll
End With
‘ 次の連鎖ストーリーが存在するかチェックし、あればrngStoryを更新
Set rngStory = rngStory.NextStoryRange
Loop Until rngStory Is Nothing
Next rngStory
‘ 画面描画を復元
Application.ScreenUpdating = True
MsgBox “すべてのストーリー(本文・ヘッダー・フッター)の置換が完了しました!”, vbInformation
End Sub
このコードの美しさと優しさのポイント
1. `Do … Loop Until rngStory Is Nothing` の構造
セクションが変わることで途切れてしまうヘッダーやフッターの鎖(連鎖)を、`NextStoryRange` を使って文字通り「端から端まで」一本釣りで追いかけます。
2. `Application.ScreenUpdating = False` による高速化
Word VBAは画面を書き換えるたびに重くなります。この1行を入れることで、目にも止まらないスピードで処理が完了します。
3. 安全なオブジェクト管理
変数 `rngStory` が正しくRangeを引き継ぐため、メモリリークや予期せぬエラーを防ぎます。
—
5. まとめ:ここをクリアすればWord VBAは怖くない!
お疲れ様でした! 本日は以下の極意を学びました。
- Wordは「複数のストーリー(部屋)」の集合体である。
- 本文だけの置換では、ヘッダーやフッターを取りこぼしてしまう。
- `StoryRanges` と `NextStoryRange` の連鎖を組み合わせることで、すべての領域をもれなく安全に一括置換できる。
Word VBAは、Excelとは違った独自の「癖」を持っていますが、その構造さえ理解してしまえば、事務作業の自動化においてこれほど頼もしい相棒はいません。毎回のコピペ作業から解放され、よりクリエイティブな仕事に集中できるようになりますよ。
ここをクリアしたあなたなら、もうWord VBAの基本はバッチリです!
ぜひ、実際の業務データで試してみてくださいね。エンジニアとしてのあなたの活躍を、心から応援しています!
