Keyword

For...Next


Description

Executes a series of statements a specified number of times.

Usage

For counter [ As datatype ] = start To | DownTo end [ Step value ]
  [ Statements ]
  [ Continue [ For ] ]
  [ Exit [ For ] ]
  [ Statements ]
Next [ counter ]

Part

Description

counter

A variable that is incremented or decremented every time the loop executes. It can be an Integer, Single or Double. By default the value is changed by 1 at the end of every iteration, i.e. when the Next statement is reached or a Continue statement is invoked inside the loop. Note that the counter can be changed inside the loop. See the Troubleshooting section.

datatype

The Datatype of the counter.

start

Initial value of counter.

To | DownTo

Use To to increment the counter at every loop iteration by the Step value (default: 1). Use DownTo to subtract the Step value from the counter at every iteration. You can also count down by using a negative Step value when using To as described in the "Step value" section below.

end

Final value of counter. The loop ends if the counter value has reached a value past the end value at the time the Next (or Continue) statement is reached (this means: If the counter gets incremented, the loop ends once counter > end; if the counter gets decremented, the loop ends once counter < end).

Step value

Amount to increment or decrement counter when a Continue or the loop's Next statement is reached. If Step is not used, the value defaults to 1.

Statements

Statements to be executed repeatedly inside the loop.

Continue

If a Continue statement is present, execution skips directly to the loop's Next statement, thereby causing another loop iteration unless the end is reached.

Exit

If an Exit statement is present, execution skips over the remaining statements in the loop and resumes with the statement following the Next statement. See the Exit statement for additional options that are relevant for nested loops.

Notes

Declaring the counter inside the For statement

The counter variable in a For statement can be declared inside the For statement rather than externally, as a local variable.

For example, the code

Var i As Integer
For i = 1 To 10
  ...
Next
' i is now 11

can also be rewritten as

For i As Integer = 1 To 10
  ... ' i can be used in here
Next
' i is not available at this point any more

In the second code example the counter variable goes out of scope after the last iteration of the For loop, i.e. you can not read the value of the counter after the loop. In the first code example, the counter variable remains accessible after the loop.


Variables declared inside the loop remain private to it

Variables declared inside a loop are not accessible outside of it (which is the same as for other block statements such as If, While and so on).

For example:

For i As Integer = 1 To 5
  Var multBy2 As Boolean
  multBy2 = i * 2
Next
MessageBox(multBy2.ToString) ' "multBy2" is out of scope, i.e. you cannot access "multBy2" here. To solve this, move the Var statement before the For statement.

Counting backward

To count from 10 down to 0, you can write (the "Step 1" part is optional):

For loopIndex As Integer = 10 DownTo 0 Step 1

Or:

For loopIndex As Integer = 10 To 0 Step -1

Step usage

Aside from using -1 as a Step value to count backward, you can also use it to change counter by a different value in every loop iteration:

For i As Integer = 1 To 6 Step 2
  MessageBox("i = " + i.ToString)
Next

The numbers 1, 3 and 5 will be shown.


Exit and Continue

Use Exit to leave a loop early:

Const attempts = 10
Var attempt As Integer
For attempt = 1 To attempts
  Var randomValue As Double = Rnd
  If randomValue > 0.9 Then
    MessageBox("Found a random value above 0.9 after " + attempt.ToString + " iterations.")
    Exit
  End If
Next
If attempt > attempts Then
  MessageBox("Found NO random value above 0.9 after " + attempts.ToString + " iterations.")
End If

Similar code using a Continue statement:

Const attempts = 100
Var matchCount As Integer
For attempt As Integer = 1 To attempts
  Var randomValue As Double = Rnd
  If randomValue <= 0.9 Then
    Continue
  End If
  matchCount = matchCount + 1
Next
MessageBox("Found " + matchCount.ToString + " random values above 0.9 within " + attempts.ToString + " iterations.")

In the case of nested loops, you can Exit or Continue to the outer loops, provided they are of a different kind (For vs. While vs. Do):

For tries As Integer = 1 To 3 ' let's try this up to 3 times
  Var misses As Integer
  Do
    Var randomValue As Integer = Rnd * 100
    If randomValue = 0 And tries > 1 Then
      Exit For ' Leaves both the Do and the For loops by jumping to #4
    End If
    If randomValue < 5 Then
      Continue For ' Leaves the Do loop for another For loop by jumping to #3
    End If
    If randomValue < 20 Then
      Continue Do ' Reiterates the Do loop by jumping to #1
    End If
    misses = misses + 1
    If misses > 10 Then
      Exit Do ' Leaves the Do loop by jumping to #2
    End If
  Loop ' #1
  MessageBox("End of Do loop") ' #2
Next ' #3
MessageBox("End of For loop") ' #4

Using Single or Double values as loop counter

The following code shows the values 1.5, 2.5 and 3.5:

For dblValue As Double = 1.5 To 4
  MessageBox("Now at " + dblValue.ToString)
Next

Counter value after the loop

If you declare the counter variable outside the loop, it will retain a value after the loop ends. If it finishes normally, i.e., it cycles though every element without encountering Exit, that value will be the end value plus 1 if you have not specified a Step value, or the end value plus Step if you have.

Var i As Integer

For i = 1 To 10
  ' Some code
Next i
' i = 11

For i = 1 To 10 Step 2
  ' Some code
Next i
' i = 12

For i = 10 DownTo 1
  ' Some code
Next i
' i = 0

For i = 10 To 1 Step -2
  ' Some code
Next i
' i = -1
Var d As Double

For d = 1.0 To 10.0
  ' Some code
Next d
' d = 11.0

For d = 1.0 To 10.0 Step 0.5
  ' Some code
Next d
' d = 10.5

If the loop exits early through Exit, the counter will retain the value it held at the point of exit.


Performance considerations

If start, end, or step are not constant values, they get evaluated every time the loop is executed, even if they evaluate to the same value for each iteration. Therefore, the loop:

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

will take more time than:

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

Be especially aware of this when the end value changes during the loop! Also, you can modify the counter variable inside the loop.

The example below shows both techniques. While it adds new elements to the array, but it will still iterate over all items:

Var values() As Integer = Array(1,5,4,8)
' The loop inserts 0 after values above 4 inside the values array:
For i As Integer = 0 To values.LastIndex
  If values(i) > 4 Then
    values.AddAt(i + 1, 100)
    i = i + 1 ' skip the next item because otherwise we'd add more values endlessly
  End If
Next

Miscellaneous

  • For...Next statements can be nested but each For...Next statement must have its own counter variable.

  • When a For loop (same goes for While and Do loops) runs, it blocks the application's user interface, preventing the user from interacting with menus and controls. Ordinarily, this is of no concern. If, however, the loop is very lengthy, you can move the code for the loop to a separate Thread, allowing it to execute in the background and allowing the user interface to remain responsive.

  • When multiple threads are running, be aware that at every loop iteration Xojo might switch to another thread. This means that if you have a time critical loop that should not yield its processing time to other threads, consider adding #Pragma BackgroundTasks False in a line before the loop statement.


Troubleshooting

You may have trouble using the For...Next loop, e.g. it exits too soon, it never ends, it processes only one every two values... In such cases, you should set a breakpoint on the For...Next line to verify the counter value.

The most common mistakes are:

  • You have defined two different integers (say, i and j) in a method and you are using both as counters. However, you have copied and pasted some code which also uses i or jj as variables. As a consequence, the computations actually modify the counters you use and mess up the loops.

  • Whenever you plan to delete some items from a list, it is strongly recommended that you write a loop going from the end down to the start to avoid problems with the counter variable.

  • You used a limited Integer type (UInt32 or UInt8) and your loop end reach the minimum or maximum size of the Integer. In order for a loop to exit the counter, it has to go beyond the bounds of the loop's specified end value. For example if your end value is 255, but you used an UInt8 which has a maximum value of 255, then your loop counter can never exceed 255 and you will have an infinite loop. The same logic applies when DownTo is used.

Sample code

The code below uses the For...Next statement to test the values in an array and change those that are "Today" to "Tomorrow".

Var days() As String = Array("May 1", "Yesterday", "Today", "Next week")
For dayIndex As Integer = 0 To days.LastIndex
  If days(dayIndex) = "Today" Then
    days(dayIndex) = "Tomorrow"
  End If
Next

The above code can also be written using the For...Each statement:

Var days() As String = Array("May 1", "Yesterday", "Today", "Next week")
For Each day As String In days
  If day = "Today" Then
    Var dayIndex As Integer = days.IndexOf(day)
    days(dayIndex) = "Tomorrow"
  End If
Next

Compatibility

All project types on all supported operating systems.

See also

Continue, Do...Loop, Exit, For...Each, While...Wend statements.