ENTERPRISE

Programming Excel with VBA and .NET : Loops

5/15/2013 7:45:14 PM

The other fundamental part of programming logic is the ability to repeat a set of actions until some condition is met. This type of logic is called looping .

Table 1. Visual Basic statements for repeating actions
StatementUse to
Do...Loop or While...WendRepeat a set of actions until a condition is met
For...NextRepeat a set of actions a number of times using a counter
For EachRepeat as set of actions for each item in a collection

Do...Loop and While...Wend are similar, but Do...Loop is more flexible so most programmers simply ignore While...Wend. I'm going to follow their lead—if you're interested, you can read about While...Wend in Help.

The Do...Loop statement repeats a set of actions until a condition is met; you can include the condition at the beginning or the end of the loop. For example, the following code speaks any words you type in an input box and exits if you don't type anything:

    Sub RepeatAfterMe( )
        Dim str As String
        Do
            str = InputBox("Enter something to say.", "Repeat after me...")
            Application.Speech.Speak str
        Loop While str <> ""
    End Sub

The preceding code executes the Speak method one time more than it really needs to —after the user cancels the input. This isn't a big problem, but you can avoid it by using an Exit Do statement instead of testing the condition at the end of the loop (change shown in bold):

    Sub RepeatAfterMe( )
        Dim str As String
        Do
            str = InputBox("Enter something to say.", "Repeat after me...")
            If str = "" Then Exit Do
            Application.Speech.Speak str
        Loop
    End Sub

It's not good style to use Exit Do within long, complicated loops. In those situations, it's important to be able to easily locate the exit condition, and burying it within the body of the loop makes it harder to find. If the unneeded Speak method still bothers you, just change the loop as shown here:

    Sub RepeatAfterMe( )
        Dim str As String
        Do
            str = InputBox("Enter something to say.", "Repeat after me...")
            If str <> "" Then _
              Application.Speech.Speak str
        Loop While str <> ""
    End Sub

Now the loop executes no unneeded statements. There's one last step in this example: the Speech object was introduced in Excel 2002. If you want the preceding code to work with previous versions of Excel, you need to add some conditional logic as shown here:

    Sub RepeatAfterMe( )
        Dim str As String
        Do
            str = InputBox("Enter something to say.", "Repeat after me...")
            ' Speech was added in Excel 10
            If Application.VERSION >= 10 And str <> "" Then
                Application.Speech.Speak str
            ' This is boring, but it works with all versions!
            ElseIf str <> "" Then
                MsgBox str, , "Repeat after me."
            End If
        Loop While str <> ""
    End Sub

This example shows how loops and conditional statements are often used together. Together they form the logical path that your program follows.


Placing the condition first in a Do...Loop prevents the loop from running unless the condition is true to start with. You can choose between While and Until when testing a condition; they are inverses of each other so While str <> "" is the same as Until str = "". The basic form of a Do...Loop is as follows:

    Do [While condition | Until condition]
        ' action
        [If condition Then Exit Do]
    Loop [While condition | Until condition]

For...Next statements perform an action a set number of times as determined by a variable used as a counter. In many situations, you know how many times you want to repeat an action, but the most common is probably when working with lists or tables of items from an array. In that case, you know the start point (the lower bound of the array) and the end point (the upper bound of the array), as shown by this code from an earlier sample:

    ' Display the items in the Flavors array
    Dim i As Integer
    For i = 0 To UBound(Flavors) - 1
        Debug.Print Flavors(i)
    Next

By default, For...Next increments the counter (i) by one each time the loop executes. Thus, Flavors(i) gets each element of the array from 0 to one less than the upper bound. That last bit might seem a little odd, but UBound returns the number of elements in the array, not the maximum index of the array; in this case, the array starts at 0, so the maximum index is one less than the upper bound. If the lower bound is 1 (as it is for arrays returned by Excel methods), then the For...Next loop looks like this:

    Sub ForNextLoop( )
        If Not IsArray(Selection.Value) Then Exit Sub
        Dim i As Integer, j As Integer, str As String
        For i = 1 To UBound(Selection.Value, 1)
            str = ""
            For j = 1 To UBound(Selection.Value, 2)
                str = str & vbTab & Selection(i, j)
            Next
            Debug.Print str
        Next
    End Sub

In the preceding code, Selection.Value returns an array if more than one cell is selected. Since Excel arrays start at 1, the count of elements in the array is the same as the array's upper bound.

You can change the increment used by For...Next by using the Step keyword as shown by the following general version of the For...Next statement:

    For counter = start To stop [Step increment]
        ' action
        [If condition Then Exit For]
    Next [counter]

Use a negative number for increment to count backward. For example, the following code performs a 10-second countdown:

    Sub CountDown( )
        Dim i As Integer
        For i = 10 To 1 Step -1
            Debug.Print i
            Application.Wait Now + #12:00:01 AM#
        Next
        Debug.Print "Blast off!"
    End Sub

In some cases, it is more convenient to perform an action on each item in a group, rather than relying on the number of items in the group. For those situations, Visual Basic provides the For Each statement. The following code displays a list of the workbook's worksheets in the Immediate window:

    Dim ws As Worksheet
    For Each ws In Worksheets
        Debug.Print ws.Name
    Next

For Each works only with collections , which are a special type of object that contains a group of other objects. All collections have a special, hidden property called an enumerator that allows them to work with For Each. Collections also usually have an Add method and a Count property and are usually named using the plural form of the name of the object they contain. Thus the Worksheets collection contains Worksheet objects.

Excel doesn't always follow these rules for collections. That's why I say usually here.


For Each sets the object variable to the next object in the collection each time the loop executes and automatically ends after it reaches the last object. There's no Step keyword to skip objects or count backward; the general form of the statement looks like this:

    For Each object In collection
        ' action
        [If condition Then Exit For]
    Next [object]

The type of object must be the same as the type of objects in collection. Some collections, such as the collection returned by the Excel Sheets method, can contain objects of more than one type. Therefore, the following code would cause a type-mismatch error if a workbook contains a Chart sheet:

     Sub ForEachLoop( )
        Dim ws As Worksheet
        For Each ws In Sheets ' Possible error!
            Debug.Print ws.Name
        Next
    End Sub

If you want to work with a mixed collection like Sheets, use a generic object as shown here:

    Sub ForEachLoop( )
        Dim obj As Object
        For Each obj In Sheets
            Debug.Print obj.Name, TypeName(obj)
        Next
    End Sub

Now the code displays a list of all the sheets in the workbook, along with their type.

Other  
 
Video
Top 10
SG50 Ferrari F12berlinetta : Prancing Horse for Lion City's 50th
The latest Audi TT : New angles for TT
Era of million-dollar luxury cars
Game Review : Hearthstone - Blackrock Mountain
Game Review : Battlefield Hardline
Google Chromecast
Keyboards for Apple iPad Air 2 (part 3) - Logitech Ultrathin Keyboard Cover for iPad Air 2
Keyboards for Apple iPad Air 2 (part 2) - Zagg Slim Book for iPad Air 2
Keyboards for Apple iPad Air 2 (part 1) - Belkin Qode Ultimate Pro Keyboard Case for iPad Air 2
Michael Kors Designs Stylish Tech Products for Women
REVIEW
- First look: Apple Watch

- 3 Tips for Maintaining Your Cell Phone Battery (part 1)

- 3 Tips for Maintaining Your Cell Phone Battery (part 2)
Popular Tags
Video Tutorail Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Exchange Server Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe Photoshop CorelDRAW X5 CorelDraw 10 windows Phone 7 windows Phone 8 Iphone