【VBA】Do While/Do Untilで条件付きループを回す方法(コピペOK)

VBA
スポンサーリンク
スポンサーリンク
  1. この記事でわかること
  2. どんな場面で使う?
  3. 完成イメージ(Before / After)
  4. Do While と For Next の違い(比較表)
  5. 実行前の準備
    1. バックアップを取る
    2. Excelをマクロ有効ブック(.xlsm)で保存する
    3. テスト用データを準備する
  6. 手順(コピペ → 実行まで約5分)
    1. VBE(コードを書く画面)を開く
    2. 標準モジュールを挿入する
    3. コードを貼り付けて実行する
  7. コード(基本版)– Do While…Loopでセルが空になるまで繰り返す
    1. 書き換えポイント
  8. コード(応用版)– Do Until / Loop While / Loop Until の4パターン
    1. 4パターンの比較表
    2. パターン1: Do While…Loop(前判定・Trueの間)
    3. パターン2: Do Until…Loop(前判定・Trueになるまで)
    4. パターン3: Do…Loop While(後判定・Trueの間)
    5. パターン4: Do…Loop Until(後判定・Trueになるまで)
  9. コード(実務版)– 空行スキップ+Dir関数との組み合わせ
    1. 実務版1: 途中の空行をスキップしながら処理
    2. 実務版2: Dir関数と組み合わせてフォルダ内のファイルを処理
    3. 書き換えポイント
  10. よくある落とし穴5選
    1. 1. カウンタ変数のインクリメント忘れ → 無限ループ
    2. 2. Do While と Do Until の条件を逆に書く
    3. 3. 後判定(Do…Loop While/Until)で空データでも1回実行される
    4. 4. Dir関数のDo Whileで fileName = Dir() を書き忘れ → 無限ループ
    5. 5. While…Wend を使っていて Exit(途中抜け)ができない
    6. VBAのDo Whileが無限ループになるときの対処法
    7. VBAのDo WhileとDo Untilの条件が逆になるときの対処法
  11. FAQ
    1. Q1: Do While と For Next はどう使い分ける?
    2. Q2: 無限ループになったときの止め方は?
    3. Q3: Exit Do はいつ使う?
    4. Q4: Do While と While…Wend の違いは?
    5. Q5: ループの中でセルに書き込みしても大丈夫?
  12. まとめ
    1. 関連記事
  13. 次にやりたくなること

この記事でわかること

  • 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 のままだとマクロが保存できない。

  1. 「ファイル」→「名前を付けて保存」
  2. ファイルの種類を「Excelマクロ有効ブック (*.xlsm)」に変更
  3. 保存

テスト用データを準備する

A列にテスト用のデータを入力する(A1〜A5に適当な値を入れ、A6は空欄にする)。

A列
りんご
みかん
バナナ
ぶどう
メロン
(空欄)

手順(コピペ → 実行まで約5分)

VBE(コードを書く画面)を開く

  1. Excelで Alt + F11 を押す

標準モジュールを挿入する

  1. VBEのメニュー →「挿入」→「標準モジュール」

コードを貼り付けて実行する

  1. コードウィンドウに、下のコードをそのままコピペする
  2. Alt + F8 → マクロ名を選んで「実行」
  3. 結果は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 + 1fileName = 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+BreakFn+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
  • 無限ループ防止: カウンタのインクリメントを忘れない。上限ガードを入れると安全

関連記事

次にやりたくなること

コメント

タイトルとURLをコピーしました