VBA性能向上委員会

VBAプログラミングの実行速度に関して、より速い性能を求めて徹底検証をします。


HOME > VBA性能徹底検証 > ForEach文

ForEach文

VBAでは、For文と呼ばれる構文は2種類あります。

『For文』と『ForEach文』です。


For文とは、指定した数分だけループさせる構文です。

ForEach文とは、配列の領域分だけループさせる構文です。


ForEach文は他の言語でも存在しますが、VBA特有の使い方で検証してみたいと思います。

まずは、ForEach文の基本的な記述方法を以下に示します。

Dim v As Variant
Dim myArray() As Variant  ' 配列

myArray() = Array("あ", "い", "う")

' 配列の領域分ループします
For Each v In myArray
Debug.Print v
Next v

この例では、イミディエイトウインドウに、

 あ

 い

 う

と、表示されます。


また、ForEach文は、配列だけでなくコレクション(オブジェクト)も指定することができるので、セルを指定してループすることもできます。

Dim c As Range

' セルの範囲分ループします
For Each c In Range("A1:C1")
Debug.Print c.Value
Next c

この例では、イミディエイトウインドウに、

 セルA1の値

 セルB1の値

 セルC1の値

が、表示されます。


セル範囲のループは、VBAプログラムではよくあるロジックなのですが、工夫次第で性能が向上することはご存知でしょうか。

今回の検証では、2つパターンを用意して、検証します。



セル範囲をRange型でループ サンプルプログラム

Dim c As Range

For Each c In Range("A:A")
Next c

ただ単純に、A列をForEach文を使ってループさせるだけのサンプルです。

セル範囲はRange型なので、Range型を各要素に割り当ててループをさせます。



セル範囲をVariant型でループ サンプルプログラム

Dim v As Variant
Dim buf As Variant

buf = Range("A:A")

For Each v In buf
Next v

2つ目のサンプルも、1つ目と同様に、A列をForEach文を使ってループさせています。

違う点は、各要素に割り当てる変数の型がVariantであるところと、セル範囲の型をVariantに変換して(配列に詰め直して)ループさせているところです。



検証

上記2つのパターンについての実行結果は以下の通りです。

回数Range型でループVariant型でループ
1回目0.0470.031
2回目0.0630.031
3回目0.0620.031
4回目0.0460.047
5回目0.0620.016
6回目0.0630.031
7回目0.0630.047
8回目0.0620.031
9回目0.0620.046
10回目0.0460.047
平均0.0580.036

※単位は全て『秒』


Variant型でループさせる方法が、Range型でループさせる方法より、

62.15%速くなっています。

これは、単純にVariant型とRange型の領域の差が出ているだけです。


この例では、セル範囲を1列のみとしましたが、列を増やすとさらに性能に差が出ます。

以下に、3列の場合と10列の場合の検証結果を示します。


3列(A:C)の場合の検証結果

回数Range型でループVariant型でループ
1回目0.1090.047
2回目0.1250.031
3回目0.1250.063
4回目0.2030.063
5回目0.1250.062
6回目0.1250.047
7回目0.1250.047
8回目0.1090.047
9回目0.1090.031
10回目0.1090.062
平均0.12640.050
※単位は全て『秒』

3列の場合、39.56%速くなっています。

10列(A:J)の場合の検証結果

回数Range型でループVariant型でループ
1回目0.3590.093
2回目0.3750.078
3回目0.3750.109
4回目0.3590.109
5回目0.3590.094
6回目0.3600.109
7回目0.3590.094
8回目0.3750.094
9回目0.3590.093
10回目0.3440.094
平均0.36240.0967

※単位は全て『秒』


10列の場合、26.68%速くなっています。

これにより、列を増やせば増やすほど、Variant型がより速くなることがわかります。

ただ今回のケースが有効になるのは、セルの値を取得する処理くらいでしょう。

Variant型の場合、値の参照しかできないので、Range型が持つさまざまなプロパティやメソッドは使えなくなります。


例えば、『あるセル範囲の中で、特定の文字列を含む行を削除』なんてプログラムを組むのは難しくなります。

例えば、『あるセル範囲(一覧)の値を、配列やクラス変数に詰める』などのような、局部的な処理で効力を発揮するでしょう。