Consulting

Results 1 to 12 of 12

Thread: Exiting Top Level For Each from nested For Each

  1. #1
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,340
    Location

    Exiting Top Level For Each from nested For Each

    I should probably know better, but I asked anyway. What is the recommended method of eixting a top levef For Each loop when a condition is met in a nested For Each loop:

    [VBA]Sub ScratchMacro()
    Dim i As Long
    Dim j As Long
    Dim k As Long
    Dim l As Long
    Dim m As Long
    i = 0
    For j = 1 To 10
    For k = 1 To 10
    For l = 1 To 10
    For m = 1 To 10
    i = i + 1
    If i = 1000 Then Exit For 'I want to exit "all" For loops.
    Next m
    Next l
    Next k
    Next j
    MsgBox i
    End Sub[/VBA]

    Thanks.
    Greg

    Visit my website: http://gregmaxey.com

  2. #2
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    Logically, an Exit instruction it is either:

    A) the immediately loop

    OR

    B) everything, i.e. the Sub.[vba]
    Sub ScratchMacro()
    Dim i As Long
    Dim j As Long
    Dim k As Long
    Dim l As Long
    Dim m As Long
    i = 0
    For j = 1 To 10
    For k = 1 To 10
    For l = 1 To 10
    For m = 1 To 10
    i = i + 1
    If i = 1000 Then
    MsgBox i
    'I want to exit "all" For loops.
    Exit Sub
    End If

    Next m
    Next l
    Next k
    Next j
    MsgBox i
    End Sub[/vba]

  3. #3
    Knowledge Base Approver VBAX Guru macropod's Avatar
    Joined
    Jul 2008
    Posts
    4,435
    Location
    Hi Greg,

    I'm sure you know this:
    [vba]Sub ScratchMacro()
    Dim i As Long, j As Long, k As Long, l As Long, m As Long
    i = 0
    For j = 1 To 10
    For k = 1 To 10
    For l = 1 To 10
    For m = 1 To 10
    i = i + 1
    If i = 1000 Then Goto Done
    Next m
    Next l
    Next k
    Next j
    Done:
    MsgBox i
    End Sub[/vba]
    Cheers
    Paul Edstein
    [Fmr MS MVP - Word]

  4. #4
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,340
    Location
    Paul,

    Ten years or so ago when I first began cobbling together elementary procedures some nasty, but good, VBA coder blasted me for using GoTo in my code (except Error Handling). I can honestly say to this day that I don't know why, but it was one of those things that stuck, so I have pretty much applid it as gospel and don't even think about it in case like this.

    Considering what I had done shown below, maybe it isn't so bad after all:
    [VBA] bFound = False
    For Each rngStory In ActiveDocument.StoryRanges
    'Iterate through all linked stories
    Select Case rngStory.StoryType
    Case 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
    Do
    For Each oCurrentCC In rngStory.ContentControls
    If Selection.Range.InRange(oCurrentCC.Range) Then
    bFound = True
    Exit For
    End If
    Next oCurrentCC
    If bFound = True Then Exit Do
    'Get next linked story (if any)
    Set rngStory = rngStory.NextStoryRange
    Loop Until rngStory Is Nothing
    Case Else
    End Select
    If bFound = True Then Exit For
    Next rngStory
    [/VBA]

    I'll be interested in seeing who else comes out for and against using GoTo
    Greg

    Visit my website: http://gregmaxey.com

  5. #5
    Knowledge Base Approver VBAX Guru macropod's Avatar
    Joined
    Jul 2008
    Posts
    4,435
    Location
    Hi Greg,

    I think the aversion to Goto is a hang-over from the old GWBASIC days, when well-structured code was well-nigh impossible and Goto statements littered the code. The stuff was almost unreadable (great for code obfuscation, though). As you've observed, Goto statements are often used in VBA as part of an error-handling routine - you could think of the example I posted as being a way to handle a deliberate 'error'.

    PS: With your Case statement, why not:
    Case 1 to 11
    Cheers
    Paul Edstein
    [Fmr MS MVP - Word]

  6. #6
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,340
    Location
    Case 1 To 11

    Just another tree in a forest that I didn't see.. Thanks.
    Greg

    Visit my website: http://gregmaxey.com

  7. #7
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    I was going to mention using a final GoTo as an alternative. It is quite legitimate.

  8. #8
    VBAX Sage
    Joined
    Apr 2007
    Location
    United States
    Posts
    8,728
    Location
    Using the Err object

    [vba]
    Option Explicit
    Sub ScratchMacro()
    Dim i As Long
    Dim j As Long
    Dim k As Long
    Dim l As Long
    Dim m As Long
    i = 0

    On Error GoTo LastOne

    For j = 1 To 1000
    For k = 1 To 1000
    For l = 1 To 1000
    For m = 1 To 1000
    i = i + 1
    If i = 1000 Then Call Err.Raise(vbObjectError + 1000, "ScratchMacro", "Got to 1000")
    Next m
    Next l
    Next k
    Next j

    Exit Sub

    LastOne:
    If Err.Number = vbObjectError + 1000 Then
    MsgBox "Got to 1000 --- " & i
    Call Err.Clear
    Exit Sub
    Else
    Resume Next
    End If

    End Sub
    [/vba]

    Paul

  9. #9
    Microsoft Word MVP 2003-2009 VBAX Guru gmaxey's Avatar
    Joined
    Sep 2005
    Posts
    3,340
    Location
    Paul,

    Thanks. I have used Err.Raise in a different manner and certainly agree taht it could be used here as you have show. However, in view of Paul and Fumei's beliefs that GoTo itself isn't so back this now looks like over kill. Would you agree?
    Greg

    Visit my website: http://gregmaxey.com

  10. #10
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    IMO, there is nothing wrong with using GoTo at all. In well structured/written code it is simply a redirection.

  11. #11
    VBAX Sage
    Joined
    Apr 2007
    Location
    United States
    Posts
    8,728
    Location
    Greg -- I agree with Gerry about a well used GoTo (at least I'll agree for the next 240 hours )

    Personal Opinion:

    Your intended usage is most likely low risk, since

    1. there is only one statement that GoesTo it; multiple statements that GoTo it could be a maintenance/debug issue.

    2. The proximity of the destimation is 'close' to the jump statement in the code; GoTo-ing a location several screens away could be confusing

    3. I had thought about a Do While construct, but decided that it was more confusing and that the reason for a GoTo would be clearest a year from now when you came back to the code

    Paul

  12. #12
    VBAX Wizard
    Joined
    May 2004
    Posts
    6,713
    Location
    I wholeheartedly agree with all of Paul's points, especially #1 and #2. My own personal opinion is that if the GoTo instructions are more than 20 lines from the pointer it may - but may not - be a good idea to look at further redirection via formal subroutine.

    Of course the main issue with THAT is that you may have to pass parameters (objects or variables) to those subroutines. Which of course brings in Scope.

    However, IMO, the advantages of easily readable and debug-able (is that a word?) code far far outweigh any disadvantages. Besides, it is excellent practice in writing object-oriented code.

    Also, I tend to avoid any procedures greater than 60 lines of instruction. Sure the overall set of instructions can be many times that, but unless you are really good at writing code (and ALWAYS comment things...), it is better to make procedures in testable chunks.

Posting Permissions

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