配列で処理を高速化する
音声
目次
1次元配列の宣言と使い方
今回できるようになることとして、1次元配列を宣言して値を入れ、セルや処理で使えるようになることを説明します。
1次元配列はリスト状のデータ(社員名一覧や数値列など)を扱うときに便利です。
宣言は Dim arr(1 To 5) As Variant のように範囲を決めて行い、ループで値を設定・取得します。
配列の型は用途(整数ならLong、文字列ならString、混在やRange扱いならVariant)で変えます。
最小マクロ:
Sub Sample1D()
Dim arr(1 To 5) As Variant
Dim i As Long
For i = 1 To 5
arr(i) = "項目" & i
Next i
For i = 1 To 5
Cells(i, 1).Value = arr(i) ' A列に出力
Next i
End Sub
貼り付け場所:標準モジュール(VBAエディタの「挿入」→「標準モジュール」)に貼り付けることを推奨します。
実行方法:VBE(Visual Basic Editor)でカーソルを置きF5実行、またはリボンにボタンを作って割り当てる方法が使いやすいです。保存はマクロ有効ブック(*.xlsm)で行ってください。
2次元配列の活用(行と列のデータ管理)
2次元配列は表形式のデータ(行と列)をそのまま扱えるため、セルの複数列処理に向いています。
宣言は Dim arr(1 To 3, 1 To 2) As Variant のように行と列を指定し、arr(row, col) でアクセスします。
For r = 1 To UBound(arr, 1) と For c = 1 To UBound(arr, 2) の二重ループで処理するのが基本です。行単位・列単位でまとめて計算する場合に効率が上がります。
確認方法は、実行後に対象セル範囲が期待どおりに変化しているかを見ます。または MsgBox で集計結果を表示して確認できます。大きな範囲ならイミディエイトウィンドウにデバッグ出力して内容を要チェックする方法も有効です。
Sub Sample2D()
Dim arr(1 To 3, 1 To 2) As Variant
Dim r As Long, c As Long
arr(1, 1) = "A1": arr(1, 2) = 10
arr(2, 1) = "A2": arr(2, 2) = 20
arr(3, 1) = "A3": arr(3, 2) = 30
For r = 1 To 3
For c = 1 To 2
Cells(r, c).Value = arr(r, c)
Next c
Next r
End Sub
セル範囲と配列の相互変換
Range.Value に配列を設定すると、Excel は自動的に 2 次元の Variant 配列として受け取ります(これが「配列←→セル範囲」の基本です)。
逆に Range("A1:A5").Value を受け取ると 1 列×5 行の 2 次元配列になるため、1 次元に変換したい場合は Application.Transpose を使うか、自分でループしてコピーします。
大きなデータを扱うときはセル→配列→処理→セルの順でまとめて行うと、描画やイベントのオーバーヘッドを減らせます。
使い分けの基準:Range と Cells の使い分けは可読性と動的指定で決めます(固定範囲なら Range("A1:B10")、可変なら Cells(row, col))です。Value と Value2 は基本ほぼ同じですが、Value2 は日付の扱いが Variant/Double でシンプルなので、高速化向きの場面があります。
動的配列(ReDim、ReDim Preserve)
動的配列はサイズが実行時に変わる場合に使います。Dim arr() As Variant としてから ReDim arr(1 To n) でサイズを設定できます。
既に値が入っている配列のサイズを変えるときは ReDim Preserve を使うとデータを保持できますが、Preserve で拡張できるのは末尾の次元だけです。2次元配列で列数を増やすことは可能ですが、行数を増やすことはできない制約があります。
サイズ変更は頻繁に行うとコストがかかるため、想定最大数で一度確保しておくと高速化につながります。
よくあるミス:ReDim Preserve の使い方で、2次元配列の先頭側の次元を変えようとしてエラーになることがあります。直し方は次元の順序を見直すか、一時配列にコピーしてから再構築する方法を使います。
配列を使った処理速度の改善例
大量のセルを1つずつアクセスすると遅くなるため、まとめて配列へ読み込み、メモリ内で処理してから一度に書き戻すと劇的に速くなります。
以下はRangeを配列に読み込み、値を加工して戻す代表例です。
実際の適用では Application.ScreenUpdating = False や Calculation = xlCalculationManual を併用するとさらに効果が出ます。
Sub FastProcess()
Dim v As Variant
Dim r As Long, c As Long
Dim ws As Worksheet
Set ws = ThisWorkbook.Sheets(1)
v = ws.Range("A1:D1000").Value ' 一括読み込み
For r = 1 To UBound(v, 1)
For c = 1 To UBound(v, 2)
If IsNumeric(v(r, c)) Then
v(r, c) = v(r, c) * 2 ' 例:数値を2倍
End If
Next c
Next r
ws.Range("A1:D1000").Value = v ' 一括書き戻し
End Sub
注意(ここだけ)
- マクロを実行する前に、ファイル形式をマクロ有効ブック(.xlsm)で保存し、Excelの「マクロを有効にする」をオンにしてから実行することがポイントです(VBEでの実行・ボタン実行とも同様です)。
要約
- 1次元配列はリスト的データに使い、Dimで宣言してループで扱います。
- 2次元配列は行列データをそのまま操作でき、二重ループで処理します。
- Range.Value は配列の読み書きに使え、通常は一括読み書きで速度向上します。
- ReDim Preserve は便利ですが、末尾次元のみ保持可能という制約があるため、想定サイズで確保するのが高速化につながります。
- 大量セル処理は配列に読み込んでメモリ内処理を行い、一括で書き戻すと実行時間が大幅に短くなります。