blackwind
blackwind

Reputation: 111

On Error works in first and doesn't work in second instance. Bug?

I have a very strange problem here. Here's the code:

reqLang = "ENG"
    Select Case reqLang
        Case "CRO", "ENG"
            'first loop -------------------------------------
            On Error GoTo reqLangVisible
            i = 1
            'Loop until ccCROENG's are all hidden and then go to reqLangVisible.
            Do
                ActiveDocument.SelectContentControlsByTag("ccCROENG")(i) _
                    .Range.Font.Hidden = True 'hides all CCs
                i = i + 1
            Loop
reqLangVisible:
            'second loop -------------------------------------
            On Error GoTo langOut
            i = 1
            'Loop until ccreqLang's are all visible and then go to langOut.
            Do
                ActiveDocument.SelectContentControlsByTitle("cc" & reqLang)(i) _
                    .Range.Font.Hidden = False 'activates reqLang CCs
                i = i + 1
            Loop ' CAN'T GET OUT -----------------------------------
        Case "CROENG"
            i = 1
            'Loop until ccCROENG's are all visible and then go to langOut.
            Do
                On Error GoTo langOut
                    ActiveDocument.SelectContentControlsByTag("ccCROENG")(i) _
                        .Range.Font.Hidden = False 'Shows all CCs
                i = i + 1
            Loop
    End Select
langOut:
MsgBox "Success!" '------- yeah, not really.
Stop

I hope it's clear enough what it's trying to do (at least programming-wise). I have multiple ContentControls(CCs) with same titles and tags. The problem I end up with is marked with CAN'T GET OUT, because, you guessed it - I can't get of this second loop! I end up with the Out of range error because it runs out of CCs.

What's even weirder is that it actually did get out of the first loop which has the exact same On Error statement, thought pointing to a different section. Is it me, or did I just - however unlikely - run onto a bug in VBA? In any case, is there a solution or at least a workaround?

Upvotes: 0

Views: 469

Answers (2)

Tim Williams
Tim Williams

Reputation: 166755

Typically you only use error handling for dealing with unexpected or unpredictable situations, such as not being able to access a drive, or finding you have no network access.

Error handling is not intended as a substitute for reasonable checks which could otherwise be done. i.e. collections have a Count property which you can use when looping over their items, so avoiding any error caused by trying to access Item(n+1) when there are only n items (and here you know n from Count). Alternatively, use a For Each loop.

Here's some sample code demonstrating use of two methods for looping over your controls:

Sub Tester()

    Dim cc1 As ContentControls, cc2 As ContentControls
    Dim c, i As Long

    With ActiveDocument
        Set cc1 = .SelectContentControlsByTag("tbTag")
        Set cc2 = .SelectContentControlsByTitle("tbTitle")
    End With

    Debug.Print "cc1 has " & cc1.Count
    Debug.Print "cc2 has " & cc2.Count

    'use the Count property
    For i = 1 To cc1.Count
        Set c = cc1(i)
        c.Range.Font.Hidden = True
    Next i

    'use a For Each loop
    For Each c In cc2
        c.Range.Font.Hidden = False
    Next c

End Sub

This is the type of scenario for which this type of flow control is designed.

Applied to your original code:

Sub Tester2()
    Dim reqLang, cc As ContentControls, c

    reqLang = "ENG"

    Select Case reqLang

        Case "CRO", "ENG"

            Set cc = ActiveDocument.SelectContentControlsByTag("ccCROENG")
            SetTextHidden cc, True

            Set cc = ActiveDocument.SelectContentControlsByTitle("cc" & reqLang)
            SetTextHidden cc, False

        Case "CROENG"

            Set cc = ActiveDocument.SelectContentControlsByTag("ccCROENG")
            SetTextHidden cc, False

    End Select

    MsgBox "Success!" '-- yeah really

End Sub

Sub SetTextHidden(cc As ContentControls, MakeHidden As Boolean)
    Dim c
    For Each c In cc
        c.Range.Font.Hidden = MakeHidden
    Next c
End Sub

Upvotes: 1

L42
L42

Reputation: 19737

So if you've read my comment, and to formally answer your question, it is not a bug.
You just need to use Error Handling Routines correctly.
What you're trying to do is somewhat like below. HTH.

Select Case reqlang

Case "CRO", "ENG"
    On Error Resume Next '~~> ignores the error when encountered
    '~~> Your loop which possibly creates the error goes here
    On Error Goto 0 '~~> resets the actively triggered error handling

Case "CROENG"
    On Error Resume Next '~~> ignores the error when encountered
    '~~> Your loop which possibly creates the error goes here
    On Error Goto 0 '~~> resets the actively triggered error handling

End Select

MsgBox "Success"

But as the link suggest, you need to handle errors and not simply disregard them.
Try cheking on the actual error and find a way to correct it or avoid it.
You'll be surprise that you won't even be needing the Error Handling Routine.

Upvotes: 0

Related Questions