Application.WaitかTimerを使用して処理を一時停止するコードとそれに関する注意点
'5秒間一時停止
Application.Wait (DateAdd("s", 5, Now))
Dim 開始時間 As Double
Const 停止時間 As Double = 0.5
'待ち時間の開始時間の取得
開始時間 = Timer
'開始時間から停止時間数値を超えるまで無限ループ
Do Until Timer - 開始時間 >= 停止時間
DoEvents
Loop
処理を一時停止するには「Application.Wait」メソッドか「Timer」関数を応用するかのどちらかを使用します
それぞれに利点があるので、解説します
コード解説(Application.Wait使用)
こちらはこの処理を一時停止させることを目的としたメソッドです
引数が必須で1つ、指定するのは時刻データ(Time)です
時刻データの引数になるので、日付データは含まれないため日をまたぐ場合は別途処理が必要になりますが、一時停止という観点からそれはほぼないと思います
そして、引数の時間に達したときにこの関数は「True」を返すとともに処理を開始します
つまり、どれだけ停止させるというよりは、いつ再開させるという考え方です
目的のメソッドであるため、1行で実装できる点が便利です
ただ、この停止時間中はExcelの操作は一切行えない状態になります
バックグラウンド処理は実行されるようですが、Excelはフリーズしたような印象を受ける形になります
その認識の無い人が遭遇した場合、タスクキルしてしまうかもしれません
その辺の注意点さえ気にしていれば、停止処理はこれで十分です
コード解説(Timer関数使用)
Timer関数を使用する場合は、もともと目的の関数ではないので少し煩雑になります
「Dim 開始時間 As Double」
「Const 停止時間 As Double = 0.5」
1行目は開始時間を代入する変数です
2行目は定数を使用して停止時間を指定する箇所で、秒数を指定します
ここでは「0.5」秒が指定されます
「開始時間 = Timer」
停止時間の開始時間を取得しています
「Do Until Timer – 開始時間 >= 停止時間」
「DoEvents」
「Loop」
ループ処理で待機させます
1行目での終了条件が差し引き時間秒数が停止時間秒数を超えているかです
2行目は後述します
3行目でループされます
このループは差し引き時間まで無限にループさせる処理です
実際のループ回数は計り知れませんが、その際に2行目のコードを入れることで「Application.Wait」よりも柔軟な使用が可能になります
と、いうのもApplication.Waitの解説にあるように停止中はExcel自体が停止するためフリーズした状態になります
これを回避するのが「DoEvents」関数です
この関数はVBAがOSに処理を一時的に渡す関数です
この関数を使用することにより、Excelの操作が可能になるのでフリーズしたような動作をすることが無くなります
また、もう一つ重要な点として「描画処理」も行われる点にも優位性があります
例えば停止処理を入れつつループ処理を実行する場合に重要です
デジタル時計を表示させる場合は、停止時間を「1」にして1秒ごとに時刻データを送信し続けます
そうすると、ある時点から描画処理が行われなくなり画面がフリーズしたような状態になり、処理終了後に描画処理が行われて最終結果が表示されます
OSに処理を渡すことで、OSは描画処理も実行しますのでここが重要になる場合もあります
それぞれの使い分けとSleep関数について
上記のように利点が異なります
使い分けとしては
・簡便なコーディング、開始時刻の指定、停止中にExcelの操作を許可しない場合はApplication.Waitを使用
・1秒未満の停止時間の指定、Excelの操作を可能、描画処理を行う場合はTimer関数を使用
処理を停止する場面はいろいろあると思いますが、停止前と開始後でセルのデータやアクティブブックが入れ替わっていて処理がおかしくなるようなら操作の許可は出来ないわけです
ただ、これに関してはTimer関数のコードからDoEvents関数を削除すれば同じようになります
Application.Waitは停止時間ではなく開始時刻を指定するので、特定の時刻に処理を開始したい場合には優位
Timer関数側ではミリ秒単位の停止時間の指定が可能なので、そこが優位ですね
ただこの2つのコードには大きな問題があります
CPUの消費量が高いことです
Application.Waitメソッドの内部的な動きは分かりませんが、Timer関数では大量にDoループが走っています
タスクマネージャーで確認しましたが、どちらも同じ消費量だったのでこれに関しての優位性はありませんでした
特にDoEvents関数で他の処理も行った場合の影響は大きそうですので、そのあたりは少し頭に入れておいてください
そして、そこでこの問題を解決してくれるのが「Sleep」関数です
これはWinAPI関数の1つです
WinAPIなので、指定の必須の関数宣言を必要としさらにbit環境にも対応しておかないといけないので初心者には少し荷が重いかもしれません
ただ、この関数はその名の通り休ませる関数なのでCPUの消費量は上がりません
WinAPIの理解とCPU占有による弊害が見逃せない状況になったら一度使用を検討してみましょう
そうでなければ、VBA標準コードのみで実装できる記事コードで十分です