【入門編】【上級者向け】Word表のデータを多次元配列に格納して一括処理し、Wordへの書き戻しを最小限にする高速化手法 – Word VBA解析バイブル

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

「マクロの記録」の先へ。Word表処理を劇的に高速化する「メモリ内一括処理」の極意

こんにちは。業務自動化の世界へようこそ。

「マクロの記録」を使って、なんとか自動化の第一歩を踏み出した。そんなあなたに、今日はエンジニアとしての「視界」を一気に広げる、非常に重要な話をしましょう。

もしあなたが今、「表のセルを一つずつループで回して、値を書き換えるマクロ」を作っているとしたら……。それは、エンジニアとしての成長の真っ只中にいます。しかし、同時に「速度」という大きな壁にぶつかる運命にもあります。

「データが増えると、処理が終わるまでコーヒーを淹れに行けるほど時間がかかる」
「セルへのアクセスが多すぎて、画面がチラついて止まらない」

これらを解決するのが、今回お伝えする「多次元配列を用いたメモリ内一括処理」というテクニックです。これを知るだけで、あなたのコードは「動くだけのツール」から「プロ仕様のシステム」へと昇華します。

さあ、準備はいいですか? 一緒に極限の効率化へと踏み出しましょう。

1. なぜ、あなたのマクロは「遅い」のか?

まず、敵を知ることから始めましょう。なぜ、Wordのセルに直接アクセスして処理を行うと遅くなるのでしょうか?

「オブジェクト・オーバーヘッド」という名の壁

Word VBAにおいて、`Table.Cell(row, col)` という記述は、単にメモリ上の値を参照しているわけではありません。

1. VBAがWordアプリケーションに対して「〇行、〇列目のセルをください」とリクエストを送る。
2. Wordがそのセルを「オブジェクト(複雑な情報の塊)」として構築する。
3. セルの中身(テキスト、書式、結合状態など)をすべて読み出す。

このプロセスを、ループの中で何百回、何千回と繰り返していると考えてみてください。これは、「書類の1行を書き換えるたびに、わざわざ本社へ承認印をもらいに行く」ようなものです。非常に非効率ですよね。

解決策:データを「メモリ」という手元のデスクに広げる

プロのエンジニアはこう考えます。
「本社(Wordオブジェクト)へ何度も行くのはやめよう。一度にすべての書類(データ)をコピーして、自分のデスク(メモリ上の配列)に広げ、そこで一気に作業を済ませてから、最後にまとめて本社へ提出しよう」

この「デスク(配列)に広げる」作業こそが、今回のテーマである多次元配列の役割です。

2. 実装の戦略:3ステップ・アプローチ

高速化を実現するための黄金パターンは、以下の3ステップです。

1. 【読み込み】 表の全データを、一度だけ「多次元配列」へ格納する。
2. 【加工】 メモリ上(配列の中)で、数値計算やテキスト加工を高速に行う。
3. 【書き戻し】 加工が終わった配列の内容を、一気に表へ反映させる。

ここで一点、重要な注意があります。Excel VBAとは異なり、Wordには「配列をセルに一括で流し込む」という魔法のようなメソッドは存在しません。しかし、「計算ロジック」をWordの外(メモリ上)に追い出すだけで、処理速度は劇的に改善します。

3. 【実践】高速化コードのテンプレート

それでは、実際に動くコードを見てみましょう。
今回は、「表の中の数値を2倍にする」という単純な処理を例に、プロ仕様の構造を解説します。

Option Explicit

''' <summary>
''' Word表のデータを高速に処理するメインルーチン
''' </summary>
Sub HighSpeedTableProcessing()
    Dim tbl As Table
    Dim dataArray As Variant
    Dim r As Long, c As Long
    
    ' 1. 対象となる表を指定(ここでは文書内の最初の表)
    If ActiveDocument.Tables.Count = 0 Then
        MsgBox "表が見つかりません。", vbExclamation
        Exit Sub
    End If
    Set tbl = ActiveDocument.Tables(1)
    
    ' 画面更新を停止して高速化(お約束のテクニック)
    Application.ScreenUpdating = False
    
    On Error GoTo ErrorHandler
    
    ' ---------------------------------------------------------
    ' STEP 1: 【読み込み】表から配列へデータを移す
    ' ---------------------------------------------------------
    ' 配列のサイズを決定(行数 × 列数)
    ' ※注意: Wordのセルには末尾に特殊な制御文字が含まれるため、
    ' 読み込み時にそれを除去する工夫が必要です。
    ReDim dataArray(1 To tbl.Rows.Count, 1 To tbl.Columns.Count)
    
    For r = 1 To tbl.Rows.Count
        For c = 1 To tbl.Columns.Count
            ' セルのテキストを取得し、Word特有の末尾文字(Chr(13) & Chr(7))を除去
            dataArray(r, c) = CleanCellText(tbl.Cell(r, c).Range.Text)
        Next c
    Next r
    
    ' ---------------------------------------------------------
    ' STEP 2: 【加工】メモリ上(配列内)で計算を行う
    ' ---------------------------------------------------------
    ' ここでの処理はWordへのアクセスを一切行わないため、爆速です。
    For r = 1 To UBound(dataArray, 1)
        For c = 1 To UBound(dataArray, 2)
            ' 例:数値であれば2倍にする(テキスト処理もここで行う)
            If IsNumeric(dataArray(r, c)) And dataArray(r, c) <> "" Then
                dataArray(r, c) = CDbl(dataArray(r, c)) * 2
            End If
        Next c
    Next r
    
    ' ---------------------------------------------------------
    ' STEP 3: 【書き戻し】加工後の配列をセルへ反映
    ' ---------------------------------------------------------
    For r = 1 To UBound(dataArray, 1)
        For c = 1 To UBound(dataArray, 2)
            ' 計算結果をセルに書き戻す
            tbl.Cell(r, c).Range.Text = dataArray(r, c)
        Next c
    Next r

    ' 終了処理
    Application.ScreenUpdating = True
    MsgBox "処理が完了しました!", vbInformation
    Exit Sub

ErrorHandler:
    Application.ScreenUpdating = True
    MsgBox "エラーが発生しました: " & Err.Description, vbCritical
End Sub

''' <summary>
''' Wordのセル特有の末尾制御文字を削除する補助関数
''' </summary>
Private Function CleanCellText(ByVal txt As String) As String
    ' Wordのセル末尾には必ず Chr(13) & Chr(7) が含まれるため、これを除去
    Dim pos As Integer
    pos = InStr(txt, Chr(13))
    If pos > 0 Then
        CleanCellText = Left(txt, pos - 1)
    Else
        CleanCellText = txt
    End If
End Function

4. ここがプロの勘所!陥りやすいエラーと対策

この手法を使いこなすために、以下の3つのポイントを必ず覚えておいてください。

① Word特有の「ゴミ」を掃除せよ

Wordのセルの値を取得すると、必ず末尾に `Chr(13)`(改行)と `Chr(7)`(セル区切り)という目に見えない文字がついてきます。
これを除去せずに `IsNumeric` で判定したり、計算に使おうとすると、「型が一致しません」というエラーの嵐に襲われます。上記のコードにある `CleanCellText` 関数は、まさにこの「掃除」を行うためのプロの防衛策です。

② 配列のインデックス(添字)に注意

VBAの配列は、宣言の仕方によって `0` から始まることもあれば、`1` から始まることもあります。
今回の例では `ReDim dataArray(1 To …)` と明示的に `1` から開始するように指定しています。これにより、Wordの行番号(1行目、2行目…)と配列の添字を一致させ、思考の混乱を防いでいます。

③ `Application.ScreenUpdating` の魔術

大規模な書き戻しを行う際、画面がチカチカ動くのはユーザー体験としても悪く、速度も低下させます。`Application.ScreenUpdating = False` で画面更新を止め、最後に `True` に戻す。これは、エンジニアとして心得ておくべき「礼儀」であり、高速化の鉄則です。

最後に:一歩踏み出したあなたへ

いかがでしたか?
「セルを一つずつ触る」という直感的な方法から、「一度メモリに引き上げてから処理する」という抽象的な方法へ。この考え方のシフトこそが、初級者と上級者を分ける境界線です。

最初はコードが複雑に見えるかもしれません。しかし、一度この「型」を身につけてしまえば、どんなに巨大なデータが来ても、あなたは冷静に、そして高速に処理を完遂できるはずです。

「ここをクリアすれば、Word VBAの基本はバッチリですよ」

自信を持って、次の自動化プロジェクトに挑んでください。応援しています!

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