On Error 在第一个实例中起作用,在第二个实例中不起作用。漏洞?

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

我这里有一个很奇怪的问题。这是代码:

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

我希望它足够清楚它正在尝试做什么(至少 programming-wise)。我有多个 ContentControls(CCs) 具有相同的标题和标签。我最终遇到的问题标有 CAN'T GET OUT,因为,您猜对了 - 我无法退出第二个循环!我以 Out of range error 结束,因为它 运行 来自 CCs.

更奇怪的是,它确实跳出了第一个循环,该循环具有完全相同的 On Error 语句,被认为指向不同的部分。 是我,还是我只是 - 尽管不太可能 - 运行 到 VBA 中的错误? 无论如何,是否有解决方案或至少有解决方法?

因此,如果您已阅读我的评论并正式回答您的问题,那么这不是错误。
您只需要正确使用 Error Handling Routines 即可。
你想要做的是有点像下面。 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"

但是正如 link 所建议的那样,您需要处理错误而不是简单地忽略它们。
尝试检查实际错误并找到纠正或避免错误的方法。
您会惊讶地发现您甚至不需要 Error Handling Routine.

通常,您仅使用错误处理来处理意外或不可预测的情况,例如无法访问驱动器,或发现您无法访问网络。

错误处理不能替代合理的检查,否则可以通过其他方式进行。即集合有一个 Count 属性 ,你可以在遍历它们的项目时使用它,这样可以避免在只有 n 个项目时尝试访问 Item(n+1) 引起的任何错误(这里你 Count 知道 n)。或者,使用 For Each 循环。

下面是一些示例代码,演示了如何使用两种方法循环您的控件:

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

这种类型的流量控制就是为这种场景设计的。

应用于您的原始代码:

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