ExcelVBAで複数の処理を順番に実行するとき、「前の処理が完全に終わってから次の処理に移りたい」というニーズは非常に多くあります。特に、外部ファイルの読み込み・フォーム操作・シートの更新・印刷・Web連携など、処理時間がかかる命令では、処理が完了する前に次の命令に進んでしまうと、意図しない動作やエラーにつながることがあります。
✅ VBAで処理が並列に動かない理由
✅ 処理完了を待ってから次に進む基本的な考え方
✅ DoEventsによる「待ち」の実現方法
✅ 外部操作(ファイル・印刷・Web)の待機制御
✅ 実務で役立つサンプルコードと注意点
目次
- ✅ ExcelVBAは基本的に「上から順番に」処理される
- ・ ただし「非同期的な動作」が発生する例もある
- ✅ 処理が終わるまで「待って」から次に進めるには?
- ・処理を完全に同期させる方法(自然な順序)
- ・DoEventsでExcelやWindowsの処理を挟む方法
- ・条件が満たされるまでループして待機する方法
- ・Shellや外部プロセスの終了を待つ方法
- ■ よくある処理パターンと「前の処理を待つ」対応例
- ・ ファイル保存後に開く処理
- ・ 印刷処理のあとに次の命令を実行
- ・ IEやChromeでWebデータを取得後に処理続行
- ■ 待機処理でやってはいけないこと・注意点
- ・ 無限ループでCPUを占有
- ・ Application.Waitは応答不能になることも
- ■ 処理の終了を確認してから進めるロジックの設計が大切
- ■ まとめ|「前の処理が終わってから」はVBA自動化の要
- ・ 本記事のポイント
✅ ExcelVBAは基本的に「上から順番に」処理される
まず基本の話として、ExcelVBAはシングルスレッド(単一処理)で動作するため、基本的には「1行目→2行目→3行目…」と順番に処理されます。
Sub Sample()
MsgBox "処理1"
MsgBox "処理2"
End Sub
このように書けば、処理1が終わったあとに処理2が表示されます。
・ ただし「非同期的な動作」が発生する例もある
- 印刷命令(PrintOut)
- 外部ファイルの開閉や保存(Workbooks.Open, SaveAsなど)
- Shellによる外部アプリの起動
- モデルレスフォームの表示
- Webブラウザ制御(IE, Chrome)など
これらは「命令を送ってすぐ次の処理へ進む」ため、完了を待たずに次のコードが動いてしまうことがあります。
✅ 処理が終わるまで「待って」から次に進めるには?
・処理を完全に同期させる方法(自然な順序)
普通の処理(セルの書き込み、計算、ループなど)はVBAが順次実行するため、特別な待機処理は不要です。
Range("A1").Value = "完了"
MsgBox "次の処理へ"
この場合、A1に文字が入ってからメッセージが表示されます。
・DoEventsでExcelやWindowsの処理を挟む方法
VBAが処理中にOSやユーザー操作を受け付けられるようにする命令が DoEvents
です。
Range("A1").Calculate
DoEvents ' 計算や画面更新が完了するのを待つ
MsgBox "次の処理へ"
画面の再描画やシートの更新が反映されないときは、DoEventsを挟むだけで安定するケースがあります。
・条件が満たされるまでループして待機する方法
たとえば「A1セルの値が '完了' になるまで待つ」といった条件付きの待機もできます。
Do
DoEvents
Loop Until Range("A1").Value = "完了"
MsgBox "A1が完了になったので次の処理へ"
これは**「前の処理が完了したことを明示的に検知」して次に進む**構文です。
・Shellや外部プロセスの終了を待つ方法
外部アプリをVBAで起動して、その終了を待ってから次の処理を行いたい場合は、Shell関数とAPIを使います。
Declare PtrSafe Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Declare PtrSafe Function WaitForSingleObject Lib "kernel32" _
(ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Sub RunAndWait()
Dim pid As Long
pid = Shell("notepad.exe", vbNormalFocus)
Dim hProcess As Long
hProcess = OpenProcess(&H100000, False, pid)
Call WaitForSingleObject(hProcess, &HFFFFFFFF)
MsgBox "メモ帳が閉じられました"
End Sub
このようにして、外部アプリが閉じられるまでVBAの処理を待機させることができます。
■ よくある処理パターンと「前の処理を待つ」対応例
・ ファイル保存後に開く処理
ActiveWorkbook.SaveAs "C:\temp\sample.xlsx"
DoEvents ' 保存が完了するまで一時待機
Workbooks.Open "C:\temp\sample.xlsx"
【VBA】ダイアログで名前を付けて保存・同じフォルダに保存する方法
・ 印刷処理のあとに次の命令を実行
ActiveSheet.PrintOut
Application.Wait Now + TimeValue("00:00:02") ' 2秒だけ待機
MsgBox "印刷完了と想定して次へ"
・ IEやChromeでWebデータを取得後に処理続行
Do While ie.Busy Or ie.ReadyState <> 4
DoEvents
Loop
MsgBox "ページ読み込み完了"
このように、ReadyStateやBusyの状態を判定することが「完了検知」になります。
■ 待機処理でやってはいけないこと・注意点
・ 無限ループでCPUを占有
Do
Loop Until Range("A1").Value = "完了"
このように DoEventsを入れずにループを回すと、Excelが固まる危険があります。
・ Application.Waitは応答不能になることも
Application.Wait Now + TimeValue("00:01:00") ' 1分待機
この命令はイベント処理を中断するため、キャンセル操作や画面操作ができなくなります。
DoEventsを併用するなど工夫しましょう。
【VBA】処理が終わるまで待機させる【Sleep関数・Application.Waitメソッド】
■ 処理の終了を確認してから進めるロジックの設計が大切
VBAで「前の処理が終わってから」次の処理を実行したい場合には、単にコードを並べるだけでなく、以下のような視点を持つことが重要です。
視点 | 実装方法例 |
---|---|
明示的な完了確認 | セル値の変化・フラグ変数などを監視 |
外部プロセスの監視 | Shell+WaitForSingleObject |
UI描画の反映 | DoEvents / Application.ScreenUpdating = True |
ユーザー操作の待機 | 入力フォーム+条件チェック |
■ まとめ|「前の処理が終わってから」はVBA自動化の要
ExcelVBAにおける「前の処理が終わってから次へ進む」という制御は、データ整合性・ユーザー操作性・エラー防止の観点で非常に重要です。
・ 本記事のポイント
- VBAは基本的に順次処理だが、一部非同期命令には注意
DoEvents
は実質的な「一時待機」や「再描画許可」として便利- 条件付きループで処理完了を検知する構成が有効
- 外部プロセスの待機にはAPI(Shell+Wait)も活用可能
- Application.Wait や Sleep は完全停止するため扱いに注意