如何像 Try/Catch 一样内联错误处理块

How to do an error handling block inline like Try/Catch

如何在 VBA 中执行内联错误处理例程?我不想把错误处理程序放在最后。

本文来自CPearson's Error Handling in VBA

Sub testErrHandling()
    On Error GoTo ErrHandler:

    Debug.print 9 / 0 'divide by zero error

    Worksheets("NewSheet").Activate 'missing worksheet error

    'more code here

    Exit Sub

ErrHandler:
    If Err.Number = 9 Then
        ' sheet does not exist, so create it
        Worksheets.Add.Name = "NewSheet"
        ' go back to the line of code that caused the problem
        Resume
    End If
End Sub

但我在 VB.net

中寻找更像 Try/Catch 块的东西

此代码将内联处理错误。这是用于处理错误的结构非常清晰的模式。流从上到下非常干净;这里没有意大利面条代码。

VBA 是一种古老的语言并且有局限性。使用错误处理的方法之一是使用 On Error Goto <Label>Resume <Label> 形式的 Goto 语句。这就创造了机会。

传统上错误处理程序放在底部。但是随着 VB.net 中取得的进步,利用想法来改进代码似乎是合理的。 Try/Catch 是一种非常结构化的错误处理方式,非常容易遵循。这种模式试图以一种非常简洁的方式重现它。流程非常一致,不会从一个地方跳到另一个地方。

Sub InLineErrorHandling()

    'code without error handling

BeginTry1:

    'activate inline error handler
    On Error GoTo ErrHandler1

    'code block that may result in an error
    Dim a As String: a = "Abc"
    Dim c As Integer: c = a 'type mismatch

ErrHandler1:

    'handle the error
    If Err.Number <> 0 Then

        'the error handler is now active
        Debug.Print (Err.Description)

    End If

    'disable previous error handler (VERY IMPORTANT)
    On Error GoTo 0
    'exit the error handler
    Resume EndTry1

EndTry1:

    'more code with or without error handling

End Sub

来源:

管理得当,效果很好。这是一个非常干净的流动模式,可以在任何需要的地方重现。

您可以尝试在变量中分配您的对象,然后改用 On Error Resume Next

Dim sh As Worksheet

'This is essentially the "Try" part
On Error Resume Next 'this ignores the error
Set sh = Worksheets("NewSheet")
On Error Goto 0 'this resets the active error handling routine

'Then this is the "Catch" part I guess
If sh Is Nothing Then 'check is something is assigned to sh
    'And I think this is "Finally" part
    Set sh = Worksheets.Add: sh.Name = "NewSheet" 'add otherwise
End If

不太熟悉 Try/Catch 因为我没有做过一些 VB.Net 但这是我能想到的最接近你的例子的内联纠错。 HTH.

经过几个月 insecurity/confusion 关于 VBA 错误处理的一些晦涩法则,对任何流行的文档页面(Microsoft VBA/VB、C. Pearson 和其他人)从未完全满意), 我用了几天的反复试验来重建
完整的集 的(书面和 unwritten/corrected) 规则 VBA错误处理:

图例:
1A:错误转到 0。1B:错误转到 line/label1C: 错误继续下一步
2A:出现错误。 2B: 错误转到 -1
3: 暂时处于子过程中,直到回来
4: 厄尔
5:恢复 […]
6:退出[…],结束[…]

规则

  • 随着 1A 生效*,错误处理将保持 禁用 不活动 。这是默认设置。
  • 随着 1B 生效*,错误处理最初是 禁用 不活动 ;它在 2Aactivatedinactivated356,并且 disabled while 3 and通过 2A6.
  • 随着 1C 生效*,错误处理最初是 禁用 不活动 ;它保持 inactive(据说 activatedinactivated 立即 2A), disabled while 3 and by 6.
  • *= 如果 1A1B1C 在错误处理为 active,Err 对象被立即清除,但是 On Error 动作改变效果被延迟直到错误处理被inactivated(通过 56)。
  • 2B(瞬间)逆转了2A的效果:错误处理是inactivated并且returns(1B)/停留(1C) 启用.
  • 1A, 1B, 1C, 2B, 5, 6 也瞬间清除 Err对象。
  • 如果在子过程中发生错误,如果在当前子过程中未处理(禁用),它将传递给第一个调用(父)过程启用 不活动。如果没有找到,它会留在那里(在子过程中)。
  • 4 如果错误处理是 active returns line(如果指定为最后一个错误的数字标签),否则为 0。
  • 5(正确地)如果在错误处理 不活动 时调用会崩溃(错误 21:“无错误继续”)。

牢记所有这些规则,并从此处发布的 开始,这是我修改后的解决方案,更正了他的代码中的几个 errors/inefficiences:

    Sub InLineErrorHandling()
    
        'code without error handling

        On Error GoTo ErrHandler1  'enable error handler
        'code block that may result in an error
        Dim a As String: a = "Abc"
        Dim c As Integer: c = a 'type mismatch

        'inline error handler routine
    ErrHandler1:
        If Err.Number <> 0 Then
            Debug.Print err.Description
            On Error GoTo -1 ' inactivate error handler
        End If        
        On Error GoTo 0 'disable error handler
        
        'more code without error handling  (default mode)
        Err.Raise 123
    
    End Sub

...如果错误处理例程中没有错误,可以进一步减少到这个(非常标准的)替代方案:

    Sub InLineErrorHandling()
    
        'code without error handling

        On Error Resume Next  'enable error handler        
        'code block that may result in an error
        Dim a As String: a = "Abc"
        Dim c As Integer: c = a 'type mismatch
    
        'inline error handler routine
        If Err.Number <> 0 Then
            Debug.Print err.Description
        End If
        On Error GoTo 0 'disable error handler
        
        'more code without error handling  (default mode)
        err.Raise 123
    
    End Sub

另外值得一提的是,在两个选项中,如果我们还想知道“代码块”的哪一行(第一个为1B,最后一个为1C)可能result in an error”导致错误,我们可以使用Erl函数,像这样:

                 ...
            'code block that may result in an error
    10      Dim a As String: a = "Abc"
    20      Dim c As Integer: c = a 'type mismatch

            'inline error handler routine
            If Err.Number <> 0 Then
                Debug.Print "Error """ & err.Description & """ in line " & Err
                 ...