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
- Calling DoEvents Returns Control
- Minimal Example
- Convenient, but with the Issue of Reentrancy
- Simple Reentrancy Prevention
- Separating DoEvents from Asynchronous Processing
- How Similar is the Relationship to the Windows Message Loop?
- When to Use It
- Summary
- Official Information and Primary Sources
- GitHub Sample
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


コメント