🚀The world's best VBA AI has evolved. ExcelMaster is now an autonomous Agent.Read more →
Back to Blog

Excel VBA の Timer — マクロの処理時間を測る(そしてスケジューラではない理由)

|

Excel VBA の Timer — マクロの処理時間を測る(そしてスケジューラではない理由)

TL;DRTimer 関数は何も一時停止しませんし、何かをスケジュールに従って実行することもありません。深夜 0 時からの経過秒数を小数で返すだけで、コードのかたまりにかかった時間を測るために、その前後で読みます。

Sub HowLongDoesItTake()
    Dim t As Double
    t = Timer                     ' ストップウォッチを始動
    ' ... 測りたいコード ...
    Range("A1:A100000").Sort Key1:=Range("A1"), Order1:=xlAscending, Header:=xlNo
    Debug.Print "Took " & Format(Timer - t, "0.00") & " seconds"
End Sub

Timer は VBA で最も名前負けしている関数です。その名前はカウントダウンやスケジューラを約束するので、人は「5 分ごとに実行」や「待ってから発火」を求めて「vba timer」を検索します — けれど Timer はそのどちらもしません。これはストップウォッチ、「あれはどれだけかかったか?」に答える手段です。本記事はこの 1 つの考えを軸にしています。Timer をストップウォッチと見た瞬間に、その本当の仕事(ベンチマーク)と二つの罠(スケジューラではないこと、深夜 0 時またぎ)がそのまま導かれるからです。

この記事で学べること

  • 考え方の軸 — Timerストップウォッチ(経過時間を測る)であって、カウントダウンやスケジューラではない
  • その本当の仕事 — ベンチマーク、そして パフォーマンスのスイッチ が本当に効いたと証明する方法
  • ナンバーワンの誤った期待 — 「N 分ごとに実行」が欲しいなら、欲しいのは Application.OnTime
  • 負の経過時間を生む深夜 0 時またぎのバグと、そのガード
  • その分解能 — およそ 100 分の 1 秒 — と、それが向くこと・向かないこと

考え方の軸:二度読むストップウォッチ

ストップウォッチは何も起こしません。鳴りもせず、レースを止めもせず、走者をスタートさせもしません。文字盤の時間を教えるだけで、時間の長さは二度読んで引き算して得ます。Timer はまさにそれです。呼び出すと「深夜 0 時からの秒数」を Single で返し(だから 00:01:30 の Timer90.0 を返します)、コードにかかった時間は前後で読んで測ります。

Dim t As Double
t = Timer               ' 文字盤を読む: 例 43521.14
' ... 処理 ...
Debug.Print Timer - t   ' もう一度読んで引く: 経過秒数

ここに「一時停止」も「後で発火」もありません。Timer はマクロのすることを決して変えません — その一部がどれだけ続いたかを教えるだけです。Timer にコードを遅延してほしかったのなら、それは SleepApplication.Wait であって、Timer ではありません。

その本当の仕事:変更が本当にマクロを速くしたと証明する

ストップウォッチのモデルは、Timer何のためにあるかをまっすぐ指し示します — ベンチマークです。Application.ScreenUpdating を切る、Application.Calculation を手動に切り替える、セル単位のループを配列に置き換える — そのとき、速くなったと信じるのではなく、測るべきです。Timer がその方法です。

Sub ProveTheSwitchHelps()
    Dim t As Double

    t = Timer
    Application.ScreenUpdating = True         ' あえて遅いやり方
    WriteTenThousandRows
    Debug.Print "ScreenUpdating on:  " & Format(Timer - t, "0.00") & "s"

    t = Timer
    Application.ScreenUpdating = False        ' 速いやり方
    WriteTenThousandRows
    Application.ScreenUpdating = True
    Debug.Print "ScreenUpdating off: " & Format(Timer - t, "0.00") & "s"
End Sub

これは、あらゆるパフォーマンスの助言に対する正直な補完です。ScreenUpdatingCalculation などはやる価値がありますが、Timer は、俗説を繰り返すのではなく、それらがこのブックで効いたと知るための方法です。遅い行を見つける方法でもあります。怪しい数か所を Timer の読み取りで挟み、直感ではなく数字に、時間がどこへ消えるかを語らせましょう。

ナンバーワンの誤った期待:Timer はスケジューラではない

ほとんどの人を検索エンジンへ送り込む誤解がこれです。マクロに5 分ごとに自分で走ってほしい、あるいは遅延の後に何かしてほしい、そして Timer という名前のものがそれに違いないと思い込む。違います。Timer は経過時間を報告するだけで、何かを引き起こすことは決してありません。

本当に欲しいものを名指ししましょう。

  • マクロを後で、あるいは繰り返しのスケジュールで実行する(「5 分ごとに更新」「午前 9 時に実行」)— Application.OnTime。Excel に時刻とマクロ名を渡し、その呼び出しを予約します。
  • マクロを一定の遅延だけ一時停止するSleep(ミリ秒)または Application.Wait(整数秒)。
  • 何かにどれだけかかったかを測るTimer。これだけ、これに限ります。

Timer で「N 秒ごとに繰り返す」ループを組もうとしている自分に気づいたら、やめましょう。欲しいのは OnTime です。ループの中の Timer は、クロックを読むだけで CPU を燃やします。

深夜 0 時またぎのバグ

Timer深夜 0 時からの秒数を測るので、0 時に 0 へリセットされます。だから 23:59:58 に始まり 00:00:03 に終わるマクロは、Timer - t をおおよそ 3 - 86398 = -86395 と計算します — の経過時間です。まれですが、実在し、「マクロにマイナス 24 時間かかった」という不可解なバグ報告を一度ならず生んできました。

実行が深夜 0 時をまたぐ可能性が少しでもあるなら、それをガードするか、代わりに Now で測りましょう。

Dim elapsed As Double
elapsed = Timer - t
If elapsed < 0 Then elapsed = elapsed + 86400   ' 一日分の秒数を足す

何時間も走りうるものには、日付ベースのタイミング(Now、あるいは Date + Timer の組み合わせ)を選び、深夜 0 時の越境が結果を壊せないようにしましょう。よくあるケース — 秒や分で終わるかたまりを測る — では、素の Timer - t で完璧です。

分解能:100 分の 1 秒

Timer は Windows でおよそ10 ミリ秒ごと(約 100 分の 1 秒)に更新されます。Timer が本来答えるべき問いには、それで十分です。「バージョン A は B より速いか?」「このインポートにどれだけかかるか?」「この 3 行のどれが遅いのか?」。マイクロベンチマークには足りません — 100 分の 1 秒を大きく下回る処理を測っても、0 としか報告されません。その精度が要るときは、処理を数千回ループして割るか、QueryPerformanceCounter API まで下りましょう。日々の「速くして、それを証明する」仕事には、Timer がまさに適役です。

ExcelMaster の活用

Timer は単純ですが、うまく使うことは小さな習慣の束です。Double に読み込む、正しい順序で引く、読みやすいよう結果を Format する、長い実行では深夜 0 時のケースをガードする、そして — 人が飛ばす部分 — 計測が意味を持つように正しいコードをちゃんと挟む。そして目的が「これをスケジュールで実行」や「ここで止める」なら、Timer はまったく間違った道具です。

ExcelMaster は、あなたが述べた内容に合った道具を選びます。「マクロにかかる時間を測って」と頼めば、整った Timer ベースのベンチマークを、書式化した Debug.Print とともに落とし込みます。「5 分ごとに実行して」と頼めば、代わりに Application.OnTime を配線します。「少し止めて」と頼めば、WaitSleep に手を伸ばします。スケジューラのふりをした Timer ループではなく、欲しかった計測が手に入ります。

よくある質問

VBA でマクロにかかる時間を測るには?

測りたいコードの前後で Timer 関数を読み、引き算します。始めに t = Timer、終わりに Debug.Print Timer - tTimer は深夜 0 時からの秒数を小数で返すので、その差が経過時間(秒)です。読みやすい結果にするには Format(..., "0.00") で包みましょう。

VBA の Timer 関数はコードを止めたりスケジュール実行したりしますか?

いいえ。Timer は深夜 0 時からの経過秒数を報告するだけで、マクロを止めることも、何かを引き起こすこともありません。止めるには SleepApplication.Wait を、マクロを後で・繰り返しのスケジュールで実行するには Application.OnTime を使います。Timer は、経過時間を測るためのストップウォッチにすぎません。

VBA の経過時間が負になるのはなぜですか?

Timer が深夜 0 時にゼロへリセットされるからです。マクロが 0 時の直前に始まり直後に終わると、Timer - t は大きな「開始前」の値を小さな「終了後」の値から引いて負になります。結果が負のときは 86400(一日分の秒数)を足してガードするか、0 時をまたぎうる実行では Now で測りましょう。

Timer と Application.OnTime の違いは何ですか?

Timer は経過時間を測ります — コードにどれだけかかったかを知るために読みます。Application.OnTime は、特定の時刻や遅延の後に走るようマクロを予約します。人はよくスケジューラを求めて「vba timer」を検索しますが、その仕事は Timer ではなく Application.OnTime のものです。

VBA の Timer 関数はどれくらい正確ですか?

Timer は Windows でおよそ 100 分の 1 秒(約 10 ミリ秒)の分解能です。二つのやり方を比べたりインポートの時間を測ったりするには十分ですが、約 10 ミリ秒より速い処理は 0 と報告されます。マイクロベンチマークには、処理を何度も繰り返して割るか、QueryPerformanceCounter という Windows API を使いましょう。

検証環境

検証環境: Excel 365 (Windows 11), VBA 7.1 — 最終確認 2026-08-19。

関連ガイド: VBA Wait · VBA Sleep · VBA ScreenUpdating · VBA Calculation · VBA DoEvents