実行速度を速くしよう。

マクロを組むようになると、いろいろな処理が自動でできるようになり、作り上げた喜びもどんどん大きくなっていきます。
それはそれでいいのですが、処理に時間がかかるようだと、使っている時ストレスを感じます。
したがって、『いかに実行速度をあげるか?』を考えてマクロを組むことが重要です。
以下で、その例を紹介します。

1.画面表示の更新をOFFにする。

 下のマクロは、どちらも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回だけ行って時間の短縮をしているわけです。

2.変数で処理をする。

 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は変数を使って処理をしています。

つまり、メモリ(変数)で計算をした方が実行速度が速くなるのです。

2.文字よりも数値を扱う。

 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バイト+文字列の長さ 可変長の文字列型の範囲と同じ 

3.条件分岐を整理する。(IF文、Select文)

 様々な処理をするとき、条件によって処理を変えることはよくあります。
 しかし、ここでも実行速度を速くする手段が残されています。
 マクロの組み方を工夫して、処理するときの、判断する条件を少なくするのです。

 下の例で、例えば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

4.マクロに処理させる仕事を減らす。

 今までにいろいろと書いてきましたが、
 最終的には、マクロに処理をさせる仕事を減らすことが一番効果が大きいです。
 3のところで、条件分岐を整理することを書きましたが、それもひとつなのです。
 処理する仕事が少なければ実行速度が速くなるのは、当たり前のことです。

 例えば、電話番号から兄弟関係を検索するケースを考えてみましょう。
 電話番号が一致すれば、兄弟になりますね。
 
 5人の電話番号を比較するとき、ただ順番に比較すると、
 1人目が4人、2人目が3人、3人目が2人比較することになり、9回比較することになります。
 しかし、兄弟がいるところだけ比較したらどうでしょうか?
 処理する回数を減らすことができます。(*1
 さらに、兄弟の数の分だけ一致があったら、処理を中断して次の処理に移ったらどうでしょう。
 さらに、処理速度が速くなっていきます。(*2

 このように、工夫して仕事を減らしてやることが、処理速度の向上につながっていくのです。

 (おまけ)たぶん、比較する文字数も少ない方が、比較が速くできると思います。

*1  兄弟がいるかどうかを、どうやって調べればいいのか?
これは、ワークシートで電話番号の横にCountIf文を入力します。
全体の中で同じ電話番号がいくつあるか数えればいいのです。
そして、2以上の場所だけ比較することになります。

 
*2  上の画像の場合だと、@の処理でBのところで1つ見つかるので、それ以降の比較をやめて、
次のAの比較をしていくことになります。