教えて!ExcelVBA!

ExcelVBAの基礎知識・書き方について紹介します。

【ExcelVBA 関数】DoEvents関数を使用してVBA処理中にExcel操作を可能にする方法を教えて!

f:id:m_kbou:20210817150356p:plain

VBA処理を実行すると、処理が終了するまではExcel操作は不可となります。特に処理時間の長いVBA処理を実行し、途中で処理を中断したい場合が多々ありますが、この場合も処理が終了するでは待ち状態となります。しかし、DoEvents関数をコーディング中に記述する事で、一時的に制御をVBA処理からExcel側に移す事が可能です。この方法について紹介します。

 

 

構文

記述方法は以下の通りとなります。

DoEvents

[説明]:

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」をセットします。

f:id:m_kbou:20210817152922p:plain

※上記の記述例は、VBE(VBA記述画面)に記述しないと実行ができません。VBEの開き方についてはこちらを参考にして下さい。 

[実行例]:

①<実行>ボタンには上記プログラミング例の実行プロシージャ、<キャンセル>ボタンにはキャンセルプロシージャが登録されています。まずは<実行>ボタンをクリックします。(※ボタンの作り方やボタンにプログラムを割り当てるにはこちらを参考にして下さい。)

f:id:m_kbou:20210817150708p:plain

②実行プロシージャが実行されるので、実行中に<キャンセル>ボタンをクリックします。しかし、実行プロシージャが実行されている間はVBA側で制御を優先するため、<キャンセル>ボタンがクリックできません。よって、実行プロシージャが完了するまで待つしかない状況が続きます。(※<キャンセル>ボタンがクリックできないため、変数:中断に「True」をセットする事ができず、実行プロシージャの処理を中断させる事ができません。)

f:id:m_kbou:20210817150722p:plain

[サンプル]:

上記で説明したファイルをダウンロードできます。ご自由にお使い下さい。

drive.google.com

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」をセットします。

f:id:m_kbou:20210817154039p:plain

※上記の記述例は、VBE(VBA記述画面)に記述しないと実行ができません。VBEの開き方についてはこちらを参考にして下さい。 

[実行例]:

①<実行>ボタンには上記プログラミング例の実行プロシージャ、<キャンセル>ボタンにはキャンセルプロシージャが登録されています。まずは<実行>ボタンをクリックします。(※ボタンの作り方やボタンにプログラムを割り当てるにはこちらを参考にして下さい。)

f:id:m_kbou:20210817154054p:plain

②実行プロシージャが実行されるので、実行中に<キャンセル>ボタンをクリックします。

f:id:m_kbou:20210817154113p:plain

③実行プロシージャの処理が中断され、MsgBoxで「処理を中断しました。」が表示されます。(※今回は一時的にExcel側に制御を渡すようにDoEventsを記述したため、<キャンセル>ボタンがクリックできます。よって、変数:中断に「True」がセットされ、実行プロシージャの処理を中断させる事ができます。)

f:id:m_kbou:20210817154127p:plain

[サンプル]:

上記で説明したファイルをダウンロードできます。ご自由にお使い下さい。

drive.google.com

DoEvents関数を使用したループ処理についての説明は以上です。 

 

おわりに

今回はDoEvents関数を使用して発生イベントをOS制御に渡す方法について説明しました。DoEvents関数を記述する事で処理の流れが通常とは異なります。予期せぬ動作が起こる可能性がありますので、多様する場合は注意して使用して下さい。