【问题标题】:Even without an Error, the code for "Line3:" still gets run on On Error GoTo Line3 [duplicate]即使没有错误,“Line3:”的代码仍然会在 On Error GoTo Line3 上运行 [重复]
【发布时间】:2022-01-02 19:53:57
【问题描述】:

示例代码:

On Error GoTo Line3

More code

Line3:
    Some code
    Some code

More code

即使出现 no 错误,Line3 下的“某些代码”仍会运行,即使我不希望它运行。否则,当出现错误时,Line3 会正确运行(跳过之前的代码)。

【问题讨论】:

  • Goto 是一个“哑”动词。除非另一个 goto 将执行发送到其他地方,否则它将一直执行到过程或函数的末尾。您可能会考虑将 Line3: 移动到源文件的末尾,并确保没有其他 goto 到那里。或者只是从 Line3 之前的程序返回。这将确保该标签下的代码不会运行。
  • 一个正确的答案将取决于这些线代表什么。你为什么不发布一个实际的例子,从SubEnd Sub(或Function),你需要在哪里应用这个?

标签: excel vba error-handling try-catch


【解决方案1】:

您的代码运行正常。处理错误的代码应该写在主过程之外,记住你的代码也应该尝试发现潜在的错误并在它们导致错误之前处理它们。

目前,当您跳转到它时,您的错误并没有被清除,并且因为它位于代码主体中,所以当您的第一组 More Code 完成并到达 Line3 标签时,它会被执行。

Sub Test1()
    'Ignore the error.
    'MsgBox won't appear, but code won't know an error occured.
    'MsgBox says all's good anyway, even though the error is still present.
    Dim Rng As Range
    On Error GoTo SkipLineWithError
    MsgBox Rng.Address
SkipLineWithError:
    MsgBox "All good, error number is " & Err.Number
End Sub 

更好的方法是在错误发生之前尝试捕获错误:

Sub Test2()

    'Checks that Rng won't throw an error if referenced.
    'Code has dealt with the error and says all's good.
    Dim Rng As Range
    If Not Rng Is Nothing Then
        MsgBox Rng.Address
    Else
        MsgBox "Range not set"
    End If
    MsgBox "All good, error number is " & Err.Number

End Sub

虽然有时确实会发生错误,但需要妥善处理。为此,您跳出主程序,处理错误并再次跳回。
使用此代码注意 Exit Sub - Exit SubEnd Sub 之间的代码是您的错误处理所在。代码主体在到达Exit Sub 时结束。
Resume 告诉您的代码跳回哪里 - 它自己跳回导致错误的行,Resume Next 是后面的行错误,Resume <label> 跳转回您输入的标签,例如Resume Line3

Sub Test3()
    Dim Rng As Range

    On Error GoTo ErrorHandler
    MsgBox Rng.Address
    MsgBox "All good, error number is " & Err.Number
    
TidyExit:
    'Close connections, general tidy up before ending procedure.
    
Exit Sub
ErrorHandler:
    Select Case Err.Number
        Case 91 'Deal with the error if it happens.
                'For this we'll give Rng a default address.
            Set Rng = Sheet1.Range("A1")
            Resume
        Case Else
            MsgBox "Error couldn't be handled... display an error message."
            Resume TidyExit 'Jump to end of main body of code.
    End Select

End Sub

编辑:根据@VBasic2008 的评论更新了代码。我的第一个代码很懒惰,错过了一个关键点。

我在这里几乎没有刮过表面,下面的链接应该会有所帮助。
on-error-statement
vba-error-handling

【讨论】:

  • 这是一个很酷但很棘手的例子。 Resume 有点“可怕”,即如果您将 91 更改为另一个数字,您将陷入无限循环,因为 Case Else 处理不当。也许指向另一个标签,例如ProcExit: 就在Exit Sub 的上方,并在MsgBox 的下方使用Resume ProcExit 行可以解决问题。
  • 好点@VBasic2008。我没有过多地考虑那方面 - Resume 将执行任何错误。我会更新那段代码。
【解决方案2】:

使用Gotos 管理执行路径几乎总是是一个糟糕的设计选择。您可以考虑以下不太依赖Goto 标签的方法。无需直观地解析任何 Goto 语句即可更轻松地查看预期的逻辑流程(和错误处理)。

Sub Example()
    If Not TryMorecode1() Then
        Somecode1
        Somecode2
    End If

    Morecode2
End Sub

Private Function TryMorecode1() As Boolean
    'catch errors locally within this function
    'return False if an error is generated
End Function

Private Sub Morecode2()
End Sub

Private Sub Somecode1()
End Sub

Private Sub Somecode2()
End Sub

【讨论】:

    【解决方案3】:

    代码仍会运行,它只是一个标签,您可以在需要时将执行指向。

    尝试这样做可以避免您的问题,但在不知道您的确切要求的情况下,您可能需要调整代码结构以满足您的需求。

    我的建议是将 Line3 放在底部,而不是放在程序的中间。这样你只需做一个清理,然后出去。从可读性的角度来看,它往往更有意义。当然,只有在错误发生后退出是有意义的情况下才应该这样做。

        On Error GoTo Line3
    
        More code
    
        Goto Line4
    
    Line3:
        Some code
        Some code
    
    Line4:
         On Error GoTo 0
    
         More code
    

    GoTo 语句的技巧(如果您打算使用它们)是谨慎使用它们。

    【讨论】:

    • 这种代码加一点磨碎的帕尔马干酪最有品味;)
    • 它回答了他的问题,这就是目的。
    猜你喜欢
    • 2015-02-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-10
    • 2021-11-16
    • 1970-01-01
    • 2018-01-10
    • 1970-01-01
    相关资源
    最近更新 更多