Err.Raise的Rethrow错误

时间:2015-08-18 09:07:26

标签: excel vba exception exception-handling

信息:感谢Gary McGill我可以改进我的问题的源代码。

在我目前的项目中,我有一个处理所有错误的子程序。应该发生以下情况:

  1. Start Sub
  2. 发送电子邮件
  3. 显示默认的Debug-Error窗口(单击&#34时指向原始错误行; Debug")
  4. 这里的要点是找出错误发生在哪一行

    Private Sub Foo()
        On Error GoTo ErrorHandling
        a = 7 / 0
    
        Exit Sub
    ErrorHandling:
            errorNumber = Err.Number
            errorSource = Err.Source
            errorDescription = Err.Description
            errorHelpFile = Err.HelpFile
            errorHelpContext = Err.HelpContext
        On Error GoTo 0
        Call HandleError(errorNumber, errorSource, errorDescription, errorHelpFile, errorHelpContext)
    End Sub
    
    Public Sub HandleError(errorNumber As Integer, errorSource As String, errorDescription As String, errorHelpFile As String, errorHelpContext As String)
        Call SendMail(subject, body, mail)
        Err.Raise errorNumber, errorSource, errorDescription, errorHelpFile, errorHelpContext
    End Sub
    

    但如果我这样做,新创建的错误窗口只指向Err.Raise行,而不是发生错误的实际行。使用插件对行进行编号是没有解决方案的,因为我的公司限制不允许使用插件。

    还有其他可能的解决方案吗?

    修改

    因此,应该突出显示行a = 7 / 0而不是this

    修改2

    可悲的是,这不起作用:

    Private Sub Foo()
        On Error GoTo ErrorHandling
        a = 7 / 0
    
        Exit Sub
        ErrorHandling:
            ...
            Call HandleError(...)
            GoTo 0
    End Sub
    

3 个答案:

答案 0 :(得分:3)

(最初)发布的代码存在一些问题:

  1. On Error Goto 0中的HandleError将清除Err.Number等的值。所有On Error变体都有效地执行Err.Clear。您可以尝试在函数开头保存这些值以供以后使用。
  2. 看起来您对HandleError的调用会引发错误,而错误又会被取消处理,然后再次转到您的ErrorHandling错误处理程序,这只会循环播放?实际上,您可能需要捕获错误处理程序中的各种错误值,然后禁用错误处理程序,然后将它们作为参数传递给HandleError函数。也许是这样的:
  3. Public Sub Foo()
        On Error Goto ErrorHandling
        number = 7/0
        Exit Sub
    ErrorHandling:
        errorNumber = Err.Number
        errorSource = Err.Source
        errorDescription = Err.Description
        errorHelpFile = Err.HelpFile
        errorHelpContext = Err.HelpContext
        On Error Goto 0
        Call HandleError(errorNumber, errorSource, errorDescription, errorHelpFile, errorHelpContext)
    End Sub
    
    Public Sub HandleError(errorNumber As Integer, errorSource As String, errorDescription As String, errorHelpFile As String, errorHelpContext As String)
        Call SendMail(subject, body, mail)
        Err.Raise errorNumber, errorSource, errorDescription, errorHelpFile, errorHelpContext 
    End Sub
    

    我没有尝试过,但看起来它可能有效。

答案 1 :(得分:0)

您可以使用StopResume返回引发错误的行,但是您无法在生产代码中使用此行。这样做会停止代码运行,然后你可以使用F8进入下一行代码,它将返回引发错误的行。

    Private Sub Foo()
    On Error GoTo ErrorHandling
    a = 7 / 0

    Exit Sub
ErrorHandling:
    errorNumber = Err.Number
    errorSource = Err.Source
    errorDescription = Err.Description
    errorHelpFile = Err.HelpFile
    errorHelpContext = Err.HelpContext

    HandleError errorNumber, errorSource, errorDescription, errorHelpFile, errorHelpContext
    Stop
    Resume
End Sub

Public Sub HandleError(errorNumber As Integer, errorSource As String,  errorDescription As String, errorHelpFile As String, errorHelpContext As String)
    Call SendMail(Subject, body, mail)

End Sub

如果您需要一些可以从生产代码中提供错误报告的内容,我不相信有一种方法可以在没有为您的行编号并使用Erl的情况下返回引发错误的行。替代方法是使用有意义的代码实现您自己的错误提升,这样您就可以识别代码的哪一部分导致错误。

答案 2 :(得分:0)

如果您在VBA中使用错误处理并希望获得发生运行时错误的行,则需要Erl() - 为此您需要行号,简单明了。

  

使用插件对行进行编号不是解决方案,因为我的公司   限制不允许插件。

你应该让他们重新考虑这个政策。在没有MZ-Tools的情况下编程VBA并不好玩,全局搜索和过程调用函数单独使用是非常宝贵的。

当然,您在开发时没有行号,您可以在将代码投入生产时添加它们。