【ExcelVBA入門】DoEventsを使って処理を途中で止める方法を徹底解説!

皆さんは、VBAでDoEnents関数を使って処理をキャンセルする方法を知っていますか?

キャンセルボタンなどを実装するときなど、処理の途中で止めたいケースはありますよね。そこで今回は、DoEvents関数の基礎的な使い方といった基礎的なことから、

  • サンプルコードを使った具体的な使い方
  • 処理速度を保ちつつDoEventsを実行する方法
  • 合わせて覚えると便利なユーザーフォームの作り方

といった応用的な方法まで、徹底的に解説します!

目次

DoEvents関数の使い方とは

DoEvents関数は、処理を途中で止めてOSに処理を渡すための関数です。たとえば、ループ処理中にキャンセルボタンを押す場合などに使います。以下のように書くことで、処理を途中で止めてOSに処理を渡すことができます。

Sub Test()

  'ループ処理
  Dim i As Integer
  For i = 0 to 10000

    DoEvents
    'メイン処理

  Next i

End Sub

この処理中にキャンセルボタンを押した場合はOSに処理が移る → キャンセルボタンのクリックが実行されるため、処理を途中で止めることができます。

サンプルコード

次に、具体的なサンプルコードをもとに、使い方を解説します。

画像:ユーザーフォームで作った画面

ユーザーフォームのコードサンプル:

Dim judgeStop As Boolean 'グローバル変数

'実行ボタンクリック時の処理
'
Private Sub CommandButton1_Click()

  judgeStop = False

  Dim i As Integer
  Dim j As Integer
  For i = 0 To 10000
    For j = 0 To 10000
      'キャンセルが来たら処理を途中で停止
      DoEvents

      ActiveSheet.Range("A1").Value = "i:" & i & vbCrLf & _
                                       "j:" & j

      'キャンセルボタンクリック時は処理を止める
      If judgeStop = True Then
        Exit Sub
      End If

    Next j
  Next i
End Sub

'キャンセルボタンクリック時の処理
'
Private Sub CommandButton2_Click()
  'キャンセルボタンクリック判定を更新
  judgeStop = True

  '画面を閉じる
  Unload UserForm1
End Sub

'ユーザーフォーム実行時の初期化処理
'
Private Sub UserForm_Initialize()
  ComboBox1.AddItem "ループ処理1"
  ComboBox1.AddItem "ループ処理2"
  ComboBox1.AddItem "ループ処理3"
  ComboBox1.AddItem "ループ処理4"

  ComboBox1.Value = "ループ処理1"
End Sub

画像:実行結果

CommandButton1_Clickで実行ボタンクリック時の処理、CommandButton2_Clickでキャンセルボタンクリック時の処理を書いています。

キャンセルボタンのクリック判定に使うために、キャンセルボタンクリック時にグローバル変数(judgeStop)をTrueに変更し、実行ボタンクリック時のループ処理でjudgeStopがTrueだったときのみ処理を停止しています。

このように、DoEvents関数 + Subをまたいで使えるグローバル変数を組み合わせると簡単にキャンセル処理を作ることができます。グローバル変数については以下で詳しく解説しているので、気になる方は見てみてくださいね!

DoEvents関数で処理が重たくなった時に試す方法

DoEvents関数は他の処理に影響が出ないか調べてからOSに処理を渡すため、処理によっては実行速度が落ちてしまうことがあります。そのため、GetInputState関数とあわせて使うのがおすすめです!GetInputState関数はイベントキューに待機中のイベントのみ調べることができます。

そのため、イベントが発生しているときだけOSに制御を渡すことができるようになり、処理時間を大幅に短縮することができます。

サンプルコード:

Private Declare Function GetInputState Lib "USER32" () As Long

Sub Test()
  Dim i As Integer
  Dim j As Integer

  'GetInputState関数でチェック
  If GetInputState() Then
    For i = 0 To 10000
      For j = 0 To 10000
        DoEvents

        'メインのループ処理

      Next j
    Next i
  End If
End Sub

処理速度が遅くなってしまった場合は、こちらも合わせて覚えておくと便利ですね。

補足:合わせて覚えると便利なユーザーフォームの作り方

補足ですが、今回のサンプルコードで紹介した画面は、ユーザーフォームを使って作ることができます。ユーザーフォームの使い方については以下で詳しく解説しているので、気になる方は見てみてくださいね!

まとめ

今回は、VBAでDoEventsを使って処理を途中で止める方法を解説しました。ループ処理中にキャンセルボタンで処理を止めるケースはよくあります。使い方も簡単なので、ぜひ使ってみてくださいね!

この記事を書いた人

北海道出身の30歳で、フリーランスエンジニア兼テックライターとして活動中。新卒入社したメーカー系のIT企業で、システムエンジニアとして約5年勤務。

Webアプリ、業務アプリ開発において、要件定義 ~ 運用保守まで様々な経験あり。また3歳の娘がいる1児のパパで、日々娘との時間を確保するために仕事を頑張っています!
侍エンジニアでは、【誰でもわかるレベルのわかりやすさ】を意識して、記事を執筆中。

目次