Word文書で「Ch :」の直前にある4桁数字だけを、太字・赤字・ターコイズのハイライトで一括装飾したいのに、Selection(選択範囲)だと1件目は動いても全文の連続処理が安定しない――この手の悩みは、Range(範囲オブジェクト)で全文をスキャンする設計に切り替えると一気に解決します。
やりたいことを整理:Wordで「Ch :」の直前にある4桁数字だけを一括装飾する
今回のゴールはシンプルです。Word文書内で Ch :(C・h・半角スペース・コロン)を見つけたら、その直前(左側)にある「4桁の数字」(例:1234)を探し、見つかった数字だけに次の装飾を適用します。
- 太字
- 文字色:赤(
wdColorRed) - ハイライト:ターコイズ(
wdTurquoise)
ポイントは「Ch : 自体」ではなく、「Ch : の直前にある4桁数字」だけを狙い撃ちすることです。手動の範囲選択(F8)で最初の1件だけうまくいっても、同じことを文書全体で漏れなく繰り返すには、VBAの検索設計を“全文走査向け”に組み直す必要があります。
なぜSelectionでの処理は途中で止まりやすいのか
「SelectionでFindして、見つかったら左へ戻って数字を装飾する」やり方は、デバッグ中は動いて見えても、実運用で不安定になりがちです。理由は大きく3つあります。
- カーソル(選択位置)が移動し続けるため、表示がジャンプし、処理の進行が目視で追いづらい
- 検索の起点が“選択位置”に依存するため、装飾や選択変更の影響で次のFindがズレやすい
- 次の検索位置を正しく進めないと無限ループや見落としが起きる(特に「見つかった文字列の直前を探す」系)
| 観点 | Selection(選択範囲) | Range(範囲オブジェクト) |
|---|---|---|
| 画面の動き | カーソルが動く/画面が跳ねる | カーソルは動かない(静かに処理) |
| 安定性 | 選択状態に左右されやすい | オブジェクトで範囲を固定でき安定 |
| Findの進行管理 | 選択位置を手動で意識しがち | Range.Collapseで機械的に進めやすい |
| 運用向き | 単発処理向き | 全文一括処理向き |
つまり、今回のように「全文を連続処理したい」場合は、Selectionを捨ててRange中心に設計した方が、結果として短く・堅牢に書けます。
Rangeで「全文を安定スキャン」する基本方針
この問題の王道解は、次の発想です。
- 文書全体(
ActiveDocument.Content)をRangeとして用意し、Ch :を前方向に検索 Ch :が見つかったら、その開始位置より左側(手前)を別Rangeに切り出す- 切り出したRangeを後ろ方向(
Forward = False)に検索し、ちょうど4桁の数字を探す - 見つかった4桁数字に装飾(太字・赤・ターコイズ)を適用
Ch :の検索RangeをCollapseで末尾へ進めて次を探す
ここで重要なのが「4桁数字の探し方」です。Wordのワイルドカード検索を使い、< >(単語境界)を付けておくと、12345 の中の 1234 を拾うような事故を減らせます。
- 使う検索パターン例:
<[0-9]{4}>
Wordのワイルドカードは正規表現と似ていますが別物です。ただ、今回の「4桁固定」程度なら素直に使えます。
まずは動く:最小構成のサンプル(Range+後方検索)
質問内容の核にあたる「Rangeで全文処理する」考え方を、そのまま実用に寄せた最小コードです。ポイントは、Findの設定を毎回きちんと指定し、検索のWrapを止めること(wdFindStop)です。
Option Explicit
Sub Format4DigitsBeforeCh_Basic()
Dim rngCh As Range
Set rngCh = ActiveDocument.Content
' 「Ch :」を全文から前方向に検索
With rngCh.Find
.ClearFormatting
.Text = "Ch :"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = False
End With
Do While rngCh.Find.Execute
' 見つかった「Ch :」の手前(左側)を対象にRangeを作る
Dim rngNum As Range
Set rngNum = ActiveDocument.Range(Start:=0, End:=rngCh.Start)
' 手前側を後方検索して「ちょうど4桁の数字」を探す
With rngNum.Find
.ClearFormatting
.Text = "<[0-9]{4}>"
.Forward = False
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
End With
' 見つかった4桁数字に装飾
If rngNum.Find.Execute Then
rngNum.Font.Bold = True
rngNum.Font.Color = wdColorRed
rngNum.HighlightColorIndex = wdTurquoise
End If
' 次の「Ch :」へ進める
rngCh.Collapse wdCollapseEnd
rngCh.End = ActiveDocument.Content.End
Loop
End Sub
最後の2行が地味に大事です。rngCh.Collapse で検索開始点を進めたあと、rngCh.End を文書末尾に戻しています。これを省略すると、環境や文書構造によっては「次が見つからない」「途中で止まる」原因になります。
このコードの動作イメージ
文書内に次のような並びがあるとします。
1234 Ch : 1
5678 Ch : 2
9012 Ch : 3
各 Ch : を見つけるたびに、その左側を後方検索して最も近い4桁数字(1234/5678/9012)を拾い、装飾します。
誤ヒット対策:「直前○文字」だけを対象にして“本当に直前”を拾う
基本版のままだと、状況によっては「Ch : からかなり離れた4桁数字」を拾うことがあります。例えば、同じ段落内に4桁数字が複数ある文書、表の中に別の4桁がある文書などです。
そこで実用面でおすすめなのが、検索範囲を“直前N文字”に制限する方法です。たとえば「Ch : の直前50文字だけ」を対象にすれば、“直前”の意味がかなり人間の感覚に近づきます。
| 方式 | 対象範囲 | メリット | 注意点 |
|---|---|---|---|
| 全文手前を後方検索 | 文頭〜Ch : の直前 | 実装が単純 | 遠い数字を拾う可能性 |
| 直前N文字だけ後方検索 | Ch : の直前N文字 | 誤ヒットが減る/「直前」に強い | Nが小さすぎると拾えない |
直前50文字に制限した例です(実務向けのバランスが良いことが多いです)。
Option Explicit
Sub Format4DigitsBeforeCh_Context50()
Const CONTEXT_LEN As Long = 50
Dim rngCh As Range
Set rngCh = ActiveDocument.Content
With rngCh.Find
.ClearFormatting
.Text = "Ch :"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = False
End With
Do While rngCh.Find.Execute
Dim chPos As Long
chPos = rngCh.Start
Dim leftStart As Long
leftStart = chPos - CONTEXT_LEN
If leftStart < 0 Then leftStart = 0
Dim rngNum As Range
Set rngNum = ActiveDocument.Range(Start:=leftStart, End:=chPos)
With rngNum.Find
.ClearFormatting
.Text = "<[0-9]{4}>"
.Forward = False
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
End With
If rngNum.Find.Execute Then
rngNum.Font.Bold = True
rngNum.Font.Color = wdColorRed
rngNum.HighlightColorIndex = wdTurquoise
End If
rngCh.Collapse wdCollapseEnd
rngCh.End = ActiveDocument.Content.End
Loop
End Sub
「50文字」に正解はありません。文書の構造次第なので、4桁数字とCh : の距離がどれくらいかを基準に、30/50/100あたりで調整すると現場でハマりにくいです。
表記ゆれ対応:「Ch:」「Ch :」「CH :」をまとめて拾う
実際の文書では Ch:(スペースなし)や、全角スペースが混ざるケースもあります。これを全部拾うなら、検索側をワイルドカードにするのが簡単です。
例として、以下のパターンを拾う設計にします。
Ch:Ch :CH :(大文字混在)Ch :(全角スペース)
Wordのワイルドカードで、Ch の大文字小文字を許容し、スペース(半角・全角)を0〜3文字許容する例です。
Option Explicit
Sub Format4DigitsBeforeCh_Variations()
Const CONTEXT_LEN As Long = 80
Dim rngCh As Range
Set rngCh = ActiveDocument.Content
' Ch の表記ゆれ対応(ワイルドカード)
With rngCh.Find
.ClearFormatting
.Text = "[Cc][Hh][ ]{0,3}:"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
End With
Do While rngCh.Find.Execute
Dim chPos As Long
chPos = rngCh.Start
Dim leftStart As Long
leftStart = chPos - CONTEXT_LEN
If leftStart < 0 Then leftStart = 0
Dim rngNum As Range
Set rngNum = ActiveDocument.Range(Start:=leftStart, End:=chPos)
With rngNum.Find
.ClearFormatting
.Text = "<[0-9]{4}>"
.Forward = False
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
End With
If rngNum.Find.Execute Then
rngNum.Font.Bold = True
rngNum.Font.Color = wdColorRed
rngNum.HighlightColorIndex = wdTurquoise
End If
rngCh.Collapse wdCollapseEnd
rngCh.End = ActiveDocument.Content.End
Loop
End Sub
注意点として、Findの設定(特にMatchWildcards)は“前回の値が残る”ことがあります。途中で別マクロを動かしたあとに挙動が変わるのはこのせいが多いので、上のように「使うFindごとに必要なプロパティを全部指定」する書き方が安全です。
もっと精度を上げる:1回のFindで「4桁+Ch :」を掴んで数字だけ装飾する
「Ch : を見つけてから左に戻る」方式は分かりやすい反面、文書構造によっては“直前とは別の4桁”を拾う可能性が残ります。これをさらに減らすなら、検索条件を次のように設計します。
- 「4桁数字」+「(0〜数文字の空白)」+「Ch :(表記ゆれ込み)」
- この塊が見つかったら、塊の先頭4文字(数字部分)だけをRangeで切って装飾
つまり「直前を探す」のではなく、「最初からセットで一致させる」発想です。実務ではこちらの方が誤ヒットがさらに減ります。
Option Explicit
Sub FormatDigitsBySingleFind()
Dim rng As Range
Set rng = ActiveDocument.Content
' 4桁 + 空白(0〜3) + Ch(表記ゆれ) + 空白(0〜3) + :
' 例:1234 Ch : / 1234Ch: / 1234 CH :
With rng.Find
.ClearFormatting
.Text = "<[0-9]{4}[ ]{0,3}[Cc][Hh][ ]{0,3}:"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
End With
Do While rng.Find.Execute
' 見つかった塊の先頭4文字(=数字)だけを装飾
Dim rngDigits As Range
Set rngDigits = rng.Duplicate
rngDigits.End = rngDigits.Start + 4
rngDigits.Font.Bold = True
rngDigits.Font.Color = wdColorRed
rngDigits.HighlightColorIndex = wdTurquoise
' 次へ
rng.Collapse wdCollapseEnd
rng.End = ActiveDocument.Content.End
Loop
End Sub
この方式のメリットは、後方検索が不要になることです。検索範囲を切り出す手間が減り、処理速度も上がりやすいです。特に「数字とChが必ず近い(ほぼ隣接している)」文書なら、こちらが最適解になりやすいです。
| 観点 | Chを見つけて後方検索 | 4桁+Chを一括でFind |
|---|---|---|
| 分かりやすさ | 直感的(左に戻る) | パターン設計が必要 |
| 誤ヒット耐性 | 範囲制限しないと誤ヒットしやすい | かなり強い(セット一致) |
| 速度 | 後方検索が入る分やや不利 | 比較的速い |
| 表記ゆれ | Ch側のFindで対応 | パターン内でまとめて対応 |
Find設定のチェック:安定させるために押さえるべき項目
Word VBAのFindは、ExcelのFindより「前回の設定が残る」影響が大きく出やすい印象があります。以下の項目は、毎回明示するのがおすすめです。
| プロパティ | 意味 | 推奨 | ハマりポイント |
|---|---|---|---|
| .Text | 検索文字列 | 必ず設定 | 前回の.Textが残って別条件で走る |
| .MatchWildcards | ワイルドカードON/OFF | 必ず設定 | ONのまま通常文字列検索すると一致しないことがある |
| .Forward | 検索方向 | 目的に応じて明示 | 後方検索のまま次の検索が始まると挙動が混乱 |
| .Wrap | 終端で折り返すか | wdFindStop | wdFindContinueだと“戻って再検索”で無限ループの温床 |
| .ClearFormatting | 書式条件をクリア | 毎回呼ぶ | 書式検索が混ざって急に見つからなくなる |
| .Format | 書式条件を使うか | False | Trueのままだと書式一致が必要になりヒットしない |
ヘッダー/フッターや脚注にもある場合:StoryRangesを回す考え方
ActiveDocument.Content は「本文(メインストーリー)」だけを対象にします。もし Ch : がヘッダー・フッター・脚注・文末脚注などにも登場するなら、StoryRanges を回して各ストーリーごとに処理するのが定石です。
ただし、テキストボックス(図形のテキスト)まで完全にカバーするには追加処理が必要になるため、まずは「ヘッダー/フッター/脚注まで」を対象にする例を載せます。
Option Explicit
Sub Format4DigitsBeforeCh_AllStories()
Dim rngStory As Range
For Each rngStory In ActiveDocument.StoryRanges
Call Format4DigitsBeforeCh_InRange(rngStory, 80)
Next rngStory
End Sub
Private Sub Format4DigitsBeforeCh_InRange(ByVal targetRange As Range, ByVal contextLen As Long)
Dim rngCh As Range
Set rngCh = targetRange.Duplicate
With rngCh.Find
.ClearFormatting
.Text = "[Cc][Hh][ ]{0,3}:"
.Forward = True
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
End With
Dim storyEnd As Long
storyEnd = targetRange.End
Do While rngCh.Find.Execute
Dim chPos As Long
chPos = rngCh.Start
Dim leftStart As Long
leftStart = chPos - contextLen
If leftStart < targetRange.Start Then leftStart = targetRange.Start
Dim rngNum As Range
Set rngNum = ActiveDocument.Range(Start:=leftStart, End:=chPos)
With rngNum.Find
.ClearFormatting
.Text = "<[0-9]{4}>"
.Forward = False
.Wrap = wdFindStop
.Format = False
.MatchWildcards = True
End With
If rngNum.Find.Execute Then
rngNum.Font.Bold = True
rngNum.Font.Color = wdColorRed
rngNum.HighlightColorIndex = wdTurquoise
End If
rngCh.Collapse wdCollapseEnd
rngCh.End = storyEnd
Loop
End Sub
ここでも「CollapseしたあとEndを戻す」点は同じです。StoryRanges はストーリーごとにEndが違うので、targetRange.End を保存しておくのが安全です。
実運用向けの仕上げ:安全・高速に動かすコツ
マクロは「動く」だけでなく「事故らない」ことも重要です。特に全文一括で書式変更するマクロは、実行前後の配慮で安心感が大きく変わります。
実行前におすすめの準備
- まずはコピーした文書で動作確認する(本番ファイル直叩きは避ける)
- Wordの変更履歴が有効な場合、意図せず大量の変更履歴が残ることがあるので運用方針を決めておく
- 文書内に「Ch :」が多い場合は、先に検索で分布を把握しておく(想定外の箇所を装飾しないため)
高速化・安定化の小技
- 画面更新を止める(体感速度が上がることが多い)
- 検索範囲を必要最小限にする(直前N文字制限や、1回Find方式)
- Find設定を毎回フル指定(別マクロの影響を受けにくくする)
画面更新を抑制する例です。処理の最後で必ず元に戻すのがポイントです。
Option Explicit
Sub Format4DigitsBeforeCh_SafeRun()
Dim prevUpdate As Boolean
prevUpdate = Application.ScreenUpdating
Application.ScreenUpdating = False
On Error GoTo EH
' 好きな方式を呼ぶ(例:1回Find方式)
Call FormatDigitsBySingleFind
SafeExit:
Application.ScreenUpdating = prevUpdate
Exit Sub
EH:
' エラー時も画面更新を戻す
Application.ScreenUpdating = prevUpdate
Err.Raise Err.Number, Err.Source, Err.Description
End Sub
よくある質問とトラブルシュート
4桁数字が装飾されない(ヒットしない)
- Ch側のFindがワイルドカードONになっているか、またはChの表記ゆれが想定外かを確認します(例:
CH:のように全角コロン)。 - 4桁数字が「数字+記号」の一部になっている場合、
< >(単語境界)が効きすぎてヒットしないことがあります。例えば「1234-」のようなケースです。その場合は数字側パターンを[0-9]{4}に緩めて、代わりに検索範囲(直前N文字)を絞る方が実務的なことがあります。
違う4桁数字が装飾される
- 後方検索方式なら、直前N文字制限を入れるのが最優先です(50〜100文字から調整)。
- さらに精度を上げたいなら、「4桁+Ch」を1回のFindで一致させる方式に寄せると誤ヒットが減ります。
処理が途中で止まる/同じ場所を回り続ける
- Collapseで検索位置を進めているか(
wdCollapseEnd)を確認します。 - .Wrap = wdFindStop になっているかを確認します。折り返し(Continue)だと、見つけた場所に戻って無限ループしやすくなります。
rng.Endを文書末尾(またはストーリー末尾)に戻しているかも重要です。
マクロの導入手順(最短)
最後に、マクロをWordに入れて実行するまでの最短手順です。
- Wordで対象文書を開く
- Alt + F11 でVBAエディタを開く
- 左のプロジェクトで対象文書を選び、挿入 → 標準モジュール
- 本記事のコードを貼り付ける(おすすめは
FormatDigitsBySingleFindまたはFormat4DigitsBeforeCh_Context50) - F5 で実行(またはWordに戻ってマクロ一覧から実行)
「Ch : の直前4桁数字だけを一括装飾」という要件は、Selection中心の発想だとどうしても不安定になりがちです。Rangeを軸に、Findの進行(Collapse)と検索条件(ワイルドカード、単語境界、直前N文字)をきちんと設計すれば、全文でも漏れなく同じ処理を回せるようになります。

コメント