Excel VBAのループ – For Each, For Next, Do While など

Written by

Editorial Team

Reviewed by

Steve Rynearson

Translated by

masahiro yoshida

Last updated on 6月 30, 2022

VBAで効率的に作業するためには、ループの理解は必須です。

ループは、コードブロックを設定された回数だけ繰り返したり、オブジェクトの集合内の各オブジェクトに対してコードブロックを繰り返すことを可能にします。 まず、ループがどのような機能を持つのか、いくつかの例を挙げて説明します。その後、ループのすべてをお教えします。

VBAループの簡単な例

For Eachループ

For Eachループは、ワークブック内のすべてのワークシートや範囲内のすべてのセルなど、コレクション内のすべてのオブジェクトをループ処理します。

ワークブック内のすべてのワークシートをループする

このコードは、ワークブック内のすべてのワークシートをループし、もし非表示に設定されていたとしても、全てのシートを見えるようにします。

Sub LoopThroughSheets()
Dim ws As Worksheet
    For Each ws In Worksheets
        ws.Visible = True
    Next
End Sub

範囲内のすべてのセルをループする

このコードは、セルの範囲内をループし、セルの値が負、正、またはゼロであるかどうかをテストします。

Sub If_Loop()
Dim Cell as Range
 
  For Each Cell In Range("A2:A6")
    If Cell.Value > 0 Then
      Cell.Offset(0, 1).Value = "正"
    ElseIf Cell.Value < 0 Then
      Cell.Offset(0, 1).Value = "負"
    Else
      Cell.Offset(0, 1).Value = "ゼロ"
    End If
  Next Cell
 
End Sub

vba else if statement if文

For Nextループ

Forループのもう一つのタイプは、For Nextループです。 For Nextループは、整数の範囲をループすることができます。 このコードでは、1から10までの整数をループして、それぞれをメッセージボックスで表示します。

Sub ForLoop()
    Dim i As Integer
    For i = 1 To 10
        MsgBox i
    Next i
End Sub

Do While ループ

Do Whileループは、ある条件を満たしている間(While)、ループします。以下のコードでは1から10までの整数をループし、それぞれをメッセージボックスで表示します。

Sub DoWhileLoop()
    Dim n As Integer
    n = 1
    Do While n < 11
        MsgBox n
        n = n + 1
    Loop
End Sub

Do Untilループ

逆に、Do Until Loopsは、ある条件が満たされるまで(Until)ループします。このコードでは、前の2つの例と同じことをします。

Sub DoUntilLoop()
    Dim n As Integer
    n = 1
    Do Until n > 10
        MsgBox n
        n = n + 1
    Loop
End Sub

後述しますが、Do WhileやDo Untilのループを作る際には、無限ループとならないように細心の注意を払う必要があります。

VBA Loop Builder

vba loop builder

上の画像はAutoMacroに含まれるプレミアムVBAアドインの「Loop Builder」のスクリーンショットです。Loop Builderを使うと、異なるオブジェクトや数値をループするループをすばやく簡単に構築できます。各オブジェクトに対してアクションを実行したり、特定の条件を満たすオブジェクトだけを選択したりすることができます。

このアドインには、他にも多くのコードビルダー、豊富なVBAコードライブラリ、コーディングツールの数々が含まれており、VBAの開発者にとって必携のアドインです。

それでは、さまざまな種類のループを徹底的に解説していきます。

VBA For Next ループ

Forループの構文

For Nextループを使用すると、コードのブロックを指定した回数だけ繰り返すことができます。構文は次のとおりです。

[Dim カウンター変数 as Long]

For カウンター変数 = 開始値 to 終了値 [ステップ値]
    [任意の処理]
Next [カウンター変数]

ここで、括弧内の項目はオプションです。

  • [Dim カウンター変数 as Long] – カウンター変数を宣言します。Option Explicit がモジュールの先頭で宣言されている場合は、必須です。
  • カウンター変数 – カウントに使われる整数型変数です。
  • 開始値 – カウントの開始値です。 (例: 1)
  • 終了値 – カウントの終了値です。 (例: 10)
  • [ステップ値] – 整数1個ごとではなく、整数n個ごとにカウントできるようにします。また、負の値で逆に数えることもできます (例: Step -1)
  • [任意の処理] – 実際に繰り返すコード。
  • Next [カウンター変数] – For Nextループの終了位置を知らせます。カウンター変数は入れても入れなくても構いません。しかし、コードを読みやすくするために、カウンター変数を含めることを強くお勧めします。

わかりにくいかもしれませんが、ご安心ください。いくつかの例題を確認します。

10まで数える

このコードでは、For-Nextループを使って10まで数えます。

Sub ForEach_CountTo10()

Dim n As Integer
For n = 1 To 10
    MsgBox n
Next n

End Sub

For ループステップ

10まで数える – 偶数のみ

このコードでは、偶数だけを数えて10まで数えます。

Sub ForEach_CountTo10_Even()

Dim n As Integer
For n = 2 To 10 Step 2
    MsgBox n
Next n

End Sub

「Step 2」を追加していることに注目してください。これは、Forループのカウンター変数を2ずつ「ステップ」するように指示しています。 また、負のステップ値を使用することで、逆にステップすることもできます。

For Loop Step – Inverse

10からのカウントダウン

このコードは10からのカウントダウンを行います。

Sub ForEach_Countdown_Inverse()

Dim n As Integer
For n = 10 To 1 Step -1
    MsgBox n
Next n
MsgBox "Lift Off"

End Sub

セルが空白の場合、行を削除する

私が最もよく使うのは、負のステップ値のForループを用いてセル範囲をループし、ある条件を満たした行を削除する方法です。 上の行から下の行へループさせると、行を削除するときにカウンタが狂ってしまうためです。

この例では、最下行から開始して空白のセルがある行を削除します。

Sub ForEach_DeleteRows_BlankCells()

Dim n As Integer
For n = 10 To 1 Step -1
    If Range("a" & n).Value = "" Then
        Range("a" & n).EntireRow.Delete
    End If
Next n

End Sub

ネストされたForループ

Forループの中に別のForループを「ネスト(入れ子)」することができます。ここでは、ネストされたForループを使って、乗算表を作成します。

Sub Nested_ForEach_MultiplicationTable()

Dim row As Integer, col As Integer

For row = 1 To 9
    For col = 1 To 9
        Cells(row + 1, col + 1).Value = row * col
    Next col
Next row

End Sub

vba nested for loop ネスト 入れ子 ループ

Exit For

Exit Forステートメントを使用すると、 For Nextループを直ちに終了させることができます。 通常、Exit ForはIfステートメントと一緒に使用し、特定の条件が満たされた場合にFor Nextループを終了させます。

例えば、あるセルを探すためにForループを使用するとします。そのセルが見つかったら、ループを終了してコードを高速化することができます。

このコードでは、1行目から1000行目までをループして、A列の「error」を探します。もし見つかったら、セルを選択した状態にして、見つかったエラーを警告してループを終了します。

Sub ExitFor_Loop()

Dim i As Integer
 
For i = 1 To 1000
    If Range("A" & i).Value = "error" Then
        Range("A" & i).Select
        MsgBox "エラーが見つかりました"
        Exit For
    End If
Next i

End Sub

重要:ネストされた For Loop の場合、Exit For は現在の For Loop を終了するだけで、アクティブな Loop をすべて終了するわけではありません。

Continue For

VBAには、Visual Basicにある「Continue」コマンドはありません。代わりに “Exit “を使用する必要があります。

VBAのFor Eachループ

VBAのFor Eachループは、コレクション内のすべてのオブジェクトをループします。

  • 範囲内のすべてのセル
  • ワークブック内の全ワークシート
  • ワークシート内の全図形
  • 開いているすべてのワークブック

また、ネストされたFor Eachループを使用することもできます。

  • すべてのワークシートの範囲内のすべてのセル
  • 全ワークシート上の全図形
  • 開いているすべてのワークブックのすべてのシート
  • などなど…

構文は以下のとおりです。

For Each オブジェクト in コレクション
[任意の処理]
Next [オブジェクト]

ここで

  • オブジェクト – レンジ、ワークシート、ワークブック、図形などを表す変数。(例:rng)
  • コレクション – オブジェクトのコレクションです。(例:Range(“a1:a10”)
  • [任意の処理] – 各オブジェクトで実行されるコードブロックです。
  • Next [オブジェクト] – クロージングステートメント。[Object] はオプションですが、強くお勧めします。

範囲内の各セルをループ

このコードでは、範囲内の各セルをループします。

Sub ForEachCell_inRange()

Dim cell As Range

For Each cell In Range("a1:a10")
    cell.Value = cell.Offset(0,1).Value
Next Cell

End Sub

ワークブック内の各ワークシートをループ

このコードは、ワークブック内のすべてのワークシートをループし、各シートのプロテクトを解除するものです。

Sub ForEachSheet_inWorkbook()

Dim ws As Worksheet

For Each ws In Worksheets
    ws.Unprotect "password"
Next ws

End Sub

開かれている各ワークブックをループ

このコードでは、開いているすべてのワークブックを保存して閉じます。

Sub ForEachWB_inWorkbooks()

Dim wb As Workbook

For Each wb In Workbooks
    wb.Close SaveChanges:=True
Next wb

End Sub

ワークシート内の各図形をループ

このコードは、アクティブシート内のすべての図形を削除します。

Sub ForEachShape()

Dim shp As Shape

For Each shp In ActiveSheet.Shapes
    shp.Delete
Next shp

End Sub

ワークブック内の各ワークシートの各図形をループ

For Eachループを入れ子にすることもできます。ここでは、アクティブワークブック内のすべてのワークシートにあるすべての図形をループします。

Sub ForEachShape_inAllWorksheets()

Dim shp As Shape, ws As Worksheet

For Each ws In Worksheets
    For Each shp In ws.Shapes
        shp.Delete
    Next shp
Next ws

End Sub

For Each – IF ループ

前にも述べたように、ループの中でIf文を使って、ある条件を満たしたときだけ動作を実行することができます。 このコードは、ある範囲内のセルが空白だった場合、そのセルが含まれる行全体を非表示にします。

Sub ForEachCell_inRange()

Dim cell As Range

For Each cell In Range("a1:a10")
    If cell.Value = "" Then _
       cell.EntireRow.Hidden = True
Next cell

End Sub

VBA Do While ループ

VBAのDo WhileとDo Until(次章参照)は非常によく似ています。これらは、ある条件を満たしている間(または、満たされるまで)、ループを繰り返します。

Do Whileループは、ある条件を満たしている間、ループを繰り返します。

以下はDo Whileの構文です。

Do While 条件
[任意の処理]
Loop

ここで

  • 条件 – テストする条件
  • [任意の処理] – 繰り返すコードブロック

ループの最後にConditionを設定したDo Whileループを設定することも可能です。

Do 
[任意の処理]
Loop While 条件

それぞれをデモして、どのように違うかを説明します。

Do While

冒頭でも紹介したDo Whileループの例です。

Sub DoWhileLoop()
    Dim n As Integer
    n = 1
    Do While n < 11
        MsgBox n
        n = n + 1
    Loop
End Sub

Loop While

今度は条件をループの最後に移動してみましょう。実行する内容は変わりません。

Sub DoLoopWhile()
    Dim n As Integer
    n = 1
    Do
        MsgBox n
        n = n + 1
    Loop while n < 11
End Sub

VBA Do Untilループ

Do Until Loopは、ある条件を満たすまでループを繰り返します。構文は基本的にDo Whileループと同じです。

Do Until 条件
[任意の処理]
Loop

Do Whileループと同様、条件の位置はループの最初でも最後でもかまいません。

Do
[任意の処理]
Loop Until 条件

Do Until

このDo Untilループは、前の例と同じように10まで数えます。

Sub DoUntilLoop()
    Dim n As Integer
    n = 1
    Do Until n > 10
        MsgBox n
        n = n + 1
    Loop
End Sub

Loop Until

このLoop Untilループも、10までカウントします。

Sub DoLoopUntil()
    Dim n As Integer
    n = 1
    Do
        MsgBox n
        n = n + 1
    Loop Until n > 10
End Sub

Doループの終了

Exit ForでForループを抜けるのと同じように、Exit DoコマンドでDoループをすぐに抜けることができます。

Exit Do

以下は、Exit Doの例です。

Sub ExitDo_Loop()

Dim i As Integer
i = 1 

Do Until i > 1000
    If Range("A" & i).Value = "error" Then
        Range("A" & i).Select
        MsgBox "エラーが見つかりました"
        Exit Do
    End If
    i = i + 1
Loop

End Sub

ループの終了または中断

前述したように、ループを抜けるにはExit ForやExit Doを使用します。

Exit For
Exit Do

ただし、これらのコマンドは、ループを実行する前にコードに追加しておく必要があります。

現在実行中のループを「壊す」場合は、キーボードでESCや CTRL+Pause Breakを押してみるとよいでしょう。ただし、これはうまくいかないかもしれません。 うまくいかない場合は、ループが終了するのを待つか、無限ループの場合は、CTRL+ALT+ DeleteでExcelを強制終了する必要があります。

このため、私はDoループを避けるようにしています。誤って無限ループを作成すると、Excelを再起動しなければならず、作業内容が失われる可能性があるからです。

その他のループの例

行をループする

これは、ある列のすべての行をループするものです。

Public Sub LoopThroughRows()
 
Dim cell As Range
 
For Each cell In Range("A:A")
    If cell.value <> "" Then MsgBox cell.address & ": " & cell.Value
Next cell
 
End Sub

列をループする

これは、1つの行のすべての列をループします。

Public Sub LoopThroughColumns()

Dim cell As Range

For Each cell In Range("1:1")
    If cell.Value <> "" Then MsgBox cell.Address & ": " & cell.Value
Next cell

End Sub

フォルダー内のファイルをループする

このコードは、フォルダー内のすべてのファイルをループして、リストを作成します。

Sub LoopThroughFiles ()

Dim oFSO As Object
Dim oFolder As Object
Dim oFile As Object
Dim i As Integer

Set oFSO = CreateObject("Scripting.FileSystemObject")

Set oFolder = oFSO.GetFolder("C:\Demo")

i = 2

For Each oFile In oFolder.Files
    Range("A" & i).value = oFile.Name
    i = i + 1
Next oFile

End Sub

配列のループ処理

このコードは、配列 ‘arrList’ の中をループします。

For i = LBound(arrList) To UBound(arrList)
    MsgBox arrList(i)
Next i

LBound関数は配列の「下限」を、UBoundは「上限」を取得します。

Access VBAのループ

上記の例のほとんどは、Access VBAでも動作します。ただし、AccessではRangeオブジェクトではなく、Recordsetオブジェクトでループします。

Sub LoopThroughRecords()
   On Error Resume Next
   Dim dbs As Database
   Dim rst As Recordset
   Set dbs = CurrentDb
   Set rst = dbs.OpenRecordset("tblClients", dbOpenDynaset)
   With rst
      .MoveLast
      .MoveFirst
      Do Until .EOF = True
         MsgBox (rst.Fields("ClientName"))
        .MoveNext
      Loop
   End With
   rst.Close
   Set rst = Nothing
   Set dbs = Nothing
End Sub
vba-free-addin

VBA Code Examples Add-in

Easily access all of the code examples found on our site.

Simply navigate to the menu, click, and the code will be inserted directly into your module. .xlam add-in.

(No installation required!)

Free Download

Return to VBA Code Examples