# Thread: [RESOLVED] Exiting a Nested For/Next Loop

1. ## [RESOLVED] Exiting a Nested For/Next Loop

Hello,

What is the proper way to exit a nested For/Next loop.

I have code in Command1_Click below that works with a GoTo statement.

I want to get rid of the GoTo, so I re-coded in Command2_Click

My use of j = 10 seems like a kludge to me,
and I was wondering if there is a another (more accepted) way to do this?

Code:
```Private Sub Command1_Click()

For i = 1 To 10
For j = 1 To 10
For k = 1 To 10
If k = 3 Then GoTo 100
Next k
Next j
100:
MsgBox "@ 100 when i = " & i

Next i

End Sub```
Code:
```Private Sub Command2_Click()

For i = 1 To 10
For j = 1 To 10
For k = 1 To 10
'If k = 3 Then GoTo 100
If k = 3 Then
MsgBox "@ 100 when i = " & i
j = 10
Exit For
End If
Next k
Next j
100:
'MsgBox "@ 100 when i = " & i

Next i

End Sub```

2. ## Re: Exiting a Nested For/Next Loop

So you actually want to jump two "For"-Levels out.
It boils down to the age old "Flamewar" about the missing "Continue"-Statemtn which has been discussed to death here in the forum
Code:
```Private Sub Command2_Click()

For i = 1 To 10
For j = 1 To 10
For k = 1 To 10
'If k = 3 Then GoTo 100
If k = 3 Then
MsgBox "@ 100 when i = " & i
'Don't manipulate a For-Variable inside the loop!
Exit For
End If
Next k
If k=3 then Exit For
Next j
'MsgBox "@ 100 when i = " & i

Next i

End Sub```

3. ## Re: Exiting a Nested For/Next Loop

now the question,
with goto your jump to a specific position, while exit for will only break the current for, meaning you need to exit for more than one and make multiple if's

I would pick goto.

4. ## Re: Exiting a Nested For/Next Loop

OK thanks.

Just a question as to why Don't manipulate a For-Variable inside the loop! ?

5. ## Re: Exiting a Nested For/Next Loop

Because it's bad practice, prone to buggers....errrr... bugs, and if you're not careful, your software is going to cause a nuclear launch in North Korea....

6. ## Re: Exiting a Nested For/Next Loop

You could also use Do..While loops and test your J & K variables to break out early. It has some annoyances like needing to increment and reset your J & K variable manually, but the advantage is that the conditions for breaking the loop need to be mentally understood only at the Do..While line instead of inside the loop.

Something like this:

Code:
```Public Sub Test()
Dim i As Long
Dim j As Long
Dim k As Long

For i = 1 To 10: j = 0: k = 0  ' Reset J & K
Do While k <> 3 And j <> 10: j = j + 1
Do While k <> 3: k = k + 1

Loop
Loop
Next i
End Sub```
If you don' like the double-test for k=3, then you can get rid it by adding a "breakloop" boolean variable that is set to True when k=3 and then reset that on each "i" loop. e.g.:

Code:
```Public Sub Test()
Dim i As Long
Dim j As Long
Dim k As Long

For i = 1 To 10: breakloop = False: j = 0: k = 0  ' Reset Loop Test Variables
Do While Not breakloop: j = j + 1
breakloop = (j >= 10)

Do While not breakloop: k = k + 1
breakloop = (k = 3)
Loop
Loop
Next i
End Sub```
Loop results with the above match your original loop:

Code:
```ORIG	NEW
LOOPS	LOOPS
I:1	I:1
J:1	J:1
K:1	K:1
K:2	K:2
K:3	K:3
I:2	I:2
J:1	J:1
K:1	K:1
K:2	K:2
K:3	K:3
I:3	I:3
J:1	J:1
K:1	K:1
K:2	K:2
K:3	K:3
I:4	I:4
J:1	J:1
K:1	K:1
K:2	K:2
K:3	K:3
I:5	I:5
J:1	J:1
K:1	K:1
K:2	K:2
K:3	K:3
I:6	I:6
J:1	J:1
K:1	K:1
K:2	K:2
K:3	K:3
I:7	I:7
J:1	J:1
K:1	K:1
K:2	K:2
K:3	K:3
I:8	I:8
J:1	J:1
K:1	K:1
K:2	K:2
K:3	K:3
I:9	I:9
J:1	J:1
K:1	K:1
K:2	K:2
K:3	K:3
I:10	I:10
J:1	J:1
K:1	K:1
K:2	K:2
K:3	K:3```

7. ## Re: Exiting a Nested For/Next Loop

OK thanks all

I used the suggestion of using a Boolean

Below code gets rid of GoTo and gets rid of manipulating For... Next variables inside the loop
Code:
```Private Sub Command1_Click()

For i = 1 To 10

Dim bConditionMet As Boolean
bConditionMet = False

For j = 1 To 10

For k = 1 To 10
If k = 3 Then
bConditionMet = True
Exit For
End If
Next k

MsgBox "@ old Goto 100 when i = " & i & " and k = " & k
If bConditionMet = True Then Exit For

Next j

Next i

End Sub```

8. ## Re: Exiting a Nested For/Next Loop

If there isn't any natural way to do the exiting then use a GoTo and be done with it. Even Exit For is just a prettied up GoTo after all.

9. ## Re: Exiting a Nested For/Next Loop

Sorry for the spam but I felt I needed to post this:

10. ## Re: Exiting a Nested For/Next Loop

exactly what dilettante wrote.
I think adding more variables is worse than using GoTo.
maybe its not pretty, but I think its easy to understand. GoTo is a very old command and I used it a lot back with commodore 64, later in Amos, and later in pascal.

and what is that makes it hard to understand a GoTo?
I think multiple if conditions are more complicated and it looks kludged for me.

11. ## Re: Exiting a Nested For/Next Loop

If there isn't any natural way to do the exiting then use a GoTo and be done with it. Even Exit For is just a prettied up GoTo after all.
and what is that makes it hard to understand a GoTo?
I think multiple if conditions are more complicated and it looks kludged for me.
I agree 100%
I guess because I've read so many times don't use it I feel compelled to get rid of them

kfcSmitty

Thanks all, for help and advice.

12. ## Re: [RESOLVED] Exiting a Nested For/Next Loop

yeah, I think the problem with GoTo is if we use it all the time, but not one time in a specific situation.

Code:
```If Number = 1 Then GoTo Line1 Else GoTo Line2
Line1:
MyString = "Number equals 1"
GoTo LastLine
Line2:
MyString = "Number equals 2"
LastLine:```
the warning is: Too many GoTo statements can make code difficult to read and debug. from docs.microsoft.com

but your code is using it 1 time only. so its ok.

13. ## Re: [RESOLVED] Exiting a Nested For/Next Loop

TBH once we're getting 3 or more loops deep, I'd start looking at moving things out to separate subs/functions with descriptive names so the code almost becomes self documenting. Something like this:

Code:
```Public Sub Test()
Dim i As Long

For i = 1 To 10
ProcessJK i
Next i
End Sub

Private Sub ProcessJK(ByVal i As Long)  ' Give this sub a descriptive name
Dim j As Long
Dim k As Long

For j = 1 To 10
For k = 1 To 10
If k = 3 Then Exit Sub   ' Short-circuit
Next k
Next j
End Sub```

14. ## Re: [RESOLVED] Exiting a Nested For/Next Loop

When I've had nested for loops that I needed to escape the outer loop I've just set the outer loop variable beyond the limit of the to statement.
Code:
```Private Sub Command1_Click()

For i = 1 To 10
For j = 1 To 10
For k = 1 To 10
If k = 3 Then
j = 11 ' Set to exit j loop
Exit For
End If
Next k
Next j
MsgBox "@ 100 when i = " & i
Next i

End Sub```

15. ## Re: [RESOLVED] Exiting a Nested For/Next Loop

@MarkT: This works but it's usually the code after Next k that must be skipped too.
Code:
```Private Sub Command1_Click()

For i = 1 To 10
For j = 1 To 10
For k = 1 To 10
If k = 3 Then
j = 11 ' Set to exit j loop
Exit For
End If
Next k
'--- here is code that needs to be skipped
Next j
MsgBox "@ 100 when i = " & i
Next i
SkipLoop:
'--- more interesting code here
End Sub```
I'll GoTo SkipLoop with no remorses here. After years of experience I'm not afraid of using GoTo at exactly 3 or 4 particular code patterns. Breaking out of nested loops is one of these. Repeating/retrying an operation is another one, for instance GoTo RepeatSend feels natural when dealing with external systems. The simple GoTo Cleanup for error handling is the most used one -- a.k.a. the C-style error handling.

cheers,
</wqw>

16. ## Re: [RESOLVED] Exiting a Nested For/Next Loop

In the OP there was no code that needed to be skipped after the k loop.

17. ## Re: [RESOLVED] Exiting a Nested For/Next Loop

Personally, I see four approaches to doing this, three that I might use, and one I'd never use. And some (maybe all) of these are mentioned above.

1. Use an "execute once" Do Loop, making sure no other Do Loops are used down in the nesting, and then make sure that Do Loop has an Exit do as the last statement...

Code:
```
Do

' Have as many nested For Next loops as you like,
' And execute an "Exit Do" when you want out.

Exit Do
Loop

```

2. Create a flag, maybe something like "Dim bKeepGoing As Boolean". And, just before each "Next" statement, check the flag, and, if it's false then execute "Exit Do".

Code:
```
Dim i As Long, j As Long, k As Long
Dim bKeepGoing As Boolean

bKeepGoing = True
For i = 0 To 9
For j = 0 To 9
For k = 0 To 9

' Do work, maybe setting bKeepGoing to False.

If Not bKeepGoing Then Exit For
Next
If Not bKeepGoing Then Exit For
Next
If Not bKeepGoing Then Exit For
Next

```
This approach has the advantage that you could actually have multiple "bKeepGoing" flags that broke the nesting at different levels.

3. With a good understanding of how For Next loops work, you could tamper with your index variables, making subsequent loops terminate. This is quite easy if all of your Step sizes are 1. If you have different Step sizes, this approach can get a bit messy. Here's a straightforward example.

Code:
```
Dim i As Long, j As Long, k As Long

For i = 0 To 9
For j = 0 To 9
For k = 0 To 9

' Do work, maybe setting bKeepGoing to False.
If WeWantToTerminate Then
k = 10
j = 10
i = 10
End If

Next
Next
Next

```
Some may frown on this approach, but I've never seen a language that didn't work in a well behaved way regarding these For Next indexes. They just do the increment (or possibly decriment), hit the Next statement, and check to see if it's over the criterion, and, if so, they exit. The index is always one increment beyond the criterion. For instance, in the following loop, when it's done, i = 10.

Code:
```
Dim i As Long

For i = 0 To 9
'
Next

```

4. Lastly, I might consider a GoTo. However, there's only one place I actually allow myself to use a GoTo, and that's when a procedure initializes some stuff that needs to be cleaned up. A good example is possibly opening a bunch of RecordSets, that must be closed when we're done. This procedure may have several "escapes". In this case, if I hit one of the "escapes", I'll allow myself a GoTo to jump to the bottom and execute the cleanup.

I personally don't allow myself to use Gotos in any other circumstance.

18. ## Re: [RESOLVED] Exiting a Nested For/Next Loop

I see little advantage in tying your code in knots just to satisfy an artificial principle. Sure, it is easy to fall into the trap of using GoTo as a crutch, and when an obvious alternative exists it should generally be used instead.

Relying on tricks and subtle side-effects just makes code harder to maintain in the long term as well as impeding portability if you ever need to port to another language.

That the loop control variable is incremented past the limit value in a For...Next should be considered well known and reliable in VB6, but I wouldn't expect any arbitrary language to act the same.

I don't see any obvious "winner" among the options, but the simple GoTo has advantages in performance and readability.

19. ## Re: [RESOLVED] Exiting a Nested For/Next Loop

I use GoTo a bit,
when "retrying" something, could be an API or I need to
example:
Code:
```Private Sub FigureOutPage(txt As TextSubDataType, ByVal Pos%, ByRef Page%)
With txt
If Pos >= UBound(.a) Then Exit Sub
retry:
If (Pos + 1) < .Page(Page).begin Then Page = Page - 1: GoTo retry
If (Pos + 1) > .Page(Page).end Then Page = Page + 1: GoTo retry
End With
End Sub```
instead of calling the the function recursively, or use do/while/loops.

also used when I analyze something, could be a complex data structure with multiple condition checks,
but if one check is enough to determine something, I "jump" ahead to the next phase.
exampe:
Code:
```            For i = 1 To sum
If data(i).sub.Item = Item Then first = True: GoTo foundAndNext
For j = 1 To data(i).nxts
If data(i).nxt(j) = Item Then first = True: GoTo foundAndNext
Next j
For j = 1 To data(i).tras
If data(i).tra(j) = Item Then first = True: GoTo foundAndNext
Next j
foundAndNext:
If first Then .Count = .Count + 1: ReDim Preserve .Nm(1 To .Count): .Nm(.Count).Id = i: .Nm(.Count).Name = data(i).name: first = False
Next i```
sure theres multiple ways to do this, but this one is good enough and GoTo is easy to understand.

not sure why people don't like GoTo and try to avoid it as much possible when its easy to use.
its like Assembly Jump command.

20. ## Re: [RESOLVED] Exiting a Nested For/Next Loop

If one limits GoTo usage to 2-3 well established patterns that are well understood by themselves or their team I see no harm reaping the performance and maintenance gains.

Here are some 3 cases that might be good candidates for a GoTo in no particular order:
1. C-Style cleanup
2. Early exit from nested loops
3. Repeating a failing operation

cheers,
</wqw>

21. ## Re: [RESOLVED] Exiting a Nested For/Next Loop

Here is an option, one that I've not used but this thread made me think of it so I'll throw it out there
Code:
```Option Explicit

Private Sub Command1_Click()
Dim i As Integer, j As Integer, k As Integer
For i = 1 To 10
Do
For j = 1 To 10
For k = 1 To 10
If k = 3 Then Exit Do
Next k
Next j
Loop While k = 0
MsgBox "@ 100 when i = " & i

Next i

End Sub```
The code above would effectively do the same thing as your code that has the goto in it
Of course in your sample loop the J loop doesn't really do anything so no reason for it to even be there as the next j statement will never execute.

#### Posting Permissions

• You may not post new threads
• You may not post replies
• You may not post attachments
• You may not edit your posts
•

Featured