VBA処理を実行すると処理が終了するまではExcel操作は不可となります。特に処理時間の長いVBA処理を実行し、途中で処理を中断したい場合が多々ありますが、この場合も処理が終了するでは待ち状態となります。しかし、DoEvents関数をコーディング中に記述する事で、一時的に制御をVBA処理からExcel側に移す事が可能です。この方法について紹介します。
構文
記述方法は以下の通りとなります。
DoEvents
[説明]:
VBAの処理を一時的に中断させてExcelに制御を渡します。
通常のVBA処理中ではExcelの操作はできませんが、この関数を使用する事でVBA処理中でもExcel操作を行う事が可能となります。DoEvents関数によりExcel側に制御が渡された後は、Excel側の待ちイベントが実施され、全てのイベントが完了次第VBA処理が継続されます。具体的な用途としては、「ループ処理中に処理を止めたい」や「プログレスバーの表示」等があります。内容を纏めると、「VBA処理中にExcel側に制御を渡し、Excel側で待ち状態にあるイベントを実施後、再度VBA処理を継続して下さい。」との意味になります。
使い方
使い方について具体的に説明します。
ループ処理の停止(DoEvents関数を使用しない)
DoEvents関数を使用しないループ処理について説明します。
[プログラミング例]:
'↓処理①
Public 中断 As Boolean
'*-----------------*
'* 実行
'*-----------------*
Sub 実行()
Dim i As Long
'↓処理②
中断 = False
'↓処理③
For i = 1 To 30
'↓処理④
Application.Wait Now + TimeValue("0:00:01")
'↓処理⑤
If (中断 = True) Then
MsgBox "処理を中断しました。"
Exit For
End If
Next
End Sub
'*-----------------*
'* キャンセル
'*-----------------*
Sub キャンセル()
'↓処理⑥
中断 = True
End Sub
今回は「実行プロシージャ」と「キャンセルプロシージャ」の2つを作成します。
・実行プロシージャ
[処理①]
Publicによる変数:中断を定義します。
※変数をPublicで定義すると複数のプロシージャで共通に使用可能です。
[処理②]
変数:中断に「False」をセットします。
[処理③]
For~Next文にてループ処理を実行します。
※今回はサンプルとして30回のループ処理としました。
[処理④]
待ち時間を設けます。
※今回はサンプルとして1秒/ループの待ち時間としました。
待ち時間の設定についてはこちらを参考にして下さい。
[処理⑤]
変数:中断が「True」の場合は処理を中断し、For~Next文を抜けます。
中断した際は、MsgBoxにて"処理を中断しました。"を表示します。
※変数:中断への「True」セットは、キャンセルプロシージャで実施します。
・キャンセルプロシージャ
[処理⑥]
変数:中断に「True」をセットします。
※上記の記述例は、VBE(VBA記述画面)に記述しないと実行ができません。VBEの開き方についてはこちらを参考にして下さい。
[実行例]:
①<実行>ボタンには上記プログラミング例の実行プロシージャ、<キャンセル>ボタンにはキャンセルプロシージャが登録されています。<実行>ボタンをクリックします。
②実行プロシージャが実行されるので、実行中に<キャンセル>ボタンをクリックします。しかし、実行プロシージャが実行されている間はVBA側で制御を優先するため、<キャンセル>ボタンがクリックできません。よって、実行プロシージャが完了するまで待つしかない状況が続きます。(※<キャンセル>ボタンがクリックできないため、変数:中断に「True」をセットする事ができず、実行プロシージャの処理を中断させる事ができません。)
[サンプル]:
上記で説明したファイルをダウンロードできます。ご自由にお使い下さい。
DoEvents関数を使用しないループ処理についての説明は以上です。
ループ処理の停止(DoEvents関数を使用)
DoEvents関数を使用したループ処理について説明します。
[プログラミング例]:
'↓処理①
Public 中断 As Boolean
'*-----------------*
'* 実行
'*-----------------*
Sub 実行()
Dim i As Long
'↓処理②
中断 = False
'↓処理③
For i = 1 To 30
'↓処理④
Application.Wait Now + TimeValue("0:00:01")
'↓処理⑤
DoEvents
'↓処理⑥
If (中断 = True) Then
MsgBox "処理を中断しました。"
Exit For
End If
Next
End Sub
'*-----------------*
'* キャンセル
'*-----------------*
Sub キャンセル()
'↓処理⑦
中断 = True
End Sub
今回は「実行プロシージャ」と「キャンセルプロシージャ」の2つを作成します。
・実行プロシージャ
[処理①]
Publicによる変数:中断を定義します。
※変数をPublicで定義すると複数のプロシージャで共通に使用可能です。
[処理②]
変数:中断に「False」をセットします。
[処理③]
For~Next文にてループ処理を実行します。
※今回はサンプルとして30回のループ処理としました。
[処理④]
待ち時間を設けます。
※今回はサンプルとして1秒/ループの待ち時間としました。
待ち時間の設定についてはこちらを参考にして下さい。
[処理⑤]
DoEventsを記述する事で一時的に制御をExcel側に渡します。
[処理⑥]
変数:中断が「True」の場合は処理を中断し、For~Next文を抜けます。
中断した際は、MsgBoxにて"処理を中断しました。"を表示します。
※変数:中断への「True」セットは、キャンセルプロシージャで実施します。
・キャンセルプロシージャ
[処理⑦]
変数:中断に「True」をセットします。
※上記の記述例は、VBE(VBA記述画面)に記述しないと実行ができません。VBEの開き方についてはこちらを参考にして下さい。
[実行例]:
①<実行>ボタンには上記プログラミング例の実行プロシージャ、<キャンセル>ボタンにはキャンセルプロシージャが登録されています。<実行>ボタンをクリックします。
②実行プロシージャが実行されるので、実行中に<キャンセル>ボタンをクリックします。
③実行プロシージャの処理が中断され、MsgBoxで「処理を中断しました。」が表示されます。(※今回は一時的にExcel側に制御を渡すようにDoEventsを記述したため、<キャンセル>ボタンがクリックできます。よって、変数:中断に「True」がセットされ、実行プロシージャの処理を中断させる事ができます。)
[サンプル]:
上記で説明したファイルをダウンロードできます。ご自由にお使い下さい。
DoEvents関数を使用したループ処理についての説明は以上です。
おわりに
今回はDoEvents関数を使用して発生イベントをOS制御に渡す方法について説明しました。DoEvents関数を記述する事で処理の流れが通常とは異なります。予期せぬ動作が起こる可能性がありますので、多様する場合は注意して使用して下さい。