教えて!ExcelVBA!

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

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

f:id:m_kbou:20210817150356p:plain

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

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関数を記述する事で処理の流れが通常とは異なります。予期せぬ動作が起こる可能性がありますので、多様する場合は注意して使用して下さい。