【入門編】Wordの『ストーリー範囲』を再考する:MainTextStory以外のテキストを安全に一括取得する – Word VBA解析バイブル

スポンサーリンク

こんにちは!Word VBAの世界へようこそ。
マクロの記録ボタンを押して、生成されたコードを眺めてみたものの、「なんだこれ? わけがわからない…」と途方に暮れていませんか?

大丈夫、安心してください。今日ここでお話しする「Wordの裏側の仕組み」を理解すれば、あなたのWord VBAスキルは一気にプロの領域へとステップアップします。

今回は、多くの人がハマる「Wordの隠されたテキストを漏れなく安全に操る方法」について、徹底的に解説していきます。ここをクリアすれば、Word VBAの基本はバッチリですよ!

1. Word VBA最大の罠:なぜ「本文」だけでは不十分なのか?

みなさんは、WordVBAで文書内の文字を置換したり、特定のキーワードを検索したりするとき、なんとなく次のようなコード書いていませんか?

‘ よくある初心者コード(実は危険!)
ActiveDocument.Content.Find.Execute FindText:=”古い文字”, ReplaceWith:=”新しい文字”

一見、これで文書全体の置換ができているように思えますよね。しかし、チーフアーキテクトである私から言わせれば、これは「氷山の一角だけを削っている状態」です。

Wordのキャンバスは、私たちが普段文字を入力している白い紙(本文)だけではありません。

  • ヘッダーやフッター
  • ページ番号
  • 図形(テキストボックス、吹き出し)
  • 脚注やコメント

これらはすべて、Wordの内部構造では「別々のストーリー(Story)」として管理されています。つまり、先ほどのコードでは、図形の中やヘッダーの中にある文字は一文字たりとも置換されないのです。

「図形の中の文字が置換できなかった…」と悩んだ経験はありませんか? 原因はこれです。Word VBAを制するためには、この「ストーリー」の概念を絶対に避けて通れません。

2. Wordの「ストーリー範囲」構造をビジュアルで理解する

Wordドキュメントは、いわば「独立した部屋(Story)のマンション」のようなものです。

[ Document (マンション全体) ]
├── 1. MainTextStory (101号室:通常の本文)
├── 2. HeaderStory (102号室:ヘッダー)
├── 3. FooterStory (103号室:フッター)
└── 4. 形状の部屋群(Shape / TextFrame)
├── 図形Aの中のテキスト
└── 吹き出しBの中のテキスト

`ActiveDocument.Content` が指しているのは、実は「101号室(MainTextStory)」だけです。だから、他の部屋にあるテキストにアクセスするには、それぞれの部屋の扉をノックして、中に入る手続きを踏まなければなりません。

3. 実装:すべてのストーリーを網羅し、安全にテキストを取得・置換するコード

では、すべてのストーリー(MainTextStoryだけでなく、ヘッダー・フッター、そして図形の中身まで!)を漏れなく巡回し、安全に一括処理を行うためのプロフェッショナルなコードをお見せしましょう。

このコードは、現場ですぐにコピー&ペーストして使える実用的なものです。

Sub MasterStorySearchAndReplace()
Dim oStoryRange As Range
Dim oShape As Shape
Dim targetWord As String
Dim replaceWord As String

‘ 置換前後の文字列を設定
targetWord = “社外秘”
replaceWord = “【閲覧注意】”

‘ —————————————————————–
G
‘ —————————————————————–
For Each oStoryRange In ActiveDocument.StoryRanges

‘ 冗長なループやエラーを防ぐためのループ開始
Do
‘ 実際の検索・置換処理
With oStoryRange.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = targetWord
.Replacement.Text = replaceWord
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchCase = False
.MatchWholeWord = False
.MatchWildcards = False
.Execute Replace:=wdReplaceAll
End With

‘ 次の連結されたストーリー(セクション違いのヘッダー等)へ移動
Set oStoryRange = oStoryRange.NextStoryRange
Loop Until oStoryRange Is Nothing

Next oStoryRange

‘ —————————————————————–
‘ 2. 【最難関】図形(Shape)内のテキストストーリーを攻略する
‘ —————————————————————–
For Each oShape In ActiveDocument.Shapes
‘ 図形の中にテキストフレーム(文字が入る空間)があるかチェック
If oShape.TextFrame.HasText Then
With oShape.TextFrame.TextRange.Find
.ClearFormatting
.Replacement.ClearFormatting
.Text = targetWord
.Replacement.Text = replaceWord
.Forward = True
.Wrap = wdFindContinue
.Execute Replace:=wdReplaceAll
End With
End If
​Next oShape

‘ 画面に完了を通知
MsgBox “すべてのストーリー領域(本文・ヘッダー・図形内)の置換が完了しました!”, vbInformation, “処理完了”
End Sub

4. コードの深掘り:なぜこの書き方なのか?

初心者から脱却するために、上記のコードの「重要なポイント」をいくつか解説しておきましょう。

① `StoryRanges` コレクションの罠

`ActiveDocument.StoryRanges` を使うと、本文、ヘッダー、フッター、脚注などを一網打尽にループできます。しかし、これだけでは「セクションごとに分かれたヘッダー」を取りこぼすことがあります。
そのため、`Do … Loop Until oStoryRange Is Nothing` という構文を挟み、繋がっているストーリーの鎖を最後まで手繰り寄せる工夫をしています。これが、エラーを出さずに確実に全域を走査するプロの技です。

② なぜ `Shapes` を別枠で回すのか?

実は、Wordの図形(Shape)の中にあるテキストは、先ほどの `StoryRanges` の中には含まれません。図形はドキュメントの「上に浮いているオブジェクト」だからです。
そのため、文書内のすべての図形を `For Each oShape In ActiveDocument.Shapes` で舐め回し、文字が存在する場合 (`HasText`) のみ、その中にある `TextRange` に対して同様の置換処理を行っています。

5. 陥りやすいエラーと注意点

最後に、現場で開発する際によくあるハマりどころをシェアします。

  • グループ化された図形(GroupShape)のエラー

今回紹介したコードは単体の `Shape` を対象にしています。もしユーザーが図形をグループ化している場合、その中にあるテキストは通常の `Shapes` コレクションからは取得できません(`GroupItems` を再帰的に回す必要があります)。複雑な図形が多い文書を扱う場合は注意してください。

  • 画面のチラつきとパフォーマンス

大量のストーリーや図形がある場合、マクロ実行中に画面がパカパカと切り替わることがあります。処理の最初に `Application.ScreenUpdating = False` を入れ、最後に `True` に戻すお呪い(定石)を入れると、実行速度が劇的に向上します。

まとめ

いかがでしたでしょうか?
「Wordのテキスト=本文(MainTextStory)」という思い込みを捨て、裏側に隠されたストーリーや図形の世界まで視野を広げることで、あなたの書くマクロは「おもちゃ」から「実用的な業務自動化ツール」へと生まれ変わります。

オブジェクトの構造を正しく理解し、コントロールする快感をぜひ味わってみてください。
それでは、次のステップでお会いしましょう!

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