错误时恢复旧VBA

时间:2018-01-04 18:55:58

标签: vba onerror

让我们假设你的主要子中有On Error。

Sub Main()

   On Error Goto CatchAll
   '... Some code... goes here
   Call XYZ



CatchAll:
   Msgbox "An Unexpected Error Occurred"
   End
End Sub

在Main子系统中,您可以调用常规XYZ。 让我们说Sub XYZ是这样的:

Sub XYZ()
   'If unexpected error happens here, control will be shifted to sub Main, Label CatchAll

   On Error Goto Errorz

   'If unexpected error happens here, control will be shifted to same sub, Label Errorz...

Errorz:
        Msgbox "You have crashed inside XYZ"
        End

End Sub

请注意在子XYZ中输入的注释。 也就是说,在经历程序崩溃之后控制转换的位置是基于最后一个" On Error Goto"言。

在VBA中,有没有办法恢复旧的On Error Goto?

换句话说,在Sub XYZ中,我有一些代码:

Sub XYZ()
   On Error Goto Errorz:

   'Some Code

   On Error Goto <Old Error Trapping Method>
   'Here I desire to go back to Main CatchAll: label.  Is there a way to do that?

End Sub

请注意上面代码中的最后一条评论。我希望能够在定义新行为之前重新定义On Error以恢复On错误的最后一个行为(Last Behavior:Goto Main.CatchAll label,New behavior,Goto XYZ.Errorz label)。我希望能够在代码的这一点上说,On Error Go to Main.CatchAll。

有没有办法实现这个目标?

3 个答案:

答案 0 :(得分:3)

是的,在XYZ()

On Error Goto 0

应清除当前过程(即XYZ()的)错误处理程序,并在您的示例中将错误处理的控制权传递给Main()中的错误处理程序。

答案 1 :(得分:0)

不确定。如果没有彻底clearing local error handling,您可以有条件地重新抛出处理程序中的错误:

Errorz:
    With Err
        If .Number = SomeSpecificLocalError Then
            ' mitigate error
            Resume Next
        Else
            ' rethrow
            .Raise .Number
        End If
    End With

这样您就可以保留原始错误消息(可选地,您可以为&#34; catch-all&#34;处理程序指定一个source和更具描述性的message以及&# 34;气泡&#34;错误调用堆栈。

让我们来说明与另一种语言的区别:

try
{
    // do stuff
}
catch
{
    // handle error
}

// do more stuff

上面的代码片段基本上是On Error GoTo 0所做的:无论do more stuff中发生什么,如果抛出错误,调用者都需要处理它。

现在比较:

try
{
    // do stuff
    // do more stuff
}
catch(InvalidOperationException e)
{
    // handle invalid operation
}
catch(FileNotFoundException)
{
    throw;
}
catch(Exception)
{
    // handle any other exception
}

此处本地范围将处理InvalidOperationException,但FileNotFoundException将显式重新抛出以供调用代码处理,而任何其他异常将被处理本地。

这两种方法都有利有弊,我只是将其留给后人:如果你愿意的话,可以在VBA中重新抛出运行时错误。

也就是说,在一个程序中需要多个错误处理策略是一种代码味道IMO:你的程序可能会导致太多事情,将其拆分。

答案 2 :(得分:0)

这足以轻松地回到main并进入错误处理程序。

Option Explicit
Private Sub CommandButton1_Click()

On Error GoTo CatchAll

Call XYZ

Exit Sub

CatchAll:
MsgBox "This is Catchall Error Handling"
End Sub

Private Sub XYZ()

'This will purposely throw an error
'ThisWorkbook.Worksheets("Sheet55").Range("A1").Value = 10

On Error GoTo 0
'This will purposely throw an error
ThisWorkbook.Worksheets("Sheet66").Range("A1").Value = 10

MsgBox "You made it to here? Wow!"

End Sub

enter image description here

如果你必须有一个子错误处理程序,当使用rethrow时,下面的答案是正确的,也是有效的,你们这些人很聪明:

Option Explicit
Private Sub CommandButton1_Click()

On Error GoTo CatchAll

Call XYZ

Exit Sub

CatchAll:
MsgBox "This is Catchall Error Handling"
End Sub

Private Sub XYZ()

'This will purposely throw an error
'ThisWorkbook.Worksheets("Sheet55").Range("A1").Value = 10

On Error GoTo Err_XYZ
ThisWorkbook.Worksheets("Sheet66").Range("A1").Value = 10

MsgBox "You made it to here? Wow!"

Exit Sub

Err_XYZ:
With Err
.Raise .Number
End With
End Sub

干杯,-WWC