読者です 読者をやめる 読者になる 読者になる

ぼくLog

子持ち、車持ち、マンション持ちの僕の日常を綴ります。車と、ラクをしたい一心で覚えたエクセルVBAを中心になりそうです。

クラスとCollectionを使ったストップウォッチ|エクセルVBA

エクセル VBA マクロ

f:id:yt4u:20160629211204j:plain

エクセルVBAで経過時間を計測するには2つ。

  • Timer関数を使う
  • Windows API の timeGetTime を使う

Timer関数を使ったストップウォッチはこちらの記事をご参照ください。

yt4u.hatenablog.com


今回は、Windows API の timeGetTime を使って、クラスとCollectionを活用したストップウォッチを作ってみました。


なお、Collectionの使い勝手いいんですよ、っていう話はこちらの記事をご参照ください。

yt4u.hatenablog.com


APIを用意

まず、APIを記述するための標準モジュールを用意。

ここでは、その標準モジュールを「blAPI」とする。
("bl"はBokuLogから取ったものです)

標準モジュール「blMdlAPI」

Declare Function timeGetTime Lib "winmm.dll" () As Long


クラスを用意

ストップウォッチ機能を持ったクラスを用意します。

ここでは、そのクラスモジュールを「blClsStopWatch」とする。

クラスモジュール「blClsStopWatch」

Option Explicit

Private mlngStartTime             As Long             'スタートした時間(ミリ秒)
Private mlngQuitTime              As Long             'ストップした時間(ミリ秒)
Private mlngRap                   As Long             'ラップタイム(ミリ秒)
Private mcolRaps                  As Collection       'ラップタイム(秒)コレクション
Private Const mcdblConvRatio      As Double = 0.001   'ミリ秒を秒に変換するための掛け目


Private Sub Class_Initialize()

  Set mcolRaps = New Collection

End Sub


Private Sub Class_Terminate()

  Set mcolRaps = Nothing
  
End Sub


'=========================================================
'スタート時間
'=========================================================
Public Sub Start()

  mlngStartTime = timeGetTime

End Sub


'=========================================================
'ラップタイム
'Rap を返すとともにラップタイムコレクションに格納
'=========================================================
Public Function Rap() As Double
  Dim dblRap            As Double

  If mcolRaps.Count = 0 Then
  
    mlngRap = timeGetTime
  
    dblRap = ((mlngRap - mlngStartTime) * mcdblConvRatio)
             
  Else
      
    dblRap = ((timeGetTime - mlngRap) * mcdblConvRatio)
              
    mlngRap = timeGetTime
              
  End If

  mcolRaps.Add dblRap

  Rap = dblRap

End Function


'=========================================================
'ストップ時間
'=========================================================
Public Sub Quit()

  mlngQuitTime = timeGetTime
  
  mcolRaps.Add (mlngQuitTime - mlngRap) * mcdblConvRatio
   
End Sub


'=========================================================
'経過時間(ミリ秒)
'=========================================================
Public Property Get ProcessingTime() As Double

  ProcessingTime = (mlngQuitTime - mlngStartTime) * mcdblConvRatio

End Property


'=========================================================
'ラップタイムコレクションを返す
'=========================================================
Public Property Get Raps() As Collection

  Set Raps = mcolRaps

End Property

これでストップウォッチクラスが完成です。


実行用標準モジュールを用意

では、作ったストップウォッチクラスの動きを確認してみます。

標準モジュール「blMdlTest」を用意します。

標準モジュール「blMdlTest」

Sub testStopWatch()
  Dim stopWatch         As blClsStopWatch
  Dim colRaps           As Collection
  Dim lngR              As Long
  
  Set stopWatch = New blClsStopWatch
  
  stopWatch.Start
    
  MsgBox stopWatch.Rap
  MsgBox stopWatch.Rap
  MsgBox stopWatch.Rap
  MsgBox stopWatch.Rap
  MsgBox stopWatch.Rap
    
  stopWatch.Quit
  
  Debug.Print stopWatch.ProcessingTime

  
  Set colRaps = stopWatch.Raps
  
  For lngR = 1 To colRaps.Count
  
    ActiveSheet.Cells(lngR, 1).Value = colRaps(lngR)
  
  Next

  Set stopWatch = Nothing
  Set colRaps = Nothing

End Sub

これを実行すると、次々にラップタイムがメッセージボックスに表示されていきます。


最初のメッセージボックスは、「Start」してすぐなのでほぼ0秒と表示されます。

その次からは、前のメッセージボックスが表示されてから、次のメッセージボックスが表示されるまでの時間が表示されます。なので、前のメッセージボックスをじっくり見ていた場合、その時間も加算されていくことになります。

「Quit」でストップウォッチを止めて、そのあと「ProcessingTime」で総経過時間を取得。

あわせて、ラップタイムコレクションを取得し、アクティブシートに出力しています。


ストップウォッチはいつでも使えるようにしておく便利です

時間を計りたいっていう場面は多くはないかもしれません。
(少なくともサンプルコードのようなただラップタイムを表示するだけという使い方はまずないですよね)

とはいえ、処理するデータ量や計算量が多くてちょっと時間が掛かりすぎるなー、っていうときがあると思います。そのとき、どこで時間が掛かっているのかを調べるために、こうしたストップウォッチ機能をいつでも使えるようにしておくと便利だと思います。


ストップウォッチを作るにあたってクラスを使いましたが、クラスって何?というときはこちらの本がオススメです。

そこが知りたい!Excel VBAプロの技 Excel97/2000/2002/2003対応!

そこが知りたい!Excel VBAプロの技 Excel97/2000/2002/2003対応!

エクセルVBAのクラスについて触れているサイトって数少なく、理解しようにも情報が不足しています。それだけでなく、書籍でもクラスに触れているものってあまりないんですよね。その点、この本はクラスを扱う数少ない本です。VBAを書くにあたって検索すれば大体のことが分かるこのご時世、わざわざ指南書を買うことは基本的にぼくはしていませんでしたが、この本は別でした。クラス以外でも内容が充実していて、ぼくが曖昧な理解でコードを書いていたことを反省させられました。2003年発売の本ですが、今でも十分通じます。