VBAで大量のセルデータを処理する際、For Each
ループなどでセルを一つずつ読み書きしていくと、データ量に比例して処理が非常に遅くなるという問題に直面します。
このパフォーマンス問題を解決する最も効果的で基本的な方法が、セル範囲の値を一度にまとめて「配列」に読み込み、VBAのメモリ上で高速に処理するというテクニックです。
この記事では、セルとVBA間のやり取りを最小限に抑え、マクロを劇的に高速化するための、この配列活用術を解説します。
なぜ配列を使うと速いのか?
VBAが遅くなる最大の原因の一つは、VBAのプログラムとExcelのワークシート間での頻繁なデータのやり取りです。
- 遅い方法(ループで1セルずつアクセス): 1万個のセルを処理する場合、VBAとExcel間で1万回の通信が発生します。これは、スーパーへ1万回買い物に行くようなもので、非常に非効率です。
- 速い方法(配列に一括代入): 最初に1回の通信で1万個のセルデータをすべてVBAのメモリ(配列)に読み込みます。メモリ上での処理は非常に高速なため、その後の処理は瞬時に完了します。これは、買い物リストを持ってスーパーへ1回だけ行くようなものです。
完成したVBAコード
以下が、C2
セルを含む表領域(CurrentRegion
)の値をすべて2次元配列に一度で読み込み、その内容の一部を表示するVBAコードです。
Sub LoadRangeIntoArray()
' 配列を格納するための変数は、必ずVariant型で宣言します
Dim dataArray As Variant
Dim sourceRange As Range
'--- 1. 配列に読み込みたいセル範囲を特定 ---
' CurrentRegionは、Ctrl + * で選択される範囲と同じです
Set sourceRange = ThisWorkbook.Worksheets("Sheet1").Range("C2").CurrentRegion
'--- 2. セル範囲の.Valueを、Variant型の変数に一括で代入 ---
' この一行だけで、範囲の値が2次元配列として格納されます
dataArray = sourceRange.Value
'--- 3. 配列の要素にアクセスして内容を確認 ---
' 配列のインデックスは (行番号, 列番号) で、1から始まります
MsgBox "配列の1行目、1列目の値は: " & dataArray(1, 1) & vbCrLf & _
"配列の3行目、2列目の値は: " & dataArray(3, 2), vbInformation, "配列の内容確認"
'--- (応用) メモリ上で配列をループ処理 ---
Dim i As Long
For i = 1 To UBound(dataArray, 1)
' 例: 3列目の値を大文字に変換してデバッグ出力
Debug.Print UCase(dataArray(i, 3))
Next i
End Sub
コードのポイント解説
① Dim dataArray As Variant
セル範囲から値を受け取る変数は、必ず**Variant
型**で宣言する必要があります。String
やLong
の配列としてDim dataArray() As String
のように宣言すると、一括代入できずエラーになります。
② dataArray = sourceRange.Value
このコードの核心部分です。複数セルを含むRange
オブジェクトの.Value
プロパティをVariant
型の変数に代入すると、VBAは自動的にその範囲の値を格納した2次元配列を作成します。
③ 配列のインデックス
Range.Value
で作成された配列には、以下のような特徴があります。
- 1から始まる: 配列のインデックスは、一般的なプログラミング言語で多い0からではなく、1から始まります。これはExcelの行番号・列番号の感覚と一致しており、直感的に扱えます。
- (行, 列) の2次元: 値にアクセスするには、
dataArray(行番号, 列番号)
のように指定します。 - 相対的な位置: 行番号・列番号は、元のワークシート上の絶対的な位置ではなく、取り込んだセル範囲の左上を(1, 1)とする相対的な位置になります。例えば、
C2:D10
の範囲を配列に取り込んだ場合、C2
セルの値はdataArray(1, 1)
に格納されます。
まとめ
VBAの処理速度を向上させるための最も重要なテクニックは、ワークシートへのアクセス回数を最小限に抑えることです。
- 処理したいデータ範囲の値を、
myArray = myRange.Value
を使って、一度にVariant
型の配列に読み込む。 For
ループなどの処理は、すべてメモリ上の配列に対して行う。- (もし書き込みが必要なら)処理が完了した配列を、再びセル範囲に一度で書き戻す。
この「最初にまとめて読み込み、最後にまとめて書き出す」という考え方を徹底するだけで、VBAマクロのパフォーマンスは劇的に改善します。