VBAテクニック集 VBA一覧 処理制御・待機・停止 文法・構文

「前の処理が終わってから」次へ進める方法|同期制御・DoEvents・待機の基本を徹底解説

ExcelVBAで複数の処理を順番に実行するとき、「前の処理が完全に終わってから次の処理に移りたい」というニーズは非常に多くあります。特に、外部ファイルの読み込み・フォーム操作・シートの更新・印刷・Web連携など、処理時間がかかる命令では、処理が完了する前に次の命令に進んでしまうと、意図しない動作やエラーにつながることがあります。

✅ VBAで処理が並列に動かない理由
✅ 処理完了を待ってから次に進む基本的な考え方
✅ DoEventsによる「待ち」の実現方法
✅ 外部操作(ファイル・印刷・Web)の待機制御
✅ 実務で役立つサンプルコードと注意点

✅ 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 は完全停止するため扱いに注意

-VBAテクニック集, VBA一覧, 処理制御・待機・停止, 文法・構文