昔、本項で比較したかったのは、要するに「For Next と For Each って、どっちが速いの?」ってことです。1995年にMicrosoftから出版されたVBAに関する公式本に「For Each の方が速いよ~理由はね~」って書いてあったからです。その頃調べた結果では、確かに For Each の方が速かったです。でも、時代は変わりました。と同時に、パソコンの性能も飛躍的に向上しています。理論的に速くても、体感速度として、あるいは計測結果としては、どうなんでしょう。
まず、For Next と For Each で比較してみましょう。
Sub Test1()
Dim i As Long
For i = 1 To 10000
Cells(i, 1) = 100
Next i
End Sub
Sub Test2()
Dim c As Range
For Each c In Range("A1:A10000")
c = 100
Next c
| 回 | For Next | For Each | % |
|---|---|---|---|
| 1 | 3.703 | 3.703 | 100.0% |
| 2 | 3.641 | 3.687 | 101.3% |
| 3 | 4.218 | 3.719 | 88.2% |
| 4 | 3.719 | 4.297 | 115.5% |
| 5 | 3.687 | 4.031 | 109.3% |
| 6 | 3.688 | 3.625 | 98.3% |
| 7 | 3.656 | 4.422 | 121.0% |
| 8 | 4.219 | 3.953 | 93.7% |
| 9 | 3.891 | 3.688 | 94.8% |
| 10 | 4.000 | 4.250 | 106.3% |
| 平均 | 3.842 | 3.938 | 102.5% |
でもまぁ考えてみれば、For Next と For Each って、考え方や使い方がそもそもまるで違うのですから、単純に"どっちが速い"って話じゃないように思います。だって、For Next のカウンタ変数は一般的にLong型ですし、対して For Each の制御変数は、オブジェクト型またはバリアント型ですから。すでに、そこが違っているわけですから、単純な比較はできないな~と。今になってそう思います。
でも、せっかくですから、もう少し検証してみましょう。上記のマクロは、1つのセルしか使っていません。でも、もし同じ行の複数セルを扱う場合。For Next なら次のように書けます。
Sub Test3()
Dim i As Long
For i = 1 To 10000
Cells(i, 1) = Cells(i, 2) + Cells(i, 3)
Next i
End Sub
対して For Each で同じことをやるなら、次のようになりますね。
Sub Test4()
Dim c As Range
For Each c In Range("A1:A10000")
c = c.Offset(0, 1) + c.Offset(0, 2)
Next c
Offsetが出てきました。さて、速度はどうでしょう。
| 回 | For Next | For Each | % |
|---|---|---|---|
| 1 | 4.125 | 3.859 | 93.6% |
| 2 | 4.563 | 3.875 | 84.9% |
| 3 | 3.766 | 3.828 | 101.6% |
| 4 | 3.843 | 3.797 | 98.8% |
| 5 | 3.797 | 3.765 | 99.2% |
| 6 | 3.766 | 3.781 | 100.4% |
| 7 | 3.750 | 3.781 | 100.8% |
| 8 | 3.781 | 4.532 | 119.9% |
| 9 | 3.766 | 4.485 | 119.1% |
| 10 | 4.547 | 3.750 | 82.5% |
| 平均 | 3.970 | 3.945 | 99.4% |
それほど変わりませんね。ちなみにVBAにはもうひとつ、Do Loopという繰り返しステートメントがあります。まぁ、ワークシート上のセルなどを操作するのでしたら、ほとんど使う機会もないのですけど。ああ、参考までに、本当を言うとVBAにはもうひとつ、While Wend という繰り返しもありますが、知ってる人はほとんどいないだろうし、使う必要性もないのでここでは触れません。
Sub Test5()
Dim i As Long
Do While i <= 10000
i = i + 1
Cells(i, 1) = Cells(i, 2) + Cells(i, 3)
Loop
End Sub
| 回 | For Next | Do Loop | % |
|---|---|---|---|
| 1 | 4.125 | 3.891 | 94.3% |
| 2 | 4.563 | 3.844 | 84.2% |
| 3 | 3.766 | 4.422 | 117.4% |
| 4 | 3.843 | 3.875 | 100.8% |
| 5 | 3.797 | 3.796 | 100.0% |
| 6 | 3.766 | 3.813 | 101.2% |
| 7 | 3.750 | 3.781 | 100.8% |
| 8 | 3.781 | 3.781 | 100.0% |
| 9 | 3.766 | 3.782 | 100.4% |
| 10 | 4.547 | 4.593 | 101.0% |
| 平均 | 3.970 | 3.958 | 99.7% |
昔の古いPCではともかく、現在のPCだったら、For Next だろうが For Each だろうが、ましてや Do Loop であっても、それほど速度差はないってことですかね。