マクロを組むようになると、いろいろな処理が自動でできるようになり、作り上げた喜びもどんどん大きくなっていきます。
それはそれでいいのですが、処理に時間がかかるようだと、使っている時ストレスを感じます。
したがって、『いかに実行速度をあげるか?』を考えてマクロを組むことが重要です。
以下で、その例を紹介します。
下のマクロは、どちらもA1に1を10000回足していきます。
そして、処理が終了したら、メッセージを表示するようにしています。
ところが、このマクロを実行させてみると、明らかに「B」のマクロの方が処理速度が速いのです。
それは、どうしてなのでしょうか?
| Sub A() Dim n As Integer Cells(1, 1) = "" For n = 1 To 10000 Cells(1, 1) = Cells(1, 1) + 1 Next n MsgBox "終了!" End Sub |
| Sub B() Dim n As Integer Cells(1, 1) = "" Application.ScreenUpdating = False For n = 1 To 10000 Cells(1, 1) = Cells(1, 1) + 1 Next n Application.ScreenUpdating = True MsgBox "終了!" End Sub |
AとBのマクロの違いは、 Applicationオブジェクトを使っているかどうかです。 ApplicationオブジェクトのScreenUpdatingで、 画面表示の更新をするかしないかを設定します。 (Falseは、しない。Trueは、する。) 更新をしないとどうなるか? 処理が済んでも、ワークシートの表示は変わりません。 実は、パソコンが処理をするとき、画面表示にずいぶんと時間がかかっているのです。 そこで、画面表示の更新を、最後に1回だけ行って時間の短縮をしているわけです。 |
A1に1を10000回足していく処理を、少しやり方を変えてみます。
実際に実行させてみると、さきほどの「B」のマクロより「C」のマクロの方が処理速度が速くなります。
これは、なぜでしょうか?
| Sub B() Dim n As Integer Cells(1, 1) = "" Application.ScreenUpdating = False For n = 1 To 10000 Cells(1, 1) = Cells(1, 1) + 1 Next n Application.ScreenUpdating = True MsgBox "終了!" End Sub |
| Sub C() Dim n As Long Dim 合計 As Integer For n = 1 To 10000 合計 = 合計 + 1 Next MsgBox "終了!" End Sub |
BとCのマクロの違いは、 Bはセルを使って処理をしているのに対して、 Cは変数を使って処理をしています。 つまり、メモリ(変数)で計算をした方が実行速度が速くなるのです。 |
Dim文で行う変数の宣言には、さまざまなデータ型があります。
以下に、代表的なものを書き出してみます。
特に考えもなく数値の変数を宣言するときは、整数型で行うのがいいでしょう。
大抵の場合には、対応できます。
さて、その整数型と文字列型の記憶領域を比較してみると、
整数型が2バイトしか使わないのに対して、文字列型は最低で10バイト使います。
(最低というのは、文字が入ってない状態です。)
5倍もの開きがあるので、処理を続けていけば、ずいぶんな時間の差が出てくるはずです。
したがって、数値に置き換えて処理できるのであれば、数値に置き換えた方が処理速度が速くなります。
| データ型 | 記憶領域 | 範囲 |
| バイト型(Byte) | 1バイト | 0〜255 |
| ブール型(Boolean) | 2バイト | 真(True)または偽(False) |
| 整数型(Integer) | 2バイト | −32,768〜32,767 |
| 文字列型(String)(可変長) | 10バイト+文字列の長さ | 0〜2GB |
| バリアント型(Variant)(数値の場合) | 16バイト | 倍精度不動小数点型の範囲と同じ |
| バリアント型(Variant)(文字列の場合) | 22バイト+文字列の長さ | 可変長の文字列型の範囲と同じ |
様々な処理をするとき、条件によって処理を変えることはよくあります。
しかし、ここでも実行速度を速くする手段が残されています。
マクロの組み方を工夫して、処理するときの、判断する条件を少なくするのです。
下の例で、例えばA=Bという条件一致があまり起こらないような場合、
(例2)の方が処理速度が速くなります。
というのは、(例1)では、IF文で5つの条件比較をしているのに対して、
(例2)では、1つめの条件が一致しなければ、あとの条件比較は省いて次の処理に進めるからです。
このことが度重なれば、その時間の差は大きくなってきます。
条件分岐をするときは、一番一致しにくい条件から個別に並べることが重要です。
| (例1) If A = B And B = C And C = D And D = E And E = F Then MsgBox "一致" End If |
| (例2) If A = B Then If B = C Then If C = D Then If D = E Then If E = F Then MsgBox "一致" End If End If End If End If End If |
今までにいろいろと書いてきましたが、
最終的には、マクロに処理をさせる仕事を減らすことが一番効果が大きいです。
3のところで、条件分岐を整理することを書きましたが、それもひとつなのです。
処理する仕事が少なければ実行速度が速くなるのは、当たり前のことです。
例えば、電話番号から兄弟関係を検索するケースを考えてみましょう。
電話番号が一致すれば、兄弟になりますね。
5人の電話番号を比較するとき、ただ順番に比較すると、
1人目が4人、2人目が3人、3人目が2人比較することになり、9回比較することになります。
しかし、兄弟がいるところだけ比較したらどうでしょうか?
処理する回数を減らすことができます。(*1)
さらに、兄弟の数の分だけ一致があったら、処理を中断して次の処理に移ったらどうでしょう。
さらに、処理速度が速くなっていきます。(*2)
このように、工夫して仕事を減らしてやることが、処理速度の向上につながっていくのです。
(おまけ)たぶん、比較する文字数も少ない方が、比較が速くできると思います。
| *1 | 兄弟がいるかどうかを、どうやって調べればいいのか? これは、ワークシートで電話番号の横にCountIf文を入力します。 全体の中で同じ電話番号がいくつあるか数えればいいのです。 そして、2以上の場所だけ比較することになります。 ![]() |
| *2 | 上の画像の場合だと、@の処理でBのところで1つ見つかるので、それ以降の比較をやめて、 次のAの比較をしていくことになります。 |