VBA技術解説
VBAでのタイマー処理(SetTimer,OnTime)

ExcelマクロVBAの問題点と解決策、VBAの技術的解説
最終更新日:2020-02-17

VBAでのタイマー処理(SetTimer,OnTime)


マクロ VBA Timer

VBAでタイマー処理(一定時間間隔で処理)を行う方法についての解説です。


最も一般的な方法は、Application.OnTimeを使う方法になりますが、
今回の主題としては、WindowsAPIのSetTimerを紹介します。

まずはApplication.OnTimeの確認してから、
次にWindowsAPIのSetTimerを紹介します。

以下のサンプルを実行するときは、他のExcelブックは閉じておいてください。
特にSetTimerの実行時は、Excel強制終了に巻き込まれないように注意してください。
そういう危険性もあるということを承知の上で実行してください。

Application.OnTime メソッド

基本的な使い方については以下を参照してください。
第120回.OnTimeメソッド
・OnTimeメソッドの構文 ・OnTimeメソッドの使用例 ・OnTimeメソッドの実践例

文字列としてのプロシージャー名を起動する方法(Run,OnTime)
文字列変数の中にプロシージャー名が入っていて、そのプロシージャーを起動したい場合になります、実際には、そのような構造が良いとは思えませんが、知っていればプログラミングの幅が広がります。使うのは、OnTimeメソッドorRunメソッドになります。

時刻になったら音を鳴らして知らせる(OnTime)
・作成するシート ・標準モジュールのVBAコード ・VBAコードの解説 ・ビープ音を変更したい場合 ・時刻になったら音を鳴らして知らせる最後に

では、サンプルになります。



Option Explicit

Public mOnTime As Date

Sub TimerProc()
 Range("A1") = Now()
End Sub

Sub OnTimeStart()
  Call TimerProc
  mOnTime = Now() + TimeSerial(0, 0, 1)
  Call Application.OnTime(mOnTime, "OnTimeStart")
End Sub

Sub OnTimeStop()
  '同一のProcedureとEarliestTimeがないとエラーになる
  On Error Resume Next
  Call Application.OnTime(mOnTime, "OnTimeStart", , False)
End Sub 

プロハージャー「OnTimeStart」を実行すると、
アクティブシートのA1セルに日時が1秒ごとに更新されて表示されます。
普通のデジタル時計です。
これが実行されている間も、他のExcel作業は普通に行えます。

ただし、注意深く良く見てください。
カーソルがチカチカしていないでしょうか。
僅かで一瞬ですがウエイトカーソルになっているのが確認できるはずです。
どうも嫌ですよね。(まあ、気分の問題ですけど…)

確認したら、プロシージャー「OnTimeStop」でタイマー処理を終了しておいてください。

WindowsAPI:SetTimer関数

まずはサンプルコードから

Option Explicit

Public Declare PtrSafe Function SetTimer Lib "USER32" _
                    (ByVal hwnd As Long, _
                    ByVal nIDEvent As Long, _
                    ByVal uElapse As Long, _
                    ByVal lpTimerFunc As LongPtr) As Long
Public Declare PtrSafe Function KillTimer Lib "USER32" _
                    (ByVal hwnd As Long, _
                    ByVal nIDEvent As Long) As Long

Public mTimerID As Long

Sub TimerProc()
  If mTimerID = 0 Then End '終了できない時の対策
  On Error Resume Next 'デバッグ出すとExcelが固まるので
  Range("A1") = Now()
End Sub

Sub TimerStart()
  If mTimerID <> 0 Then
    MsgBox "起動済です。"
    Exit Sub
  End If
  mTimerID = SetTimer(0&, 1&, 1000&, AddressOf TimerProc)
End Sub

Sub TimerStop()
  Call KillTimer(0&, mTimerID)
  mTimerID = 0
End Sub

引数の説明


hWnd タイマーに関連付けるウィンドウのハンドル
nIDEvent タイマーID(任意の値、0以外)
uElapse タイマーの間隔(ミリ秒単位1/1000秒)
lpTimerFunc タイマーのコールバック関数のポインタを指定

戻り値
戻り値は関数が成功すると新しいタイマIDが返され、失敗すると 0 が返ります。

注意点
タイマー起動したプロシージャーでデバッグが出てしまうような事があると、
エクセルが操作不能になったり、
Excelそのものを終了しても勝手にExcelが立ち上がってしまったり、
いろいろとめんどうな事が起こったりします。

上記掲載のコードでは、これらに対応して、
If mTimerID = 0 Then End '終了できない時の対策
On Error Resume Next 'デバッグ出すとExcelが固まるので
これらを一応入れていますが、テスト過程では決して過信しないでください。
最悪、Windowsを終了しても良いくらいのつもりで実行してもらえれば問題ありませんが、
少なくとも、Excelはタスクを終了しても良いつもりで実行してください。。
もちろん、ちゃんとVBAを書けばちゃんと動きます。

必ず、TimerStopKillTimerを起動して終了してください。
これで停止させずにExcelを閉じた場合、非表示状態のExcelがタスクに残る場合があります。
新たにエクセルを起動できなくなった等の現象になった場合は、タスクマネージャーを確認してください。

Application.OnTimeと違い、そもそもタイマー処理機能のAPI関数ですので、
1回起動すると、その後は指定間隔ごとにプロシージャーが起動されます。
このタイマーを止めるものが、KillTimer関数になります。

プロシージャー「TimerStart」を実行すると、
アクティブシートのA1セルに日時が1秒ごとに更新されて表示されます。
OnTimeと違って、カーソルがチカチカしないはずです。
動いていることを意識できないくらいスムーズに動作している事が確認できると思います。

最後に

今回は、タイマー処理をVBAに実装する場合のごく簡単な紹介でした。

さすがに、サンプルコードのようなセルに時刻を出力することは無いとは思いますが、、、
タイマー処理自体はプログラミングとしては普通の事ですので、知識としては覚えておくこと良いでしょう。

いつかタイマー処理が必要になった時に本記事を思い出してもらえれば良いと思います。




同じテーマ「マクロVBA技術解説」の記事

ドキュメントプロパティ(BuiltinDocumentProperties,CustomDocumentProperties)
VBAでファイルを既定のアプリで開く方法
Excelアドインの作成と登録について
VBAでのタイマー処理(SetTimer,OnTime)
マクロでShift_JIS文字コードか判定する
Byte配列と文字コード関数について
Applicationを省略できるApplicationのメソッド・プロパティ一覧
PowerQueryの強力な機能をVBAから利用する方法
ShapesとDrawingObjectsの相違点と使い方
新規挿入可能なシート名の判定
VBAにおける配列やコレクションの起点について


新着記事NEW ・・・新着記事一覧を見る

抜けている数値を探せ|エクセル雑感(2022-07-01)
.Net FrameworkのSystem.Collectionsを利用|VBA技術解説(2022-06-29)
迷路ネコが影分身の術を体得したら…|エクセル雑感(2022-06-27)
迷路にネコが挑戦したら、どうなるかな…|エクセル雑感(2022-06-26)
サロゲートペアに対応した自作関数(Len,Left,Mid,Right)|エクセル雑感(2022-06-24)
「マクロの登録」で登録できないプロシージャーは?|エクセル雑感(2022-06-23)
オブジェクトのByRef、ByVal、Variant|エクセル雑感(2022-06-22)
コメントから特定形式の年月を取り出す|エクセル雑感(2022-06-19)
4,9を使わない連番作成|エクセル雑感(2022-06-17)
連番を折り返して出力|エクセル雑感(2022-06-16)


アクセスランキング ・・・ ランキング一覧を見る

1.最終行の取得(End,Rows.Count)|VBA入門
2.RangeとCellsの使い方|VBA入門
3.変数宣言のDimとデータ型|VBA入門
4.繰り返し処理(For Next)|VBA入門
5.セルのコピー&値の貼り付け(PasteSpecial)|VBA入門
6.Excelショートカットキー一覧|Excelリファレンス
7.マクロって何?VBAって何?|VBA入門
8.並べ替え(Sort)|VBA入門
9.Range以外の指定方法(Cells,Rows,Columns)|VBA入門
10.エクセルVBAでのシート指定方法|VBA技術解説




このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。


記述には細心の注意をしたつもりですが、
間違いやご指摘がありましたら、「お問い合わせ」からお知らせいただけると幸いです。
掲載のVBAコードは動作を保証するものではなく、あくまでVBA学習のサンプルとして掲載しています。
掲載のVBAコードは自己責任でご使用ください。万一データ破損等の損害が発生しても責任は負いません。



このサイトがお役に立ちましたら「シェア」「Bookmark」をお願いいたします。
本文下部へ