Excel VBAで業務を自動化していくと、必ず直面する壁があります。
それが「処理が遅い」「件数が増えると固まる」「実務では使えない」という問題です。
この原因の多くは、セルを1つずつ直接操作していることにあります。
特に行数が数百、数千を超えるデータでは、
Range を直接参照し続ける処理は一気にパフォーマンスが落ちます。
そこで重要になるのが、
2次元配列を使ってデータを一括で格納し、配列上でループ処理する設計です。
この記事では、Excel VBAにおける
- 2次元配列とは何か
- なぜ一括格納が高速なのか
- 2次元配列に格納する正しい方法
- 配列データを安全にループ処理する方法
- 実務で壊れないテンプレート設計
を、実務目線で徹底的に解説します。
目次
- ✅ なぜ2次元配列を使うと処理が速くなるのか
- ・セル操作は非常にコストが高い
- ・配列ならメモリ上で完結する
- ✅ Excel VBAにおける2次元配列とは
- ・2次元配列の基本構造
- ・Rangeを配列に格納すると自動で2次元になる
- ✅ 2次元配列に一括でデータを格納する基本パターン
- ・基本構文
- ・行数・列数の取得方法
- ✅ 2次元配列をループで処理する基本構造
- ・行方向だけをループする場合
- ・行×列の2重ループ
- ✅ 実務でよく使う2次元配列処理テンプレート
- ・データ加工用の基本テンプレート
- ✅ 条件付きで2次元配列を処理する方法
- ・If文を組み合わせた例
- ✅ 空白行・欠損データを含む場合の対処
- ・空白チェックを組み込む
- ✅ 処理結果を一括でシートに書き戻す方法
- ✅ 2次元配列処理と処理速度最適化
- ✅ UiPath・RPA連携を前提にした2次元配列設計
- ✅ よくある失敗パターンと回避策
- ・失敗例① セル参照と配列参照を混在させる
- ・失敗例② 行数を固定でループ
- ・失敗例③ 配列の次元を意識していない
- ✅ まとめ:2次元配列を使えばVBAは実務レベルになる
✅ なぜ2次元配列を使うと処理が速くなるのか
VBA初心者の多くは、「For Eachでセルを回せばいい」と考えがちです。
しかし実務では、この考え方が大きな足かせになります。
ここでは、2次元配列を使うべき理由を整理します。
この章を理解していないと、後半のコードの価値が半減します。
処理速度と安定性の本質を、まず押さえてください。
・セル操作は非常にコストが高い
For i = 2 To 1000
Cells(i, 1).Value = Cells(i, 1).Value & "_A"
Next i
一見問題なさそうですが、
このコードは 1000回 Excelとやり取りをしています。
・配列ならメモリ上で完結する
arr = Range("A2:A1000").Value
この1行で、
1000件分のデータを一括でメモリに読み込みます。
以降の処理は、すべてメモリ上で完結します。
これが、2次元配列が圧倒的に速い理由です。
✅ Excel VBAにおける2次元配列とは
まずは、言葉の整理から行います。
ここを曖昧にすると、配列の扱いで必ず混乱します。
・2次元配列の基本構造
Excel VBAの2次元配列は、次のような形です。
arr(行, 列)
たとえば、
arr(1, 1) ' 1行目・1列目
arr(3, 2) ' 3行目・2列目
という形でアクセスします。
・Rangeを配列に格納すると自動で2次元になる
Dim arr As Variant
arr = Range("A1:C5").Value
この時点で、
- 行方向
- 列方向
を持つ2次元配列になります。
✅ 2次元配列に一括でデータを格納する基本パターン
ここからが実践のスタートです。
まずは「正しい一括格納の方法」を確実に押さえます。
・基本構文
Dim arr As Variant
arr = Range("A2:D100").Value
これだけで、
- 行数:99行
- 列数:4列
の2次元配列が作成されます。
・行数・列数の取得方法
Dim rowCount As Long
Dim colCount As Long
rowCount = UBound(arr, 1)
colCount = UBound(arr, 2)
ここで重要なのは、
2次元配列では次元を必ず指定するという点です。
✅ 2次元配列をループで処理する基本構造
一括格納しただけでは意味がありません。
次に、配列上で安全にループ処理する方法を解説します。
・行方向だけをループする場合
Dim i As Long
For i = LBound(arr, 1) To UBound(arr, 1)
Debug.Print arr(i, 1)
Next i
ポイント
- LBound ~ UBound を必ず使う
- 固定値(1や最終行)は使わない
・行×列の2重ループ
Dim i As Long
Dim j As Long
For i = LBound(arr, 1) To UBound(arr, 1)
For j = LBound(arr, 2) To UBound(arr, 2)
Debug.Print arr(i, j)
Next j
Next i
実務での注意点
- 必要な列だけ処理する
- 無駄な2重ループは避ける
参考:【VBA】ExcelVBAのLBound関数・UBound関数を使用する配列の基本
✅ 実務でよく使う2次元配列処理テンプレート
ここからは、実務でそのまま使える形を紹介します。
・データ加工用の基本テンプレート
Sub ProcessDataByArray()
Dim src As Variant
Dim result As Variant
Dim i As Long
src = Range("A2:C100").Value
ReDim result(1 To UBound(src, 1), 1 To 1)
For i = LBound(src, 1) To UBound(src, 1)
result(i, 1) = src(i, 1) & "_" & src(i, 2)
Next i
Range("D2").Resize(UBound(result, 1), 1).Value = result
End Sub
このテンプレートの強み
- 高速
- 行数変動に強い
- 処理内容が分かりやすい
✅ 条件付きで2次元配列を処理する方法
実務では「条件付き処理」が必須です。
・If文を組み合わせた例
For i = LBound(src, 1) To UBound(src, 1)
If src(i, 3) <> "" Then
result(i, 1) = src(i, 3)
End If
Next i
実務ポイント
- 空白チェックは必須
- 条件の順序を意識する
✅ 空白行・欠損データを含む場合の対処
配列処理では、
「すべての行に値が入っている」と思い込むのは危険です。
・空白チェックを組み込む
If Trim(src(i, 1)) <> "" Then
' 処理
End If
これだけで、事故を大きく減らせます。
参考:【VBA】行を削除する方法|Rows.Deleteで空白行をまとめて処理
✅ 処理結果を一括でシートに書き戻す方法
配列処理の最後は、一括出力が基本です。
Range("E2").Resize(UBound(result, 1), UBound(result, 2)).Value = result
なぜ一括出力が重要か
- セル書き込み回数を最小化
- 画面更新の負荷を軽減
- 処理時間を大幅短縮
参考:【VBA】Excel VBAで.Resizeメソッドを活用する方法
✅ 2次元配列処理と処理速度最適化
2次元配列と合わせて、
必ず行いたい設定があります。
Application.ScreenUpdating = False
Application.Calculation = xlCalculationManual
処理後は必ず元に戻します。
参考:【VBA】処理が終わるまで待機させる【Sleep関数・Application.Waitメソッド】
✅ UiPath・RPA連携を前提にした2次元配列設計
近年の実務では、
Excel VBAは RPAの前処理として使われるケースが増えています。
- RPA:ファイル取得・登録
- VBA:2次元配列で高速加工
この役割分担が、
保守性と安定性を両立させます。
✅ よくある失敗パターンと回避策
・失敗例① セル参照と配列参照を混在させる
→ 処理速度が落ちる
・失敗例② 行数を固定でループ
→ データ欠損・エラー発生
・失敗例③ 配列の次元を意識していない
→ 意味不明なバグ
✅ まとめ:2次元配列を使えばVBAは実務レベルになる
- 2次元配列は高速処理の基本
- Rangeを一括で配列に格納する
- ループは LBound ~ UBound を使う
- 条件付き処理・空白対策を必ず入れる
- 出力も一括で行う
- RPA連携を見据えると設計が安定する
2次元配列を正しく使えるようになると、
Excel VBAは「おもちゃ」から「業務ツール」へ変わります。
この記事をベースに、
ぜひ自分のマクロを配列ベースに書き換えてみてください。
処理速度・安定性・保守性の違いを、確実に実感できるはずです。