我没仔细研究过这个问题,但下面链接的作者建议我不要在VBA中使用“冒泡”来集中处理错误。
通过谷歌图书查看Excel编程周末速成课
但我不确定他为什么这样建议,他也没有解释原因。
有人能告诉我为什么我应该在每个过程中都放置错误处理,而不是使用“冒泡”吗?或者至少,你知道作者为什么不建议使用吗?
谢谢。
有人能告诉我为什么我应该在每个过程中都放置错误处理,而不是使用“冒泡”吗?或者至少,你知道作者为什么不建议使用吗?
谢谢。
Sub Caller()
On Error GoTo HANDLER
ChildProc
On Error GoTo 0
Exit Sub
HANDLER:
Debug.Print Error, "Parent cleanup - something happened in either this procedure or a procedure that it called"
End Sub
Sub ChildProc()
Debug.Print 10 / 0 ' causes error
'Don't bother handling errors here since there's nothing this routine can do about them
End Sub
Sub Caller()
On Error GoTo HANDLER
ChildProc
On Error GoTo 0
Exit Sub
HANDLER:
Debug.Print Error, "Parent cleanup"
End Sub
Sub ChildProc()
'Pretend this routine gets ahold of some resource that must be cleaned up when it's done
call get_resources()
On Error GoTo HANDLER
Debug.Print 10 / 0 ' causes error
On Error GoTo 0
'Clean up once we're done
call release_resources()
Exit Sub
HANDLER:
Debug.Print Error, "Child cleanup"
'Clean up in case of an error
call release_resources()
'Raise another error if necessary to let callers know something went wrong
Err.Raise 10000, "ChildProc", Error
End Sub
我个人的建议是: 你应该在所有公共过程和事件中加入错误处理程序。这意味着调用堆栈底部的过程将始终有一个错误处理程序。然后根据需要在其他过程中添加错误处理程序。如果在没有错误处理程序的过程中发生错误,它将“冒泡”到顶层错误处理程序,在那里以专业的方式记录/显示错误。 下面是一个你可能想在私有(较低级别)过程中添加错误处理程序的场景: 代码需要快速执行。你有一种罕见的情况可以避免,但是将强制在循环内执行昂贵的逻辑测试(或更糟糕的是嵌套循环)。 你可以在错误处理程序中执行逻辑测试,并且如果说是“罕见情况”,则进行更正并恢复。由于条件罕见,所以大多数情况下你会看到性能提升。如果错误处理程序无法找出并纠正问题,则重新引发错误以将其向上冒泡到堆栈。
显然,这只是一个场景。
我不确定VBA的默认错误处理方式是什么,但由于它是Visual Basic for Applications,而这些应用程序包括像Excel和Word这样的东西,我认为只会出现一个对用户没有帮助的对话框。
我猜作者曾经因为代码没有处理错误而受到过打击,所以现在建议所有过程都要处理错误。
完整的答案是,您必须意识到可能发生的每个错误,并编写代码来处理它,无论它是尽可能低(您可能不知道该怎么做),还是尽可能高(这意味着编写错误处理代码的工作量较小,但不知道错误发生的原因),或者是战略性的(就是在应该能够从大多数常见错误中恢复的正确位置)或者是无处不在的(这可能只是太多的开发工作)。
最好不要使用错误处理的“冒泡”部分,因为错误应该被处理,如果已知该怎么做,当这样的错误发生时,程序应该知道该怎么做,而不是调用过程。
Sub test()
On Error GoTo e
Dim c As Integer
Dim d As Integer
c = add(5, 0)
d = divideWhichManagedItsOwnErrorHandling(5, 0)
d = divide(5, 0)
Exit Sub
e:
MsgBox "error occurred somewhere for which I don't know what to do: " + Err.Description
End Sub
Function add(a As Integer, b As Integer) As Integer
add = a + b
End Function
Function divide(a As Integer, b As Integer) As Integer
divide = a / b 'if error occurs, it will "bubble-up" to the caller.
End Function
Function divideWhichManagedItsOwnErrorHandling(a As Integer, b As Integer) As Integer
On Error Resume Next
Dim result As Integer
result = a / b
If Err.Number = 11 Then 'if divide by zero occurred, user must have passed 0 for b
result = 0 ' return 0 if the divide by zero occurs.
End If
divideWhichManagedItsOwnErrorHandling = result
End Function