個別に呼ばない


昔、本項で比較したかったのは、要するに「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 であっても、それほど速度差はないってことですかね。