wrote :: 2005.01.18

トップページ > Excel > VBA > 高速化テクニック > 何度も同じこと言わせるな!


何度も同じこと言わせるな!

内容にもよりますが、10行のマクロと1000行のマクロでは、普通10行のマクロの方が高速です。それは、行数が少ないからではなく、Excelが実行するコマンドの数が少ないからです。ちょっと乱暴な言い方をすれば、使用するコマンドの数を少なくすればマクロの実行速度を上げることが出来るわけです。

もちろん動作に必要なコードを削ることはできませんが、同じ動作を実現するにしてもコードを簡素化することは可能です。

 Test1Test2%
1回目00:1600:16100.0%
2回目00:1600:1593.8%
3回目00:1600:16100.0%
4回目00:1600:1593.8%
5回目00:1600:16100.0%
6回目00:1700:1694.1%
7回目00:1600:16100.0%
8回目00:1600:1593.8%
9回目00:1600:1593.8%
10回目00:1700:1694.1%
平均00:1600:1696.3%
下記のTest1とTest2を計測してみました。それほど大きい差はでませんでしたね。Excel 97の頃は10%〜20%の速度アップでしたが、今回の計測では5%前後。ほとんど差がないと言ってもいいでしょう。

Sub Test1()
    Dim i As Integer, j As Integer
    For i = 1 To 300
        For j = 1 To 10
            ActiveWorkbook.Worksheets(1).Range("A1").Value = _
            ActiveWorkbook.Worksheets(1).Range("A1").Value + j
        Next j
    Next i
End Sub

Sub Test2()
    Dim i As Integer, j As Integer
    With ActiveWorkbook.Worksheets(1).Range("A1")
    For i = 1 To 300
        For j = 1 To 10
                .Value = .Value + j
        Next j
    Next i
    End With
End Sub

ActiveWorkbook.Worksheets(1).Range("A1").Valueを分解すると、

(1)ActiveWorkbookプロパティ
(2)Worksheetsプロパティ
(3)Rangeプロパティ
(4)Valueプロパティ

と、4つのプロパティを参照しています。Test1では、さらに4つのプロパティで参照した数値を代入していますので合計8プロパティです。それに対してTest2では、ActiveWorkbookプロパティ、Worksheetsプロパティ、Rangeプロパティの3つをWithステートメントで省略しています。そのWithステートメントは、For Nextステートメントの外に記述している点に留意してください。これなら、For Nextステートメントの内部で実行されるプロパティは2つで済みます。

速度的に大きな差はありませんでしたが、こんなケースでは絶対Withステートメントを使うべきです。コードの可読性が高まり修正や編集が容易になり、同時にアドレスの間違いなど単純なバグの混入も減ります。何より、美しいです。同じプロパティを何度も記述して同じオブジェクトを操作するようなときには、まずWithステートメントの使用を検討してください。

ちなみに、次のようなコードも計測してみました。

Sub Test3()
    Dim i As Integer, j As Integer, myCell As Range
    Set myCell = ActiveWorkbook.Worksheets(1).Range("A1")
    For i = 1 To 300
        For j = 1 To 10
                myCell.Value = myCell.Value + j
        Next j
    Next i
End Sub

 Test1Test3%
1回目00:1600:20125.0%
2回目00:1600:19118.8%
3回目00:1600:20125.0%
4回目00:1600:20125.0%
5回目00:1600:19118.8%
6回目00:1700:20117.6%
7回目00:1600:19118.8%
8回目00:1600:20125.0%
9回目00:1600:20125.0%
10回目00:1700:20117.6%
平均00:1600:20121.6%
Test3は、WithステートメントでActiveWorkbook.Worksheets(1).Range("A1")を省略するのではなく、myCellというオブジェクト型変数に格納しています。操作の対象となるオブジェクトが簡単にアクセスできないとき、こうして事前にオブジェクト型変数に格納しておき、以降で使用するのはよくやるテクニックです。

ところが、意外なことに実行速度は逆に遅くなりました。現在のところ、原因はわかりません。

個人的な感覚ですが、何度もプロパティを使ってオブジェクトを特定するとき、Withステートメントで省略するかオブジェクト型変数を使うかは、人によって好き嫌いがあるようです。Withステートメント派は、Withの中でさらにWithを使い…とWithステートメントのネストにも抵抗がありません。一方のオブジェクト変数派は、プロシージャの先頭でとにかくオブジェクト変数に格納しまくり、いくつかの変数は結局一度も使わない…なんてこともあります。どちらかに固執するのではなく、ケースに応じて柔軟に使い分けられるようにしたいものです。ちなみに私はガチガチのWithステートメント派です(^^;


[余計なことはするな!]戻る← | →進む[個別に呼ぶな!]