ForEach文
VBAでは、For文と呼ばれる構文は2種類あります。
『For文』と『ForEach文』です。
For文とは、指定した数分だけループさせる構文です。
ForEach文とは、配列の領域分だけループさせる構文です。
ForEach文は他の言語でも存在しますが、VBA特有の使い方で検証してみたいと思います。
まずは、ForEach文の基本的な記述方法を以下に示します。
この例では、イミディエイトウインドウに、
あ
い
う
と、表示されます。
また、ForEach文は、配列だけでなくコレクション(オブジェクト)も指定することができるので、セルを指定してループすることもできます。
この例では、イミディエイトウインドウに、
セルA1の値
セルB1の値
セルC1の値
が、表示されます。
セル範囲のループは、VBAプログラムではよくあるロジックなのですが、工夫次第で性能が向上することはご存知でしょうか。
今回の検証では、2つパターンを用意して、検証します。
セル範囲をRange型でループ サンプルプログラム
ただ単純に、A列をForEach文を使ってループさせるだけのサンプルです。
セル範囲はRange型なので、Range型を各要素に割り当ててループをさせます。
セル範囲をVariant型でループ サンプルプログラム
2つ目のサンプルも、1つ目と同様に、A列をForEach文を使ってループさせています。
違う点は、各要素に割り当てる変数の型がVariantであるところと、セル範囲の型をVariantに変換して(配列に詰め直して)ループさせているところです。
検証
上記2つのパターンについての実行結果は以下の通りです。
回数 | Range型でループ | Variant型でループ |
---|---|---|
1回目 | 0.047 | 0.031 |
2回目 | 0.063 | 0.031 |
3回目 | 0.062 | 0.031 |
4回目 | 0.046 | 0.047 |
5回目 | 0.062 | 0.016 |
6回目 | 0.063 | 0.031 |
7回目 | 0.063 | 0.047 |
8回目 | 0.062 | 0.031 |
9回目 | 0.062 | 0.046 |
10回目 | 0.046 | 0.047 |
平均 | 0.058 | 0.036 |
※単位は全て『秒』
Variant型でループさせる方法が、Range型でループさせる方法より、
62.15%速くなっています。
これは、単純にVariant型とRange型の領域の差が出ているだけです。
この例では、セル範囲を1列のみとしましたが、列を増やすとさらに性能に差が出ます。
以下に、3列の場合と10列の場合の検証結果を示します。
3列(A:C)の場合の検証結果
回数 | Range型でループ | Variant型でループ |
---|---|---|
1回目 | 0.109 | 0.047 |
2回目 | 0.125 | 0.031 |
3回目 | 0.125 | 0.063 |
4回目 | 0.203 | 0.063 |
5回目 | 0.125 | 0.062 |
6回目 | 0.125 | 0.047 |
7回目 | 0.125 | 0.047 |
8回目 | 0.109 | 0.047 |
9回目 | 0.109 | 0.031 |
10回目 | 0.109 | 0.062 |
平均 | 0.1264 | 0.050 |
3列の場合、39.56%速くなっています。
10列(A:J)の場合の検証結果
回数 | Range型でループ | Variant型でループ |
---|---|---|
1回目 | 0.359 | 0.093 |
2回目 | 0.375 | 0.078 |
3回目 | 0.375 | 0.109 |
4回目 | 0.359 | 0.109 |
5回目 | 0.359 | 0.094 |
6回目 | 0.360 | 0.109 |
7回目 | 0.359 | 0.094 |
8回目 | 0.375 | 0.094 |
9回目 | 0.359 | 0.093 |
10回目 | 0.344 | 0.094 |
平均 | 0.3624 | 0.0967 |
※単位は全て『秒』
10列の場合、26.68%速くなっています。
これにより、列を増やせば増やすほど、Variant型がより速くなることがわかります。
ただ今回のケースが有効になるのは、セルの値を取得する処理くらいでしょう。
Variant型の場合、値の参照しかできないので、Range型が持つさまざまなプロパティやメソッドは使えなくなります。
例えば、『あるセル範囲の中で、特定の文字列を含む行を削除』なんてプログラムを組むのは難しくなります。
例えば、『あるセル範囲(一覧)の値を、配列やクラス変数に詰める』などのような、局部的な処理で効力を発揮するでしょう。