UserGuide

Repeating Code

From Xojo Documentation

There may be times when one or more lines of code need to be executed more than once. If you know how many times the code should execute, you could simply repeat the code that many times, but that is not an efficient way to write code. For example, if you wanted a PushButton to display a message three times when clicked, you could simply put the MessageBox method in your code three times like this:

MessageBox("One")
MessageBox("Two")
MessageBox("Three")

But suppose you need it to count fifty times or perhaps until a certain condition is met? Simply repeating the code over and over in these cases will either be just tedious or not possible. How do you solve this problem? The answer is a loop.

Loops execute one or more lines of code over and over again.

The following types of loop structures are available:

  • While...Wend: The loop runs until the condition specified in the While statement is satisfied.
  • Do...Loop: The loop runs until the condition specified in the Do or Loop statements are satisfied.
  • For...Next: The loop runs a specified number of times given in the For statement. A local counter variable controls the execution of the loop.
  • For...Each: The loop runs repeatedly for each element in an array.

You can declare local variables inside a loop structure. When you define a local variable inside a loop structure, its scope is local to the structure itself, not the entire method. It goes out of scope after the condition of the loop is satisfied. If you need to use the variable after the loop executes, define it outside the loop, so that it is local to the method.

While...Wend

A While...Wend loop executes one or more lines of code between the While and the Wend statements. The code between these statements is executed repeatedly, provided that the condition passed to the While statement continues to evaluate to True.

Consider the following example:

Var i As Integer
While i < 10
i = i + 1
Wend

The variable “i” will be zero by default when it is created by the Var statement. Because zero is less than ten, execution will move inside the While...Wend loop. The variable i is incremented by one and the loop returns to the top where the While statement checks to see if the condition is still True and if it is, then the code inside the loop executes again. This continues until the condition is no longer True. If the variable i was not less than ten in the first place, the contents fo the loop are skipped entirely and execution would continue at the line of code after the Wend statement.

Do...Loop

Do...Loops are similar to While loops but a bit more flexible. Do loops continue to execute all lines of code between the Do and Loop statements until a particular condition is True. While loops on the other hand execute as long as the condition remains True. Do loops provide more flexibility than While loops because they allow you to test the condition at the beginning or end of the loop. The example below shows two loops; one testing the condition at the beginning and the other testing it at the end:

Var i As Integer
Do Until i = 10
i = i + 1
Loop

i = 0
Do
i = i + 1
Loop Until i = 10

The difference between these two loops is this: In the first case, the loop will not execute if the variable i is already equal to 10. The second loop executes at least once regardless of the value of i because the condition is not tested until the end of the loop.

It is possible to create a Do loop that does not test for any condition. Consider this loop:

Do
i = i + 1
Loop

Because there is no test, this loop will run endlessly. You use the Exit command to force a loop to exit without testing for a condition. However, this is generally considered poor design because you have to read through the code to figure out what will cause the loop to end.

Do
i = i + 1
If i > 10 Then Exit
Loop

Endless Loops

Much like the situation with a Do...Loop without a condition, you should be sure that the code inside your While and Do loops eventually causes the condition to be satisfied. Otherwise, you will end up with an endless loop that runs forever. Should you do this accidentally, you can click the Stop button in the Debugger. If this doesn’t work, you can always “force-quit” your running application using Task Manager on Windows, the Force Quit window on macOS or the Tasks window in Linux.

Lengthy Loops

When a loop starts running, its process “takes over” and doesn’t allow the user to interact with interface elements such as menus, buttons, and scroll bars. On modern computers and reasonably short loops, this isn’t a problem because the loop executes faster than the user can think of another button to push or menu item to select. If this is not true, there are a couple of things you can do:

  • If the user should wait until the loop is finished before doing anything else (e.g., if a user action might invalidate the results of the loop), you can signal that a lengthy operation is in progress by changing the mouse cursor to a “wait” cursor until the loop ends.
  • If the user is permitted to do other tasks while the loop is running, you should consider using a thread. A thread runs code in the background, allowing the main application to handle user operations in the foreground.

For...Next

While and Do loops are perfect when the number of times the loop should execute cannot be determined because it is based on a condition. A For...Next loop is for cases in which you can determine the number of times to execute the loop. For example, suppose you want to add the numbers one through ten to a List Box. Since you know exactly how many times the code should execute, a For...Next loop is the right choice. For...Next loops also differ from While and Do loops because For loops have a loop counter variable, a starting value for that variable and an ending value. The basic construction of a For loop is:

Var Counter As Integer
For Counter = 0 To 100
// [your code goes here]
Next

Notice that the Var statement declares the counter as an Integer. Although an Integer is the most common way to define the counter variable, you can also declare it as a Single or Double.

In this example, the counter variable was declared in the usual way, via the Var statement. Since counter variables are rarely needed outside the For loop, you can also declare the counter variable right inside the For statement. In other words, you can redo this example like this:

For Counter As Integer = 0 To 100
// [your code goes here]
Next

Notice that the Var statement has been removed from the example. If you declare the counter variable this way, you can use it only within the For loop. It goes out of scope after the For loop is finished. This is the recommended way to declare a counter variable. Of course, if you need to read or change the value of the counter variable outside the For loop, which is rarely necessary, you should use the Var statement instead.

In the prior examples, the starting value and the ending value are specified as numbers. You can also use variables, as shown in this example:

Var startingValue, endingValue As Integer
startingValue = 0
endingValue = 100

For counter As Integer = startingValue To endingValue
// [your code goes here]
Next

The first time through the loop, the counter variable will be set to startingValue. When the loop reaches the Next statement, the counter variable will be incremented by one. When the Next statement is reached and the counter variable is equal to endingValue, the counter will be incremented and the loop will end.

Look back at the example mentioned earlier. You want to add the numbers one through ten to a List Box. The following code accomplishes that:

For i As Integer = 1 To 10
ListBox1.AddRow(i.ToString)
Next

The counter variable (i in this case) is passed to the Str function to be converted to a string so that it can be passed to the AddRow method of ListBox1.

fa-info-circle-32.png
Note: The letter “i” is commonly used as the loop counter for historical reasons. In FORTRAN (an early programming language), the letters I through N are integers by default. Therefore, FORTRAN programmers began the practice of using those letters as counters, and in the order they appear in the alphabet. That is, if a FORTRAN programmer needed to nest one loop in another, they would use j as the counter for the inner loop. This convention made it easy for FORTRAN programmers to follow the logic of code that processed multi-dimensional arrays.

By default, For loops increment the counter by one. You can specify another increment value using the Step statement. In this example, the Step statement is added to increment the counter variable by 5 instead of 1:

For i As Integer = 5 To 100 Step 5
ListBox1.AddRow(i.ToString)
Next

All the above examples count from lowest to highest values. But you can also count in reverse order by using DownTo in place of To. For example, this counts from 10 to 1:

For i As Integer = 10 DownTo 1
ListBox1.AddRow(i.ToString)
Next

You can also use Step when counting in reverse. In this example, the For loop starts the counter at 100 and decrements by 5:

For i As Integer = 100 DownTo 1 Step 5
ListBox1.AddRow(i.ToString)
Next

Performance Considerations

So far, you have seen examples where startingValue and endingValue are integer numbers. If either startingValue or endingValue are expressions that must be evaluated to integers (such as a function call), the For loop will perform the evaluation each time it increments the counter — even if the expression always evaluates to the same integer.

Therefore, for performance reasons it is advisable to perform any evaluations before entering the loop. For example, consider a loop that needs to process all the fonts that are installed on the user’s computer. This number cannot be known in advance but there is a built-in function, System.FontCount, that you can use to obtain the total number of fonts. If you use it in the For statement to compute endingValue (like so):

For i As Integer = 0 To FontCount - 1
.
.
Next

The loop will run more slowly than if you calculate the value only once:

Var numFonts As Integer = FontCount - 1
For i As Integer = 0 To numFonts
.
.
Next

However, the difference in speed may be of no practical value unless it is an incredibly lengthy loop. On a typical computer the difference between these two loops is only small fractions of a second — not enough to lose sleep over.

Nested Loops

A For loop (as well as any other kind of loop) can have another loop inside it. In the case of a For loop, the only thing you will have to watch out for is making sure that the counter variables are different so that the loops won’t confuse each other. The example below uses a For loop embedded inside another For loop to go through all the cells of a multi-column ListBox counting the number of cells in which the word “Hello” appears:

Var count As Integer
For row As Integer = 0 To ListBox1.LastRowIndex
For column As Integer = 0 To ListBox1.ColumnCount - 1
If ListBox1.CellValueAt(row, column) = "hello" Then
count = count + 1
End If
Next
Next
MessageBox(count.ToString)

One way to help keep this readable is to include the counter variable with the Next statement so you can more easily see which loop is which:

Var count As Integer
For row As Integer = 0 To ListBox1.LastRowIndex
For column As Integer = 0 To ListBox1.ColumnCount - 1
If ListBox1.CellValueAt(row, column) = "hello" Then
count = count + 1
End If
Next row
Next count
MessageBox(count.ToString)

For Each...Next

Another situation in which you want to loop through a group of values is array processing. Rather than looping through a set of statements for each value of a counter, the For Each...Next statement processes each element of an array that is passed to it.

Take a look at an example to sum the values of an array using a counter variable:

Var values() As Double
values = Array(2.2, 1.1, 3.3, 4.4)

Var sum As Double
Var element As Double

For i As Integer = 0 To values.LastRowIndex
sum = sum + values(i)
Next

Here is the same example using For...Each:

Var values() As Double
values = Array(2.2, 1.1, 3.3, 4.4)

Var sum As Double
Var element As Double

For Each element In values
sum = sum + element
Next

In the For Each statement, instead of a counter variable, there is a variable that automatically gets the value of each element in the array. In the above example, the element variable gets the next value in the values array each time through the loop. When you are working with arrays, For Each allows you to write simpler code.

Since the array doesn’t necessarily have to be numbers, this statement enables you to process a group of objects of any type. They could be pictures, colors, documents, sets of database records, and so forth. As is the case for the For...Next loop, you can declare the data type of the element variable inside the For Each statement rather than in a separate Var statement. For example the previous example could be rewritten like this:

Var values() As Double
values = Array(2.2, 1.1, 3.3, 4.4)

Var sum As Double
For Each element As Double In values
sum = sum + element
Next

Adding Loops Using the Code Editor

The Code Editor’s contextual menu offers an especially convenient way of adding loops to your code. There are several items in the contextual menu to wrap the selected lines of code inside a type of loop. To use these menu items, simply write the code that goes inside the loop, select the lines, and then choose the type of loop from the contextual menu. Your choices are Do/Loop, While/Wend and For/Next.

The Code Editor can wrap the selected lines in the loop but it doesn’t know what condition should terminate the loop. Therefore, it inserts the placeholder text _condition_ in the loop statement. This condition is selected for you so all you need to do is start typing to replace it with the condition you want.

See Also

For...Next, For Each...Next, Do...Loop, While...Wend commands