VBAの高速化において、セル範囲のデータを一度「配列」に読み込んでから処理するテクニックは非常に重要です。そして、その配列をどのようにループ処理するか、またどのようにクリアするかによっても、パフォーマンスやコードの正確性が変わってきます。
この記事では、配列を扱う際の基本的な2種類のループ方法と、3種類のクリア方法を比較し、それぞれの長所・短所と推奨される使い方を解説します。
配列を読み取るループ:2つの方法
作成した配列の各要素を順番に読み取っていくには、主に2つのループ方法があります。
方法1:インデックスを使った For...Next
ループ
配列のインデックス番号(添え字)を使って、要素に直接アクセスする最も基本的な方法です。
Sub LoopWithForNext()
Dim weekdays(1 To 7) As String
Dim i As Long
' 配列に値を設定
weekdays(1) = "月曜": weekdays(2) = "火曜": weekdays(3) = "水曜"
weekdays(4) = "木曜": weekdays(5) = "金曜": weekdays(6) = "土曜": weekdays(7) = "日曜"
' LBound(下限)からUBound(上限)までループ
For i = LBound(weekdays) To UBound(weekdays)
Debug.Print weekdays(i)
Next i
End Sub
LBound
とUBound
関数を使うことで、配列の大きさが変わってもコードを修正する必要がなくなります。一般的に、処理速度は後述のFor Each
よりも若干高速です。
方法2:For Each...Next
ループ
配列内の各要素を、ループのたびに変数に格納して処理する方法です。
Sub LoopWithForEach()
Dim weekdays(1 To 7) As String
Dim day As Variant
' 配列に値を設定
weekdays(1) = "月曜": weekdays(2) = "火曜": weekdays(3) = "水曜"
weekdays(4) = "木曜": weekdays(5) = "金曜": weekdays(6) = "土曜": weekdays(7) = "日曜"
' 配列内の各要素(day)を順番に処理
For Each day In weekdays
Debug.Print day
Next day
End Sub
インデックスを意識する必要がないため、コードがシンプルで読みやすくなるのが最大の利点です。
配列をクリア(初期化)する方法
使用済みの配列を空にするには、いくつかの方法がありますが、推奨される方法は一つだけです。
方法1:Erase
ステートメント(強く推奨)
配列をクリアするための専用命令です。最も高速で、メモリ管理の観点からも正しい方法です。
Sub ClearArrayWithErase()
Dim weekdays(1 To 7) As String
' (配列に値が入っているとする)
' Eraseで配列を初期化
Erase weekdays
' 文字列配列の場合、要素は空文字列("")になる
Debug.Print weekdays(1) ' -> 結果は空
End Sub
- 固定長の配列(例:
Dim data(1 To 100)
)の場合:Erase
はすべての要素をそのデータ型の初期値(数値なら0
、文字列なら""
)にリセットします。 - 動的配列(例:
Dim data()
)の場合:Erase
は配列に割り当てられたメモリを完全に解放します。
方法2:ループで要素を空にする(非推奨)
For
ループを使って、全要素に空の値を代入する方法です。
For i = LBound(weekdays) To UBound(weekdays)
weekdays(i) = ""
Next i
この方法はErase
に比べて処理が遅く、コードも長くなるため、通常は使いません。
【注意】For Each
では配列の値を変更(クリア)できない
For Each
ループを使って配列をクリアしようとすると、期待通りに動作しません。
' !!! 間違ったコードの例 !!!
For Each day In weekdays
day = "" ' ← dayという「コピー」が空になるだけで、元の配列は変わらない
Next day
For Each
のループ変数(day
)は、配列の要素のコピーを格納しています。そのため、変数day
の値を変更しても、元のweekdays
配列の中身には一切影響がありません。これは、初心者が陥りやすい間違いなので注意が必要です。
まとめ
配列の操作におけるベストプラクティスは以下の通りです。
- 配列の読み取り:
- 可読性を重視するなら
For Each
- 極限まで速度を追求するなら
For i = LBound to UBound
- 可読性を重視するなら
- 配列のクリア:
- 常に
Erase
ステートメントを使うのが、最も高速かつ確実です。
- 常に
- 配列への書き込み:
- 必ずインデックスを指定する
For i
ループを使いましょう。For Each
では書き込みはできません。
- 必ずインデックスを指定する
これらの特性を理解し、場面に応じて最適な方法を選択することで、VBAの処理効率とコードの品質を向上させることができます。