【社内SE必見】VBA Timerでマクロの処理速度を精密計測!ボトルネック特定から高速化への第一歩
「このマクロ、またフリーズしてる…」「処理が終わるまで休憩でも行くか…」
日々寄せられるユーザーからの問い合わせや、度重なるルーティン業務の中で、動作の遅いVBAマクロに頭を悩ませる社内SEの皆さん、そのイライラ、本当によく分かります。処理に10分かかるマクロを何とか1分に短縮したい、でもどこから手をつければいいのか…。
マクロ高速化の第一歩は、「どこが遅いのか」を正確に把握することです。感覚ではなく、客観的な数値でボトルネックを特定するためには、処理速度の計測が不可欠。
今回は、VBAに標準で備わるTimer関数を使って、マクロの処理速度を手軽に、そして正確に計測する方法を解説します。
コピペで即実践!Timer関数を使った処理速度計測コード
まずは、VBAのTimer関数を使った基本的な計測コードをご紹介します。このコードをマクロの開始前と終了後に挿入するだけで、瞬時に処理時間を計測できます。変数はSingle型を使用しましょう。
Sub MeasureMacroPerformance()
Dim startTime As Single
Dim endTime As Single
Dim elapsedTime As Single
Dim i As Long ' ループ処理のデモンストレーション用
' ★ここから計測開始★
startTime = Timer
' =========================================================
' ここに計測したい処理を記述します
' =========================================================
' 例: 100万回のループ処理(実際の業務処理を想定)
Debug.Print "処理を開始します..."
For i = 1 To 1000000 ' 例として、時間のかかるループ処理
' 何らかの計算やオブジェクト操作をシミュレート
If i Mod 100000 = 0 Then ' 適度にDoEventsを入れてフリーズを回避
DoEvents
End If
Next i
Debug.Print "処理が完了しました。"
' =========================================================
' ★ここまで計測終了★
endTime = Timer
' 処理時間を計算(秒単位、小数点以下まで細かく表示)
elapsedTime = endTime - startTime
' 結果の表示(イミディエイトウィンドウとメッセージボックス)
Debug.Print "============================================="
Debug.Print "計測結果:"
Debug.Print "処理時間: " & Format(elapsedTime, "0.000") & "秒"
Debug.Print "============================================="
MsgBox "マクロの処理が完了しました!" & vbCrLf & _
"処理時間: " & Format(elapsedTime, "0.000") & "秒", _
vbInformation, "処理速度計測結果"
End Sub
このコードをモジュールに貼り付け、「ここに計測したい処理を記述します」と書かれた部分に、あなたが速度改善したいマクロの処理をコピペしてください。
実行すると、イミディエイトウィンドウ(Ctrl+Gで表示)とメッセージボックスに処理時間が秒単位で表示されます。
Timer関数の落とし穴と長時間処理の計測方法
Timer関数は手軽で非常に便利ですが、一つ大きな落とし穴があります。
【重要】Timer関数は午前0時でリセットされます!
Timer関数は、システムが午前0時0分0秒になってからの経過秒数を返します。そのため、日を跨ぐような長時間処理の計測には使えません。
例えば、午後11時59分55秒に計測を開始し、午前0時05秒に処理が終了した場合、結果は負の値となり正確な時間を計測できません。
ほとんどのVBAマクロは数秒~数分で完結するためTimer関数で十分ですが、もし数十分や数時間かかるようなバッチ処理を計測する場合は、別の方法が必要です。
そのようなケースでは、Now()関数とDateDiff関数を組み合わせるのが最もシンプルで確実です。
Sub MeasureLongRunningMacroPerformance()
Dim startTime As Date ' Date型で日付と時刻を記録
Dim endTime As Date
Dim elapsedSeconds As Long ' 秒単位の経過時間
' ★ここから計測開始★
startTime = Now ' 現在の日付と時刻を記録
' =========================================================
' ここに計測したい長時間処理を記述します
' =========================================================
' 例: 非常に時間のかかる処理(デモのため10秒待機)
Debug.Print "長時間処理を開始します..."
' 実際の処理の代わりに、10秒間待機するコード
Application.Wait Now + TimeValue("00:00:10")
Debug.Print "長時間処理が完了しました。"
' =========================================================
' ★ここまで計測終了★
endTime = Now ' 終了時の日付と時刻を記録
' 経過時間を秒単位で計算(DateDiff関数は日付を跨いでも正確)
elapsedSeconds = DateDiff("s", startTime, endTime)
' 結果の表示(イミディエイトウィンドウとメッセージボックス)
Debug.Print "============================================="
Debug.Print "長時間処理の計測結果:"
Debug.Print "処理時間 (秒): " & elapsedSeconds & "秒"
Debug.Print "処理時間 (分): " & Format(elapsedSeconds / 60, "0.00") & "分"
Debug.Print "============================================="
MsgBox "長時間マクロの処理が完了しました!" & vbCrLf & _
"処理時間: " & Format(elapsedSeconds / 60, "0.00") & "分 (" & elapsedSeconds & "秒)", _
vbInformation, "長時間処理速度計測結果"
End Sub
Now()関数は現在の日付と時刻をDate型で返し、DateDiff関数は指定した単位("s"で秒)で二つのDate型の差を計算します。これにより、日を跨ぐ処理でも正確な時間を計測できます。
DateDiffは分("n")や時間("h")でも計測できますが、ボトルネック特定には秒単位が適しているでしょう。
まとめ:計測は高速化への羅針盤
VBAのTimer関数は、ちょっとしたマクロの処理速度を計測するのに非常に手軽で便利です。ほとんどの社内SEが直面する「遅いマクロ」のボトルネック特定に大いに役立つでしょう。ただし、日を跨ぐような超長時間処理の場合はNow()関数とDateDiff関数を組み合わせるのが鉄則です。
処理速度を「測る」ことは、「改善する」ための最初にして最も重要なステップです。計測によってボトルネックが特定できれば、そこに対して具体的な対策(画面更新の停止、計算ロジックの見直し、Range操作の最小化など)を講じることができます。 ぜひ、今回ご紹介したコードを活用して、あなたのVBAマクロを「10分かかる処理から1分で終わるスマートな処理」へと進化させ、社内の業務効率を飛躍的に向上させてください!