【実務・中級編】【初心者向け】Word表のセル内にある特定キーワードを検出し、その行全体を強調表示するマクロ – Word VBA解析バイブル

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

【極限の設計】Word VBAにおける表操作の鉄則:キーワード検知と行全体への動的スタイル適用

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

多くの開発者が、最初の一歩として「Wordの表を操作するマクロ」に挑みます。しかし、そこで書かれるコードのほとんどは、実務の現場では「使い物にならない」と断じざるを得ません。

なぜか? それは、彼らが「動けばいいコード」を書き、「堅牢な設計」を無視しているからです。

「特定のキーワードを含むセルを見つけ、その行全体の色を変える」
一見、単純なタスクに見えます。しかし、実務で遭遇する文書は、結合されたセル、予期せぬ書式、そして数千行に及ぶ膨大なデータを含んでいます。これらを考慮せずに書かれたコードは、実行時にエラーを吐き出し、最悪の場合、Wordをクラッシュさせます。

今日は、単なる「コピペ用コード」ではなく、プロフェッショナルが設計段階で何を考え、どのようにオブジェクトを制御しているのか、その真髄を伝授します。

1. 初心者が陥る「致命的な設計ミス」

コードを書く前に、まず以下の「アンチパターン」を脳に刻んでください。これらは、パフォーマンスを著しく低下させ、保守性を破壊する元凶です。

① `Select` と `Selection` の乱用

マクロ記録機能を使った初心者が最もやりがちなミスです。`Selection.Font.ColorIndex = …` のように、対象を一度「選択」してから操作する手法です。
これは最悪です。 画面の更新(リフレッシュ)が走るたびにCPUリソースを消費し、処理速度は劇的に低下します。プロは、対象となるオブジェクト(`Cell` や `Row`)を直接指定し、メモリ上のオブジェクトに対して直接命令を下します。

② 結合セルの考慮漏れ

Wordの表において、「セルの結合」は悪魔の存在です。結合されたセルが含まれる表に対して、単純な `Rows(i).Cells(j)` というインデックス指定を行うと、実行時エラー `5941`(指定されたメンバーが見つかりません)が発生します。実務で使うツールなら、この例外処理は必須です。

③ マジックナンバーとハードコーディング

「色を黄色にする」という処理を、コード内に直接 `wdYellow` と書き込む。これは設計の放棄です。キーワードや色、スタイルは、必ず「定数」として定義し、変更 easily(容易)に、かつ一箇所で制御できるようにすべきです。

2. プロダクション・クオリティのコード実装

では、これらを踏まえた、堅牢で高速な実装例を示します。このコードは、単に動くだけでなく、エラーハンドリングと保守性を兼ね備えた「プロダクション・コード」の雛形です。

Option Explicit

' ==============================================================================
' Module: TableAutomationModule
' Description: 表内の特定キーワードを検出し、行全体にスタイルを適用する
' Author: Chief Architect
' ==============================================================================

' プロダクション設計における定数定義(保守性を高めるための基本)
Private Const TARGET_KEYWORD As String = "重要" ' 検出したいキーワード
Private Const BG_COLOR As Long = 65535         ' 背景色 (vbYellow)
Private Const FONT_COLOR As Long = wdColorRed  ' フォント色
Private Const BOLD_STYLE As Boolean = True      ' 太字にするか

''' <summary>
''' 文書内の全ての表を走査し、キーワードを含む行を強調表示する
''' </summary>
Public Sub HighlightRowsByKeyword()
    Dim doc As Document
    Dim tbl As Table
    Dim rowIdx As Long
    Dim cellIdx As Long
    Dim targetCell As Cell
    Dim foundInRow As Boolean
    
    ' 高速化のための設定
    ' WordにはExcelのようなScreenUpdatingの明示的な制御が限定的だが、
    ' Selectionを避けることで実質的な描画負荷を最小化する
    
    Set doc = ActiveDocument
    
    ' エラーハンドリングの開始
    On Error GoTo ErrorHandler
    
    ' 1. 文書内の全てのテーブルをループ
    For Each tbl In doc.Tables
        
        ' 2. テーブル内の各行をループ
        ' ※ Rowsコレクションを直接回すことで、結合セルの影響を最小限に抑える設計
        For rowIdx = 1 To tbl.Rows.Count
            foundInRow = False
            
            ' 3. 行内の各セルをループ
            ' セルの結合がある場合、Rows(i).Cells(j) はエラーになる可能性があるため
            ' Try-Catch的なアプローチ(On Error Resume Next)で回避する
            On Error Resume Next
            For cellIdx = 1 To tbl.Rows(rowIdx).Cells.Count
                Set targetCell = tbl.Rows(rowIdx).Cells(cellIdx)
                
                If Not targetCell Is Nothing Then
                    ' セル内のテキストを判定(Wordのセル末尾には特殊文字が含まれるためTrimが必要)
                    ' InStrを使用して部分一致を検出
                    If InStr(1, targetCell.Range.Text, TARGET_KEYWORD, vbTextCompare) > 0 Then
                        foundInRow = True
                        Exit For ' 行内で一つでも見つかれば、その行のセル探索は終了
                    End If
                End If
            Next cellIdx
            On Error GoTo ErrorHandler ' エラーハンドリングを元に戻す
            
            ' 4. キーワードが見つかった場合、行全体にスタイルを適用
            If foundInRow Then
                ApplyRowStyle tbl.Rows(rowIdx)
            End If
            
            ' オブジェクトの解放(メモリ管理の基本)
            Set targetCell = Nothing
        Next rowIdx
    Next tbl
    
    MsgBox "処理が完了しました。", vbInformation, "Success"
    Exit Sub

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

''' <summary>
''' 指定された行に対して書式設定を適用する(責務の分離)
''' </summary>
''' <param name="targetRow">スタイルを適用するRowオブジェクト</param>
Private Sub ApplyRowStyle(ByRef targetRow As Row)
    On Error Resume Next ' 結合セルによるエラーを回避
    With targetRow.Range
        .Font.Color = FONT_COLOR
        .Font.Bold = BOLD_STYLE
    End With
    
    ' 背景色の設定は、Rangeに対して行う
    targetRow.Shading.BackgroundPatternColor = BG_COLOR
    On Error GoTo 0
End Sub

3. アーキテクトの視点:なぜこの設計なのか

このコードを単なる「動くコード」として片付けてはいけません。設計の意図を理解してください。

責務の分離 (Separation of Concerns)

私は `ApplyRowStyle` というサブプロシージャを独立させました。
「キーワードを探すロジック」と「見た目を整えるロジック」を分けることで、将来的に「背景色ではなく、文字を赤くするだけにしてほしい」という仕様変更があった際、修正箇所が1箇所で済み、他のロジックを壊すリスクを最小限に抑えられます。

エラーハンドリングの戦略的配置

結合セルが含まれる表において、`tbl.Rows(rowIdx).Cells(cellIdx)` は非常に脆弱です。私はあえて `On Error Resume Next` を局所的に使用しています。これは「エラーを無視する」ためではなく、「結合セルの構造的な不整合による中断を防ぎ、次のセルへ進む」という意図的な制御です。

計算量と効率性

`Exit For` を活用しています。行の中にキーワードが1つでも見つかった時点で、その行の残りのセルを探索する必要はありません。この「早期リターン」の積み重ねが、数千行のテーブルを扱う際のパフォーマンスの差となって現れます。

4. 実務への応用:さらなる高みへ

このマクロを、真の業務自動化ツールへと昇華させるためのステップを提示します。

1. 外部データとの連携:
現在は `TARGET_KEYWORD` を定数にしていますが、これをExcelのセルから読み込む、あるいはテキストファイルからリストとして読み込むように改造してください。これにより、コードを書き換えずに検索条件を変更できる「ツール」になります。
2. データベース連携:
大規模な管理業務であれば、検索対象のキーワードをSQL ServerやAccessのテーブルから取得し、Word文書の整合性をチェックするようなワークフローを構築してください。
3. ログ出力:
どの行のどのセルでキーワードが検出されたかを、別途テキストログに出力する機能を実装してください。これは、自動化プロセスが正しく動いたかを監査するための「証跡」となります。

結論

Word VBAは、単なる「おまけの機能」ではありません。正しく設計されたVBAは、人間の手作業を数時間から数秒へと圧縮する、強力な武器になります。

「動けばいい」という思考を捨て、「壊れない、速い、直しやすい」というエンジニアリングの視点を持ってください。その差が、単なる事務作業員と、自動化エンジニアを分かつ境界線です。

健闘を祈る。

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