What Does VBA DoEvents Actually Do? — Understanding Why Screens Freeze and How Event Processing Works

VBA・Officeカテゴリを表すパンダのイラスト VBA / Office

About This Article
This article reviews the official Microsoft Learn documentation for the VBA DoEvents function and organizes the concepts down to Excel VBA event processing and reentrancy.

Validation Status: 📘 Official Specifications Confirmed / Excel Hardware Unverified
DoEvents does not turn long-running processes into true asynchronous operations.

When running a long loop in Excel VBA, the screen may appear to freeze. Calling DoEvents makes it easier to accept user operations because VBA temporarily yields control to the operating system, creating an opportunity to process pending events.

What is important here is not to view DoEvents as a “command that makes things asynchronous.”

What Happens Without DoEvents

sequenceDiagram
    participant U as User
    participant E as Excel UI
    participant V as VBA

    U->>E: Click / repaint等のイベント
    V->>V: 長いloopを継続
    Note over E,V: VBAが処理を占有
    E-->>U: 反応しにくく見える

While VBA continues a long-running process, if the UI has fewer opportunities to process events, redrawing and input responsiveness will be delayed.

Calling DoEvents Returns Control

Microsoft Learn explains that DoEvents is a function that yields execution so that the operating system can process other events.

sequenceDiagram
    participant V as VBA
    participant O as Excel / OS event processing
    participant U as User

    V->>V: loopを実行
    V->>O: DoEvents
    U->>O: input / repaint
    O->>O: queue中のeventを処理
    O-->>V: controlを戻す
    V->>V: loopの続きを実行

The main processing body does not move to a separate thread before and after DoEvents.

Minimal Example

Sub DemoDoEvents()

    Const MaxCount As Long = 5000000
    Dim i As Long

    On Error GoTo CleanUp

    For i = 1 To MaxCount
        If i Mod 10000 = 0 Then
            Application.StatusBar = _
                "Processing: " & Format(i / MaxCount, "0%")
            DoEvents
        End If
    Next i

CleanUp:
    Application.StatusBar = False

End Sub

Instead of calling DoEvents in every loop, control is returned to the UI at regular intervals.

Convenient, but with the Issue of Reentrancy

During DoEvents, another event procedure may be executed.

For example, if a long process is started from Button_Click and that same button is pressed again during DoEvents midway through, the exact same process could start overlapping.

flowchart TB
    A[Button_Click] --> B[長い処理]
    B --> C[DoEvents]
    C --> D{同じbuttonが再度押された?}
    D -->|No| E[元の処理へ戻る]
    D -->|Yes| F[同じevent procedureへ再入]
    F --> G[状態の競合・二重実行]

Microsoft Learn also warns to watch out for the same procedure being re-executed while control is yielded via DoEvents.

Simple Reentrancy Prevention

For small-scale countermeasures in existing macros, a running flag can be used.

Private mRunning As Boolean

Sub LongTask()

    Const MaxCount As Long = 5000000
    Dim i As Long

    If mRunning Then
        MsgBox "Already running."
        Exit Sub
    End If

    mRunning = True
    On Error GoTo CleanUp

    For i = 1 To MaxCount
        If i Mod 10000 = 0 Then
            Application.StatusBar = _
                "Processing: " & Format(i / MaxCount, "0%")
            DoEvents
        End If
    Next i

CleanUp:
    Application.StatusBar = False
    mRunning = False

End Sub

This is not thread-safe concurrency control. It is a simple state management approach to make it harder to double-start the same operation in Excel VBA.

Separating DoEvents from Asynchronous Processing

flowchart LR
    A[DoEvents] --> B[イベント処理へ一時的にcontrolを渡す]
    C[非同期I/O] --> D[待ち時間をcallback/event等で扱う]
    E[別process/thread] --> F[処理主体そのものを分ける]
    B -. 同じではない .- D
    B -. 同じではない .- F

For processes with long external I/O wait times, such as HTTP communication, designing around the asynchronous modes, events, or callbacks provided by the target API may be fundamentally more appropriate.

DoEvents is not “magic that converts synchronous processing into asynchronous processing.”

How Similar is the Relationship to the Windows Message Loop?

It is best to avoid equating the internal implementation of VBA/Excel with a typical Win32 GetMessage/DispatchMessage loop.

On the other hand, DoEvents serves as an interesting topic to learn how Windows GUIs operate while processing messages/events.

flowchart TB
    A[Windows GUIのevent/message] --> B[Excel application]
    B --> C[VBA event procedure]
    C --> D[長い同期処理]
    D --> E[DoEvents]
    E --> B

Rather than asserting that “the internal code of VBA DoEvents is literally this diagram,” treat it as a conceptual illustration to understand event-driven programming.

When to Use It

DoEvents tends to be useful when you want to achieve the following in small, existing macros:

  • Update progress such as on the StatusBar

  • Accept cancel operations

  • Avoid making the UI look completely unresponsive

On the other hand, for long or complex processes, processes with heavy state sharing, or processes centered around external I/O waits, consider alternative designs.

Summary

  • DoEvents temporarily yields control to the OS to process events

  • It is not asynchronous processing itself

  • There are scenarios where UI responsiveness can be improved

  • Watch out for reentrancy during DoEvents

  • Consider async APIs or alternative designs for long I/O waits

  • It can be used as an entry point for learning Windows event/message processing, but do not oversimplify its internal implementation

Official Information and Primary Sources

GitHub Sample

ライセンス:本記事のテキスト/コードは特記なき限り CC BY 4.0 です。引用の際は出典URL(本ページ)を明記してください。
利用ポリシー もご参照ください。

コメント

Copied title and URL