VBA Loops

A loop is a programming construct which iteratively executes code. There are different types of loops which use different techniques to iterate. For loops use a counter, Do loops use a condition, and For Each loops iterate over all the elements within an iterable object such as an array or Collection. Loops can also be created using the GoTo statement or recursive procedure calls. Infinite loops can be created intentionally or accidentally which will iterate forever or until the loop's execution is interrupted by the user.

For Loops

For Loops increment or decrement a counter after each iteration until a specified limit is reach. For loops should be used when the number of each iteration is important and when looping over arrays. Specify a starting value, a limit, and a step value to increment or decrement by. If Step is omitted, the default Step value is one. The control variable can be omitted after the Next keyword but this is not recommended. Explicitly writing the control variable helps improve code readability, especially when there are multiple nested loops.

Public Sub Example()

    Dim i As Long  

    'Prints 0 through 9 - Step value is 1 by default
    For i = 0 To 9
        Debug.Print i
    Next i

    'Prints 0 through 9
    For i = 0 To 9 Step 1
        Debug.Print i
    Next i

    'Prints 9 through 0
    For i = 9 To 0 Step -1
        Debug.Print i
    Next i

    'Prints 0, 2, 4, 6, 8
    For i = 0 To 9 Step 2
        Debug.Print i
    Next i

    'Prints 0 through 9 - Control Variable omitted - Not recommended
    For i = 0 To 9
        Debug.Print i
    Next

End Sub

For Each Loops

For Each Loops are used to loop over iterable objects such as arrays and Collections. Specify a control variable and an iterable object to loop over. Writing the control variable after the Next keyword is optional but it is recommended to write it. Explicitly writing the control variable helps with code readability, especially when there are multiple nested loops. When looping over a Collection, the control variable must be a Variant, Object, or the specific Class type of the objects contained in the Collection.

Note: A For Each loop should always be used to iterate over a Collection. It is inefficient to loop over a Collection using a For loop because accessing each item through the Item method of the Collection object is inefficient. With For Each loops, each item is accessed efficiently via the control variable on each iteration.

Public Sub Example()

    '''Loop over collection of value type variables

    Dim Coll As Collection
    Set Coll = New Collection

    Coll.Add 1
    Coll.Add 2
    Coll.Add 3

    Dim i As Variant

    For Each i In Coll
        Debug.Print i
    Next i

    Set Coll = Nothing

End Sub
Public Sub Example()

    '''Loop over a collection of objects

    Dim Coll As Collection
    Set Coll = New Collection

    Coll.Add New Collection
    Coll.Add New Collection
    Coll.Add New Collection

    Dim C As Collection
   'Dim C As Object 'Also works

    For Each C In Coll
        Debug.Print C.Count
    Next C

    Set Coll = Nothing

End Sub

Do While Loops

Do While Loops iterate as long as a conditional statement evaluates to True. Do loops can be used to provide structure and flexibility to looping. The condition can be placed at the top or bottom of the loop.

If the condition is placed at the top of the loop it will be tested before executing its first iteration.

Public Sub Example()

    'Prints 0 through 9

    Dim i As Long

    Do While i < 10
        Debug.Print i
        i = i + 1
    Loop

End Sub

If the condition is placed at the bottom, the loop will always execute the first iteration before testing the condition.

Public Sub Example()

    'Prints 0 through 9

    Dim i As Long

    Do 
        Debug.Print i
        i = i + 1
    Loop While i < 10

End Sub

Do Until Loops

Do Until Loops iterate until a conditional statement evaluates to True. In other words, a Do Until loop iterates while a conditional statement is False. Do loops can be used to provide structure and flexibility to looping. The condition can be placed at the top or bottom of the loop.

If the condition is placed at the top of the loop it will be tested before executing its first iteration.

Public Sub Example()

    'Prints 0 through 9

    Dim i As Long

    Do Until i = 10
        Debug.Print i
        i = i + 1
    Loop

End Sub

If the condition is placed at the bottom, the loop will always execute the first iteration before testing the condition.

Public Sub Example()

    'Prints 0 through 9

    Dim i As Long

    Do 
        Debug.Print i
        i = i + 1
    Loop Until i = 10

End Sub

While Wend Loops

While Wend Loops iterate until a conditional statement evaluates to True. While...Wend loops do not provide the structure and flexibility that Do loops provide. Therefore, Do loops should always be preferred over While...Wend loops.

Public Sub Example()

    'Prints 0 through 9

    Dim i As Long

    While i < 10
        Debug.Print i
        i = i + 1
    Wend

End Sub

GoTo Loops

The GoTo statement can be used to construct a loop by using a condition and a label or line number. Although loops can be constructed using the GoTo statement it is not recommended. Formal looping constructs should be preferred over loops created using GoTo.

Public Sub Example()

    'Prints 0 through 9

    Dim i As Long

TopLoop:
    Debug.Print i
    i = i + 1
    If i < 10 Then GoTo TopLoop

End Sub

Exiting Loops Early

At times it is necessary to break out of a loop before it completes all iterations. To exit from a loop early use the Exit statement.

To exit a For Next loop or a For Each loop early use Exit For.

Public Sub Example()

    'Prints 0 through 5 and then exits loop

    Dim i As Long

    For i = 0 To 9

        Debug.Print i

        If i = 5 Then
            Exit For
        End If

    Next i

End Sub
Public Sub Example()

    'Prints 1, 2 then exits loop

    Dim Coll As Collection
    Dim i As Variant

    Set Coll = New Collection
    Coll.Add 1
    Coll.Add 2
    Coll.Add 3

    For Each i In Coll
 
        Debug.Print i

        If i = 2 Then
            Exit For
        End If

    Next i

    Set coll = Nothing

End Sub

To Exit a Do While or Do Until loop early use Exit Do.

Public Sub Example()

    'Prints 0 through 9

    Dim i As Long

    Do While True

        Debug.Print i

        i = i + 1

        If i > 9 Then
            Exit Do
        End If

    Loop

End Sub
Public Sub Example()

    'Prints 0 through 9

    Dim i As Long

    Do Until False

        Debug.Print i

        i = i + 1

        If i > 9 Then
            Exit Do
        End If

    Loop

End Sub

To exit a While Wend loop or a loop constructed using the GoTo statement, use the GoTo statement with a label or line number outside of the loop.

Public Sub Example()

    'Prints 0 through 4

    Dim i As Long

    While i < 10
        Debug.Print i
        i = i + 1
        If i = 5 Then
            GoTo ExitWhileWendLoop
        End If
    Wend
ExitWhileWendLoop:

End Sub
Public Sub Example1()

    'Prints 0 through 4

    Dim i As Long

    TopLoop:
    Debug.Print i
    i = i + 1
    If i = 5 Then GoTo ExitLoopEarly
    If i < 9 Then GoTo TopLoop
ExitLoopEarly:

End Sub

Nested Loops

Loops can be nested inside each other. Any type of loop can be nested inside any type of loop.

Public Sub Example()

    Dim i As Long
    Dim j As Long
    Dim k As Long

    Dim c As Long

    For i = 1 To 10
        For j = 1 To 10
            For k = 1 To 10
                c = c + 1
            Next k
        Next j
    Next i

    Debug.Print c

End Sub

Recursion

Recursion is a loop in and of itself. A recursive procedure will call itself until a base case is reached (or until stack space is exhausted).

Public Sub Example()

    Recurse 0

End Sub

Public Function Recurse(i As Long)

    'Prints i through 9

    If i > 9 Then Exit Function    
    Debug.Print i
    Recurse i + 1

End Function

Infinite Loops

Infinite loops continue to iterate until the user manually intervenes. Infinite loops can be bugs created accidentally which can cause a program to get stuck, or they can be created intentionally to serve a purpose. Some examples of use cases for infinite loops might be REPLs (Read Evaluate Print Loops), games, monitoring programs, servers, and operating systems. These programs by their nature need to run continuously unless the user manually intervenes.

Public Sub Example1()
    Do While True
        'True is always True.
        Stop
    Loop
End Sub

Public Sub Example2()        
    Do While 1 = 1
        '1 = 1 is always True.
        Stop
    Loop
End Sub

Public Sub Example3()
    Do Until False
        'False is never True.
        Stop
    Loop
End Sub