Word VBAで「Ch :」直前の4桁数字を一括装飾する方法|Range.Findで太字・赤字・ターコイズ強調

Word文書で「Ch :」の直前にある4桁数字だけを、太字・赤字・ターコイズのハイライトで一括装飾したいのに、Selection(選択範囲)だと1件目は動いても全文の連続処理が安定しない――この手の悩みは、Range(範囲オブジェクト)で全文をスキャンする設計に切り替えると一気に解決します。

日程Fit。無料・登録不要。「いつ空いてる?」を、ひとつのリンクで。リンクを送って、○△×でかんたん日程調整。無料で日程を作る。
目次

やりたいことを整理: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終端で折り返すかwdFindStopwdFindContinueだと“戻って再検索”で無限ループの温床
.ClearFormatting書式条件をクリア毎回呼ぶ書式検索が混ざって急に見つからなくなる
.Format書式条件を使うかFalseTrueのままだと書式一致が必要になりヒットしない

ヘッダー/フッターや脚注にもある場合: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に入れて実行するまでの最短手順です。

  1. Wordで対象文書を開く
  2. Alt + F11 でVBAエディタを開く
  3. 左のプロジェクトで対象文書を選び、挿入 → 標準モジュール
  4. 本記事のコードを貼り付ける(おすすめは FormatDigitsBySingleFind または Format4DigitsBeforeCh_Context50
  5. F5 で実行(またはWordに戻ってマクロ一覧から実行)

「Ch : の直前4桁数字だけを一括装飾」という要件は、Selection中心の発想だとどうしても不安定になりがちです。Rangeを軸に、Findの進行(Collapse)と検索条件(ワイルドカード、単語境界、直前N文字)をきちんと設計すれば、全文でも漏れなく同じ処理を回せるようになります。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次