この記事でわかること
- Do While…Loop で「条件がTrueの間」ループを回す方法
- Do Until…Loop で「条件がTrueになるまで」ループを回す方法
- 前判定(Do While/Until…Loop)と後判定(Do…Loop While/Until)の違い
- For Next との使い分けの基準
- 無限ループの回避方法
対象: Excel 2016以降 / Microsoft 365、Windows 10/11
—
どんな場面で使う?
- データの最終行まで1行ずつ処理を繰り返したい(行数が事前にわからないとき)
- Dir関数でフォルダ内のファイルを1つずつ処理するループを書きたい
- 条件を満たすまで(またはFalseになるまで)処理を繰り返したい
- For Nextでは書きにくい「条件付きループ」の書き方を知りたい—
完成イメージ(Before / After)
Before(For Nextで無理やり対処):
| 問題 | 状況 |
|---|---|
| 最終行を毎回取得する必要がある | End(xlUp).Row を書き忘れると処理が抜ける |
| 途中の空行に対応できない | データの途中に空行があると最終行がずれる |
| 回数が決まらない処理に不向き | Dir関数でファイルを順番に処理できない |
After(Do While / Do Untilで条件ループ):
| 改善 | 状況 |
|---|---|
| 空セルで自動停止 | 最終行の取得が不要 |
| 条件で柔軟に制御 | 「値が100を超えたら停止」も簡単 |
| Dir関数と組み合わせ可能 | ファイル数を事前に数えなくてOK |
—
自分もFor Nextだけでループを書いていた時期がある。「セルが空になるまで繰り返す」を実現するために毎回 End(xlUp).Row で最終行を取得していたが、途中に空行があるデータでは最終行がずれて処理が抜けることがあった。地味に面倒だった。Do Whileを覚えてからは「空セルに当たったら止める」が1行で書けるようになり、最終行の取得で悩むことが減った。この記事で、同じように条件付きループに苦労している人がサクッと使えるようになればうれしい。
結論: 回数が決まっていないループには Do While / Do Until を使う。For Next との使い分けを覚えれば、VBAのループ処理の幅が一気に広がる。
なお、最終行の取得方法を復習したい場合は データの最終行・最終列を正確に取得する方法 を参照。
—
Do While と For Next の違い(比較表)
| 項目 | For Next | Do While / Do Until |
|---|---|---|
| ループ回数 | 事前に決まっている | 条件次第(事前に不明でもOK) |
| 典型的な用途 | 「1行目〜最終行まで」 | 「空セルになるまで」「ファイルがなくなるまで」 |
| カウンタ変数 | 自動でインクリメント | 手動でインクリメント(忘れると無限ループ) |
| 途中で抜ける | Exit For | Exit Do |
| 使用頻度 | 高い | 中〜高(実務で頻出) |
判断基準: 「何回ループするか事前に分かる?」→ Yes なら For Next、No なら Do While。
—
実行前の準備
バックアップを取る
実務データで実行する場合は、必ずファイルのコピーを別フォルダに保存してから実行する。
Excelをマクロ有効ブック(.xlsm)で保存する
拡張子が .xlsx のままだとマクロが保存できない。
- 「ファイル」→「名前を付けて保存」
- ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
- 保存
テスト用データを準備する
A列にテスト用のデータを入力する(A1〜A5に適当な値を入れ、A6は空欄にする)。
| A列 |
|---|
| りんご |
| みかん |
| バナナ |
| ぶどう |
| メロン |
| (空欄) |
—
手順(コピペ → 実行まで約5分)
VBE(コードを書く画面)を開く
- Excelで
Alt + F11を押す
標準モジュールを挿入する
- VBEのメニュー →「挿入」→「標準モジュール」
コードを貼り付けて実行する
- コードウィンドウに、下のコードをそのままコピペする
Alt + F8→ マクロ名を選んで「実行」- 結果はVBEの「イミディエイトウィンドウ」(
Ctrl + G)で確認できる
ボタンに割り当てれば毎回Alt+F8を押さなくて済む。方法は マクロをボタン1つで実行する方法 を参照。
—
コード(基本版)– Do While…Loopでセルが空になるまで繰り返す
A列のデータを上から順に処理し、空セルに到達したら自動でループ終了する。
'============================================================
' ■ Do While...Loop(基本版)
' → A列のセルが空になるまで繰り返す
'============================================================
Sub DoWhileBasic()
Dim i As Long
i = 1 '← 開始行
'--- セルが空でない間ループ
Do While Cells(i, 1).Value <> ""
'--- ここに処理を書く(例: イミディエイトウィンドウに出力)
Debug.Print "行" & i & ": " & Cells(i, 1).Value
i = i + 1 '← ★これを忘れると無限ループ!
Loop
MsgBox i - 1 & " 行のデータを処理しました。", vbInformation
End Sub
書き換えポイント
| 変数 | 説明 | 初期値 |
|---|---|---|
i |
開始行番号 | 1(1行目から) |
Cells(i, 1) |
処理対象の列 | 1(A列) |
ポイント: i = i + 1 をLoop直前に必ず書く。これを忘れると無限ループになる。
—
コード(応用版)– Do Until / Loop While / Loop Until の4パターン
Do While / Do Until には4つの書き方がある。前判定と後判定の違いを理解しておくと、場面に応じて使い分けられる。
4パターンの比較表
| パターン | 構文 | 判定タイミング | 最低実行回数 | 使いどころ |
|---|---|---|---|---|
| 1 | Do While 条件…Loop | 前判定 | 0回 | 最もよく使う。迷ったらこれ |
| 2 | Do Until 条件…Loop | 前判定 | 0回 | 「〜になるまで」と読みたいとき |
| 3 | Do…Loop While 条件 | 後判定 | 1回 | 必ず1回は処理したいとき |
| 4 | Do…Loop Until 条件 | 後判定 | 1回 | 必ず1回は処理したいとき |
判断基準: 迷ったらパターン1(Do While…Loop)を使う。後判定(パターン3・4)はデータが空でも1回実行されるため、空チェックが不要な場面だけ使う。
パターン1: Do While…Loop(前判定・Trueの間)
'============================================================
' ■ Do While...Loop(前判定)
' → 条件がTrueの間ループ(最もよく使う)
'============================================================
Sub PatternDoWhile()
Dim i As Long
i = 1
'--- 「セルが空でない間」ループ(空なら最初から実行しない)
Do While Cells(i, 1).Value <> ""
Debug.Print "While前判定 行" & i & ": " & Cells(i, 1).Value
i = i + 1
Loop
Debug.Print "--- 処理終了(" & i - 1 & "行)---"
End Sub
パターン2: Do Until…Loop(前判定・Trueになるまで)
'============================================================
' ■ Do Until...Loop(前判定)
' → 条件がTrueになるまでループ
'============================================================
Sub PatternDoUntil()
Dim i As Long
i = 1
'--- 「セルが空になるまで」ループ(空なら最初から実行しない)
Do Until Cells(i, 1).Value = ""
Debug.Print "Until前判定 行" & i & ": " & Cells(i, 1).Value
i = i + 1
Loop
Debug.Print "--- 処理終了(" & i - 1 & "行)---"
End Sub
パターン3: Do…Loop While(後判定・Trueの間)
'============================================================
' ■ Do...Loop While(後判定)
' → 必ず1回は実行してから条件を評価
'============================================================
Sub PatternLoopWhile()
Dim i As Long
i = 1
'--- 必ず1回は実行し、「セルが空でない間」続ける
Do
Debug.Print "While後判定 行" & i & ": " & Cells(i, 1).Value
i = i + 1
Loop While Cells(i, 1).Value <> ""
Debug.Print "--- 処理終了(" & i - 1 & "行)---"
End Sub
パターン4: Do…Loop Until(後判定・Trueになるまで)
'============================================================
' ■ Do...Loop Until(後判定)
' → 必ず1回は実行してから条件を評価
'============================================================
Sub PatternLoopUntil()
Dim i As Long
i = 1
'--- 必ず1回は実行し、「セルが空になるまで」続ける
Do
Debug.Print "Until後判定 行" & i & ": " & Cells(i, 1).Value
i = i + 1
Loop Until Cells(i, 1).Value = ""
Debug.Print "--- 処理終了(" & i - 1 & "行)---"
End Sub
—
コード(実務版)– 空行スキップ+Dir関数との組み合わせ
実務ではデータの途中に空行がある場合や、フォルダ内のファイルを順番に処理する場面が多い。Do Whileを使えばどちらもシンプルに書ける。
Dir関数と組み合わせてフォルダ内のファイルをDo Whileで回すようにしてからは、ファイル数を事前に数える手間がなくなった。For Nextで回していたときよりコードもスッキリした。
実務版1: 途中の空行をスキップしながら処理
'============================================================
' ■ 空行をスキップしながらA列を処理(実務版1)
' → 途中に空行があっても最終行まで処理する
' → 最終行はEnd(xlUp)で取得し、Do Whileで条件判定
'============================================================
Sub DoWhileSkipBlanks()
'--- ★書き換えポイント ---
Dim targetCol As Long
targetCol = 1 '← 処理対象の列(A列=1)
Dim startRow As Long
startRow = 1 '← 開始行
'--- ★ここまで ---
'--- 最終行を取得(空行があってもOK)
Dim lastRow As Long
lastRow = Cells(Rows.Count, targetCol).End(xlUp).Row
If lastRow < startRow Then
MsgBox "データがありません。", vbExclamation
Exit Sub
End If
'--- 最終行までループ(空行はスキップ)
Dim i As Long
Dim processCount As Long
i = startRow
processCount = 0
Do While i <= lastRow
'--- 空行ならスキップ
If Cells(i, targetCol).Value <> "" Then
Debug.Print "行" & i & ": " & Cells(i, targetCol).Value
processCount = processCount + 1
End If
i = i + 1
Loop
MsgBox processCount & " 行のデータを処理しました(空行はスキップ)。", vbInformation
End Sub
実務版2: Dir関数と組み合わせてフォルダ内のファイルを処理
'============================================================
' ■ Dir関数でフォルダ内のExcelファイルを順番に処理(実務版2)
' → Do While でファイル名が空になるまでループ
' → ファイル数を事前に数える必要なし
'============================================================
Sub DoWhileWithDir()
'--- ★書き換えポイント(自分の環境に合わせて変更)---
Dim folderPath As String
folderPath = "C:\SampleData\" '← 対象フォルダ(末尾に\)
Dim filePattern As String
filePattern = "*.xlsx" '← 対象ファイルの拡張子
'--- ★ここまで ---
'--- フォルダの存在確認
If Dir(folderPath, vbDirectory) = "" Then
MsgBox "フォルダが見つかりません: " & folderPath, vbExclamation
Exit Sub
End If
'--- 最初のファイル名を取得
Dim fileName As String
fileName = Dir(folderPath & filePattern)
'--- ファイル名が空になるまでループ
Dim fileCount As Long
fileCount = 0
Do While fileName <> ""
fileCount = fileCount + 1
Debug.Print fileCount & ": " & fileName
'--- ★ここにファイルごとの処理を書く ---
' 例: Workbooks.Open folderPath & fileName
' (処理)
' ActiveWorkbook.Close SaveChanges:=False
'--- 次のファイル名を取得(★これを忘れると無限ループ!)
fileName = Dir()
Loop
MsgBox fileCount & " 個のファイルを処理しました。", vbInformation
End Sub
書き換えポイント
| 変数 | 説明 | 初期値 |
|---|---|---|
targetCol(実務版1) |
処理対象の列 | 1(A列) |
startRow(実務版1) |
開始行 | 1 |
folderPath(実務版2) |
対象フォルダのパス(末尾に\) |
"C:\SampleData\" |
filePattern(実務版2) |
対象ファイルの拡張子 | "*.xlsx" |
大量のデータを処理する場合は、配列に読み込んでからループすると高速になる。方法は 配列を使ってVBAを高速化する方法 を参照。
処理に時間がかかる場合は VBAの処理速度を高速化する方法 の ScreenUpdating / Calculation の設定も組み合わせると効果的。
—
よくある落とし穴5選
1. カウンタ変数のインクリメント忘れ → 無限ループ
自分もこれで正直焦った。Do Whileの中で i = i + 1 を書き忘れて無限ループになり、Excelが固まった。Ctrl+Breakで止められることを知らず、タスクマネージャーで強制終了するしかなかった。
| 項目 | 内容 |
|---|---|
| 症状 | マクロが終わらない。Excelが応答なしになる |
| 原因 | i = i + 1(カウンタのインクリメント)をLoop直前に書き忘れた |
| 対策 | Do Whileの中では必ずカウンタをインクリメントする。安全策として上限ガードを入れる |
'--- 無限ループ防止の上限ガード
Dim safetyCount As Long
safetyCount = 0
Do While Cells(i, 1).Value <> ""
'--- 処理
i = i + 1
'--- ★安全弁: 10万回を超えたら強制終了
safetyCount = safetyCount + 1
If safetyCount > 100000 Then
MsgBox "ループ回数が上限を超えました。処理を中断します。", vbExclamation
Exit Do
End If
Loop
2. Do While と Do Until の条件を逆に書く
| 項目 | 内容 |
|---|---|
| 症状 | ループが1回も実行されない、または無限ループになる |
| 原因 | Do While は「Trueの間」、Do Until は「Trueになるまで」。条件の論理が逆 |
| 対策 | 迷ったら Do While を使い、「〜の間回す」と日本語で読む |
'--- NG: Do While で「空になるまで」のつもりで空判定を書いてしまう
Do While Cells(i, 1).Value = "" '← これだと空の間ループ(意図と逆)
'...
Loop
'--- OK: 「空でない間」ループ
Do While Cells(i, 1).Value <> ""
'...
Loop
3. 後判定(Do…Loop While/Until)で空データでも1回実行される
| 項目 | 内容 |
|---|---|
| 症状 | データがないのに処理が1回実行され、空セルに対して処理が走る |
| 原因 | 後判定は必ず1回はループ本体を実行してから条件を評価する |
| 対策 | データが空の可能性がある場合は前判定(Do While/Until…Loop)を使う |
4. Dir関数のDo Whileで fileName = Dir() を書き忘れ → 無限ループ
| 項目 | 内容 |
|---|---|
| 症状 | 同じファイルが延々と処理される |
| 原因 | ループ内で fileName = Dir() を呼ばないと、fileName の値が更新されない |
| 対策 | ループ末尾に fileName = Dir() を必ず書く |
5. While…Wend を使っていて Exit(途中抜け)ができない
| 項目 | 内容 |
|---|---|
| 症状 | 途中でループを抜けたいが方法がない |
| 原因 | While…Wend は古い構文で Exit Wend が存在しない |
| 対策 | Do While…Loop に書き換える。Exit Do で途中抜けできる |
—
VBAのDo Whileが無限ループになるときの対処法
「Do Whileループが止まらなくなった」という場合、原因はループ内でカウンタ変数のインクリメントや条件変更を書き忘れていることだ。Do While内で必ず条件がFalseに変わる処理(i = i + 1 や fileName = Dir() など)を入れること。Ctrl+Breakで強制停止できる。
VBAのDo WhileとDo Untilの条件が逆になるときの対処法
「Do Whileで書いたらループが1回も回らない」という場合、原因はWhileとUntilの条件が逆になっていることだ。Do While は条件がTrueの間ループし、Do Until は条件がTrueになるまでループする。Do While x <> "" と Do Until x = "" は同じ意味。
FAQ
Q1: Do While と For Next はどう使い分ける?
回数が決まっていれば For Next、条件で止めたければ Do While。
| 場面 | 推奨 |
|---|---|
| 1行目〜最終行まで順に処理 | For Next |
| セルが空になるまで処理 | Do While |
| フォルダ内のファイルを全部処理(Dir関数) | Do While |
| 配列の要素を順に処理 | For Next(For Each) |
| ユーザーが「終了」を選ぶまで繰り返す | Do While / Do Until |
Q2: 無限ループになったときの止め方は?
Ctrl+Break(またはCtrl+Pause)でマクロを中断できる。ノートPCでは Fn+Break や Fn+Pause の場合がある。キーボードに Pause/Break キーがない場合は Esc キー を連打する。それでも止まらない場合は Ctrl+Alt+Delete → タスクマネージャーでExcelを強制終了する。
強制終了すると未保存のデータは失われる。実行前にバックアップを取る習慣をつけておくと安心。
Q3: Exit Do はいつ使う?
特定の条件でループを途中終了したい場合に使う。For Next の Exit For と同じ。
Do While Cells(i, 1).Value <> ""
If Cells(i, 1).Value = "終了" Then
MsgBox "「終了」が見つかりました(行" & i & ")。", vbInformation
Exit Do '← ループを途中で抜ける
End If
i = i + 1
Loop
Q4: Do While と While…Wend の違いは?
While…Wend は古い構文。Do While…Loop を使うのが現在の標準。
| 項目 | Do While…Loop | While…Wend |
|---|---|---|
| 途中抜け | Exit Do で可能 | 不可 |
| 後判定 | Do…Loop While で可能 | 不可 |
| 推奨度 | 推奨 | 非推奨 |
Q5: ループの中でセルに書き込みしても大丈夫?
大丈夫だが、処理速度に影響する。大量のセルに書き込む場合は 配列を使ってVBAを高速化する方法 の方法で配列に一括読み込み→一括書き戻しすると高速になる。
ループ中のエラーで処理が止まるのを防ぎたい場合は エラー処理(On Error)で止まらないマクロを作る方法 を参照。
—
まとめ
- Do While…Loop: 条件がTrueの間ループ。最もよく使う
- Do Until…Loop: 条件がTrueになるまでループ。While の逆
- Do…Loop While / Until: 後判定。必ず1回は実行される
- For Next との違い: 回数が決まっていればFor Next、条件で止めるならDo While
- 無限ループ防止: カウンタのインクリメントを忘れない。上限ガードを入れると安全
関連記事
- データの最終行・最終列を正確に取得する方法 — Do Whileと組み合わせてデータ範囲を正確に処理
- 空白行を一括削除する方法 — Do Whileで空白行を検索しながら削除する実務例
- 配列を使ってVBAを高速化する方法 — ループ対象が大量データの場合、配列で数倍〜数十倍高速に
- VBAの処理速度を高速化する方法 — ScreenUpdating / Calculation の設定でループ処理を高速化
- エラー処理(On Error)で止まらないマクロを作る方法 — ループ中のエラーで処理が止まるのを防ぐ
—
次にやりたくなること
- 空白行を一括削除する方法: Do Whileで空白行を検索しながら削除する処理に応用できる
- 配列を使ってVBAを高速化する方法: ループ対象が大量データの場合、配列に読み込んでから処理すると数倍〜数十倍速くなる
- フォルダ内ファイル一覧を自動取得する方法: Dir関数とDo Whileを組み合わせてフォルダ内のファイルを一括処理する


コメント