コードの実行がどのくらいかかるか,経過時間を知りたい場合があると思います。私の場合は以下のような時です。
- 膨大な時間がかかる処理を幾つかに分けて行う場合,まず一つ実行してみて,全体でどれぐらいかかるか知りたい。
- コードの高速化を図りたいとき,現在のコードでどれぐらい時間がかかるか,改善したコードでどれぐらい短縮できるかを知りたい。
このような場合,以下の3手法があります。
- Now関数とDateDiff関数による方法 → 1秒単位でしか計測できない
- Timer関数の差分を用いる → 日付を超えて計測できない
- Windows API のGetTickCount関数 → ミリ秒単位で計測が可能
場合によっては,1番目や2番目の手法で十分なケースがあると思いますが,どのようなケースでも汎用性がある3番目の手法を使うようにしています。
はじめに
何をする関数か
計測を開始した時点から計測を終了する時点までの経過時間をミリ秒単位で計測します。
引数・戻り値
引数
GetTickCountによる計測ミリ秒
戻り値
「○時間 ○分 ○.○○○秒」の書式の文字列
動作確認状況
Excel | 32ビット | 64ビット |
---|---|---|
2007 | OK | – |
2010 | たぶんOK(未確認) | たぶんOK(未確認) |
2011 Mac | NG | – |
2013 | OK | OK |
最初に作成したのは2007でした。2013では32/64ビットとも確認しました。
Win32APIを用いているのでMacでは動きません。
関数の作成
標準モジュールに関数を作成します。(Publicを省略していますが、パブリック関数になります。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
Function ElapsedTime(t As Long) As String Dim h As Integer Dim m As Integer Dim s As Single If t > 3600000 Then '1時間を超えていたら h = Int(t / 3600000) '時間数を計算 ElapsedTime = h & "時間 " '文字列に変換 t = t - h * 3600000 '経過時間から時間数の分を控除 End If If t > 60000 Then '1分を超えていたら m = Int(t / 60000) '分数を計算 ElapsedTime = ElapsedTime & m & "分 " '文字列に変換して加える t = t - m * 60000 '経過時間から分数のぶんを控除 End If s = t / 1000 '1分未満の秒数 ElapsedTime = ElapsedTime & s & "秒 " '文字列に変換して加える End Function |
引数t(ミリ秒)から経過時間、分、秒を計算しています。
例えばt=5,025,678ミリ秒の場合、1時間(=1×60×60×1000ms)+23分(=23×60×1000ms)+45.678秒(=45.678×1000ms)となります。
簡単な内容なので,説明はコード中のコメントに記載したとおりですが、ミリ秒を変換して「○時間 ○分 ○.○○○秒」の文字列を作成しています。ただし1時間を超えない場合は,分と秒,1分を超えない場合は,秒のみ表示するようにしています。
使用例
前準備
まず,適当な標準モジュールの宣言セクションに以下のように書きます。
1 2 3 4 5 |
#If VBA7 And Win64 Then '64ビット版 Private Declare PtrSafe Function GetTickCount Lib "kernel32" () As Long #Else '32ビット版 Private Declare Function GetTickCount Lib "kernel32" () As Long #End If |
これにより,Windows APIのGetTickCount関数が使えるようになり,Windowsが起動してからの経過時間をミリ秒で取得出来ます。
※64ビットでも動作するように変更しました。
計測開始部
次に,時間計測を開始したい箇所に以下のように書きます。
1 |
Dim Start As Long: Start = GetTickCount |
GetTickCountは、システムを起動した後の経過時間を、ミリ秒(ms)単位で取得できますが、計測開始時の値をStartに代入します。
計測終了部
最後に,時間計測を終了したい箇所に以下のように書きます。
1 2 3 4 5 |
Dim Elapsed As Long: Elapsed = GetTickCount - Start MsgBox ElapsedTime(Elapsed) '経過時間をダイアログで表示 Debug.Print ElapsedTime(Elapsed) 'またはイミディエイトウィンドウに表示 |
1行目
計測終了時のGetTickCountから、計測開始時のGetTickCount(=Start)の差をミリ秒で得て、その経過時間(ミリ秒)をElapsedに代入します。
3,5行目
Elapsed(ミリ秒)を、先ほど作成したElapsedTime関数を用いて「○時間 ○分 ○.○○○秒」の文字列に変換します。
これを確認するため、ダイアログボックスを表示する場合は4行目、イミディエイトウィンドウに表示する場合は6行目のように記述します。
おわりに
この関数は経過時間を計測する機能に過ぎませんが、これで確認しながらコードの高速化を検討してみてはいかがでしょうか。