2022-01-16 VBA Wait、Sleep、DoEventsの違い

2
ちゅん🐤 @KotorinChunChun

VBAの待機命令 Application.Wait と Sleepの違いをまとめてみた。 WaitとSleepの比較記事で、WaitがESCやCtrl+Breakのキーで割り込みができることを解説しているのって見たことないですよね。 pic.twitter.com/kkkVMe4XMA

2022-01-15 23:40:09
拡大
かっしゃん_VBA練習中 @VBAminarai

@KotorinChunChun 待機と一時停止? 待機処理中だから処理の中止が出来て、一時停止は処理をしていないから中止が無い??

2022-01-15 23:46:49
ちゅん🐤 @KotorinChunChun

挙動からの予測ですが、Waitは無限ループする関数を実行しているような状態です。 VBAが全力全開で動いているんです。 だからCPU使用率が増大します。 Excelがフリーズしているように見えます。 その無限ループの中で、キー入力はキッチリ監視しているので、待機が強制終了できるようになってます。

2022-01-16 00:15:03
ちゅん🐤 @KotorinChunChun

SleepはOSに自身のプロセスを眠らせるように依頼します。 Excelが眠っているので、フリーズしているように見えるし、CPU使用率は増えません。 OSに眠らされているので、ユーザーがExcelに向かって何をしても、自主的に目覚めることはできません。 WaitとSleepは、真逆の仕組みによって待機してます。

2022-01-16 00:18:36
ちゅん🐤 @KotorinChunChun

以上の仕組みから、メリット・デメリットを把握して使い分けると良いでしょう。 ざっくり言うと Waitは初心者でも安全。Sleepはちょっと危険。Waitの問題を避けるために使うと良いです。

2022-01-16 00:45:35
ちゅん🐤 @KotorinChunChun

Waitは不安定なVBAを実行しているときは、自分の都合で自由に止められるという点で有利です。 しかし、緊急でデバッグモードに入りたいとき、いつも通りESCを押すと本来必要な待機時間がスルーされてしまいます。 ESCを押し続けても、何ステップも進んでからしかデバッグモードに入れません。

2022-01-16 00:45:35
ちゅん🐤 @KotorinChunChun

要するにWaitは、「Ctrl+Breakキーで止める」という知識があって、初めて安全に真価を発揮します。 大多数のケースでは止められさえすれば良いので、仮に誤ったパラメータを渡したとしても中断可能なWaitは、使いやすいです。

2022-01-16 00:45:35
ちゅん🐤 @KotorinChunChun

Waitにはミリ秒精度の待機が書きにくいという問題もあります。 約1秒の待機ならこう書けます。 Application.Wait Now() + TimeValue("00:00:01") でも0.1秒待機の場合 [Now()] + TimeValue("00:00:01") / 10 や [Now()] + 0.1 / 24 / 60 / 60 や [Now() + "00:00:00.1"] って書かないといけません。

2022-01-16 01:09:13
ちゅん🐤 @KotorinChunChun

ここで登場する「現在日時」を求める Now() が曲者です。 Now()はVBA標準ライブラリの VBA.DateTime.Now() です。 [Now()]はExcel関数のNOW関数です。 VBA関数は秒までしか精度がありませんが、Excel関数は10ミリ秒程度の精度があります。 これを分ってないと、正確に待機させられません。 pic.twitter.com/06faI8Er6d

2022-01-16 01:15:34
拡大
ちゅん🐤 @KotorinChunChun

書き方を間違えたら「過去の日時」を指定して、永遠に待機が終わらないコードを書いてしまうことが多々あります。 従って私は、IMEの変換辞書に、上記構文を登録してます。 ミスしてもESCキーで取り消しができるので、終わらないこと自体は大したデメリットとはならないと思います。

2022-01-16 01:21:16
ちゅん🐤 @KotorinChunChun

Sleepは、指定したミリ秒数は確実に眠っていて欲しい時に有効です。Waitのようにユーザーの操作で待機がスルーされる心配がありません。 パソコンに負荷をかけないので、VBAを動かしたまま他のアプリケーションを操作したいときや、他のアプリと連携するVBAではWaitより高い安定性を期待できます。

2022-01-16 01:24:12
ちゅん🐤 @KotorinChunChun

構文が簡潔というのも良いです。 使う時は  Sleep 待機させたいミリ秒数 これだけです。 しかし、ミリ秒というのは(私にとって)直感的ではないので、結構な頻度で「秒数」を書いてしまって、全く待機してくれないというミスをやらかします。 即興で書く時は要注意ですね。

2022-01-16 01:27:16
ちゅん🐤 @KotorinChunChun

ESCで取り消しできないというのは、誤って大きな数値を指定したとき、Excelがフリーズするというリスクを抱えています。 例えば、10秒待機のときに100秒指定したら、100秒待たない事にはVBAを中断できません。 ひょんな事から1000倍してしまったら、Excelごと強制終了待ったなしです。

2022-01-16 01:30:02
ちゅん🐤 @KotorinChunChun

Sleepにはもう一つ問題があります。 コーディング中にいざSleepを使おうとしたとき、必ずDecrare文を書かないといけません。 Wait文以上に難解で、こちらの暗記は、ほぼ不可能です。 こちらも辞書登録で対策はできますが、それでも面倒です。Wait以上に。 それを承知でSleepを使うわけです。

2022-01-16 01:34:05
ちゅん🐤 @KotorinChunChun

というわけで、WaitとSleepの解説は以上です。 全く違う性質のものなので、どっちが上位ってことはありません。好きな方を使ってください。 せっかくなので、明日にでもブログの記事化しておきます。

2022-01-16 01:41:01
ちゅん🐤 @KotorinChunChun

Waitの検証コードを書いてみました。 1秒待機を100回繰り返すループです。 Wait中にESCキーを押したら、待機状態は瞬時にキャンセルされ、処理が先に進みます。 さらに、ESCを離したとしても、以降で実行されるWaitの待機時間は0になります。 これは、100万回のループにしても同じです。 pic.twitter.com/hCopVW2YzR

2022-01-16 12:29:00
ちゅん🐤 @KotorinChunChun

「ESCを押したらWaitの待ち時間が0になる問題」を解決するために、ループ内にDoEventsを仕込みます。 ご覧の通り、すぐに離した場合は次のWaitが働くようになりました。 ESCキーを押し続けている間のみ、Waitがスルーされるようになります。 ところが、これはこれで問題があるんです...... pic.twitter.com/26qmKL9uXr

2022-01-16 12:51:22
ちゅん🐤 @KotorinChunChun

DoEventsを入れていないWaitでは、「とりあえずESCキーを押し続ける戦法」で、かなり処理が流れた後になるものの「中断できる」んです。 でもDoEventsを入れた途端に「ESCが効きにくく」なります。 要するに知名度の低い「Ctrl+Pause/Break」キーの知識が必須になるんです。 excel-chunchun.com/entry/2019/01/…

2022-01-16 12:58:59
ちゅん🐤 @KotorinChunChun

視覚的に体感していただけるように、グラフィックも入れてみました。 WaitでDoEvents無しで、 1.ESCを押し続けた場合→中断 2.ESCを押してすぐ離した場合→延々に待機0で暴走 こういう状態になります。 pic.twitter.com/sTZTzzZ7Jq

2022-01-16 13:13:50
ちゅん🐤 @KotorinChunChun

今度は WaitでDoEvents有りの場合。 1.ESCを離したら待機時間が回復してます。 2.ESCを押し続けても一向に中断されません。 それと、全体としての処理速度が急激に落ちているのが分ると思います。 pic.twitter.com/XkhtGGJNAV

2022-01-16 13:19:50
踊るエクセル@VBEアドイン作ってVBEハック中・・・ @ExcelVBAer

@KotorinChunChun 違いといえば、 Application.Wait はエクセル固有で、 ワード,パワポ,アクセスでは 使えないっぽいね~🐣

2022-01-16 14:38:29
風柳 @furyutei

SleepでEscが効かない問題は、小刻みにSleepを呼んで指定時間まで待つようなプロシージャを作っておけばいちおう解消できますね(画像のプロシージャではついでに待ち時間を秒単位にしてます) twitter.com/KotorinChunChu… pic.twitter.com/LgiHuFMSq1

2022-01-16 17:07:33
拡大
ちゅん🐤 @KotorinChunChun

@furyutei ですです。 (更に気軽に使えなくなるという問題はさておき)APIを直接使わなければ、大抵の問題は解決できますね

2022-01-16 17:15:50
ちゅん🐤 @KotorinChunChun

ExcelVBAのWaitとSleepの違い。 身も蓋もない言い方をすれば ・Waitはペットに「待て!」をして食い止めてる状態 ・Sleepはペットに麻酔注射して眠らせてる状態 twitter.com/KotorinChunChu…

2022-01-16 20:30:03
ほえほえ@スプシマン @hoehoe1234

>sleepはペットに麻酔注射して眠らせてる状態 ひどすw twitter.com/KotorinChunChu…

2022-01-16 21:20:46