【実務・中級編】【初心者向け】Word表の全セルを走査し、特定のキーワードが含まれる行全体をハイライトする – Word VBA解析バイブル

スポンサーリンク
スポンサーリンク

【Word VBA 掌握術】表走査の罠を回避せよ:キーワードによる行ハイライトの堅牢な実装

業務自動化の世界へようこそ。

「表の中から特定の文字を探して、その行に色を塗る」
一見すると、これほど単純で、初心者向けの題材があるでしょうか? ネット上の断片的なコードを拾い集めれば、5行程度のコードでそれらしい動きを作ることは可能です。

しかし、プロフェッショナルとして「プロダクション環境(実務)」に投入するツールを作るのであれば、話は別です。

もし、その表に「セルの結合」が含まれていたら?
もし、データが数千行に及ぶ「巨大なドキュメント」だったら?
もし、検索キーワードが「外部ファイル」から動的に変わる仕様だったら?

安易なループ処理とオブジェクト操作は、実行速度の低下、あるいは予期せぬランタイムエラーを引き起こし、現場の信頼を失墜させます。本記事では、単なる「動くコード」ではなく、「壊れない、遅くない、拡張できる」設計思想に基づいた、Word VBAによる表操作の極意を伝授します。

1. 初心者が陥る「3つの設計的欠陥」

コードを書く前に、まず「なぜ既存の多くのサンプルコードが実務に耐えないのか」を理解してください。

① セル結合(Merged Cells)への無理解

WordのTableオブジェクトは、Excelのそれとは根本的に異なります。セルが結合されている場合、`cell.RowIndex` や `cell.Row` の挙動が不安定になったり、特定のインデックスへのアクセスがエラーを吐いたりすることがあります。結合セルを含む表を走査する際は、オブジェクトの構造を正しく把握したアプローチが必要です。

② DOM操作のオーバーヘッド(パフォーマンス問題)

Word VBAにおける「オブジェクトへのアクセス」は、非常にコストの高い処理です。
`For Each cell In Table.Range.Cells` のような二重ループの中で、一回ごとに `cell.Row.Shading…` とプロパティを書き換えていくのは、描画エンジンに対して過剰な命令を送り続ける行為です。大規模な表では、画面の更新(ScreenUpdating)を制御しない限り、処理は絶望的に遅くなります。

③ ロジックと設定の密結合

「検索したいキーワード」や「ハイライトの色」をコード内に直接書き込む(ハードコーディングする)ことは、保守性を著しく低下させます。仕様変更のたびにVBAエディタを開いて書き換える。これはエンジニアの仕事ではありません。

2. プロダクション・アーキテクチャ

堅牢なツールを作るために、以下の設計原則を適用します。

1. エラーハンドリングの徹底: 予期せぬ構造の表に遭遇しても、プロセスを安全に終了させる。
2. 描画制御による高速化: `Application.ScreenUpdating` を制御し、描画負荷を最小化する。
3. 関数の責務分離: 「検索ロジック」と「書式設定ロジック」を分ける。

3. 実装例:堅牢な行ハイライト・エンジン

以下に、そのまま実務で使用できるレベルのコードを示します。

Option Explicit

' ==============================================================================
' モジュール名: modTableAutomation
' 概要: Word表内のキーワード検索および行ハイライト機能
' 設計思想: エラーハンドリング、高速化、保守性を重視したプロダクション設計
' ==============================================================================

''' <summary>
''' 指定したキーワードが含まれる行をハイライトするメインルーチン
''' </summary>
Public Sub HighlightRowsByKeyword()
    ' --- 設定エリア (本来は外部ファイルや引数から取得すべき) ---
    Const TARGET_KEYWORD As String = "重要"  ' 検索対象キーワード
    Const HIGHLIGHT_COLOR As Long = wdColorYellow ' ハイライト色
    Const RESET_COLOR As Long = wdColorAutomatic ' リセット色
    ' ---------------------------------------------------------

    Dim targetDoc As Document
    Set targetDoc = ActiveDocument

    Dim tbl As Table
    Dim targetRow As Row
    Dim cellObj As Cell
    Dim foundMatch As Boolean
    
    ' パフォーマンス向上のための制御
    On Error GoTo ErrorHandler
    Application.ScreenUpdating = False

    ' 1. 全てのテーブルを走査
    For Each tbl In targetDoc.Tables
        
        ' 2. まずは既存のハイライトをクリア(クリーンな状態から開始)
        ' ※実務では「前回の実行結果」を保持する必要がある場合は設計を見直す
        ClearTableShading tbl, RESET_COLOR

        ' 3. 行単位の走査(セル単位ではなく行単位で回すことで効率化)
        For Each targetRow In tbl.Rows
            foundMatch = False
            
            ' 4. 行内の各セルをチェック
            ' セル結合がある場合、targetRow.Cells の数が不安定になることがあるため
            ' エラーをトラップしながら走査する
            On Error Resume Next
            For Each cellObj In targetRow.Cells
                If InStr(1, cellObj.Range.Text, TARGET_KEYWORD, vbTextCompare) > 0 Then
                    foundMatch = True
                    Exit For ' 一つでも見つかればその行のセル走査は終了
                End If
            Next cellObj
            On Error GoTo ErrorHandler

            ' 5. 条件合致時の書式適用
            If foundMatch Then
                ApplyRowHighlight targetRow, HIGHLIGHT_COLOR
            End If
        Next targetRow
    Next tbl

    MsgBox "処理が完了しました。", vbInformation, "Success"

CleanUp:
    Application.ScreenUpdating = True
    Exit Sub

ErrorHandler:
    MsgBox "予期せぬエラーが発生しました。" & vbCrLf & _
           "Error No: " & Err.Number & vbCrLf & _
           "Description: " & Err.Description, vbCritical, "Fatal Error"
    Resume CleanUp
End Sub

''' <summary>
''' テーブル内の全セルの背景色をリセットする
''' </summary>
Private Sub ClearTableShading(ByRef targetTable As Table, ByVal color As Long)
    On Error Resume Next
    targetTable.Range.Shading.BackgroundPatternColor = color
    On Error GoTo 0
End Sub

''' <summary>
''' 特定の行に対してハイライトを適用する
''' </summary>
Private Sub ApplyRowHighlight(ByRef targetRow As Row, ByVal color As Long)
    On Error Resume Next
    targetRow.Range.Shading.BackgroundPatternColor = color
    On Error GoTo 0
End Sub

4. コードの解説と「プロの視点」

高速化の鍵:`Application.ScreenUpdating = False`

Wordは、オブジェクトのプロパティが変わるたびに画面を再描画しようとします。これを `False` にすることで、メモリ上での計算に集中させ、実行時間を劇的に短縮します。これは自動化エンジニアの「マナー」です。

結合セルへの耐性:`On Error Resume Next` の戦略的配置

`targetRow.Cells` をループする際、結合セルが含まれていると、インデックスの整合性が崩れ、実行時エラーが発生することがあります。これを防ぐために、セル走査の部分に限定して `On Error Resume Next` を適用しています。ただし、「何でもかんでも無視する」のは素人のすることです。 必要な箇所にのみ、ピンポイントで適用するのがプロの技です。

責務の分離(Encapsulation)

`ApplyRowHighlight` や `ClearTableShading` を独立した `Private Sub` として切り出しました。これにより、メインのロジック(`HighlightRowsByKeyword`)は「何をするか」に集中し、具体的な「どう塗るか」という実装の詳細から解放されます。これが保守性の高いコードの第一歩です。

5. さらに上のステップへ:スケーラビリティの確保

実務でこのツールをさらに進化させるなら、以下の拡張を検討してください。

1. 外部データ連携: `TARGET_KEYWORD` を `InputBox` で受け取る、あるいは Excel ファイルやテキストファイルからキーワードリストを読み込むように変更する。
2. 正規表現(RegExp)の導入: 単純な `InStr` ではなく、`VBScript.RegExp` を利用して、「日付形式の文字列」や「特定のパターンを持つID」を検索できるようにする。
3. ログ出力: どのテーブルの、何行目で、どのキーワードが見つかったかをテキストファイルに書き出す。これは大規模な自動化プロジェクトにおける「デバッグの生命線」となります。

結びに

Word VBAは、一見古臭い技術に見えるかもしれません。しかし、そのオブジェクトモデルを深く理解し、堅牢な設計思想を持って扱うならば、これほど強力な武器はありません。

「とりあえず動くコード」を書くのは今日で終わりにしましょう。
次にあなたが書くのは、「誰が、いつ、どのようなデータに対して実行しても、静かに、かつ正確に任務を遂行する」、そんなプロフェッショナルのコードです。

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