【问题标题】:Error handling between multiple modules and subroutines多个模块和子程序之间的错误处理
【发布时间】:2019-08-05 13:58:53
【问题描述】:

我有一个单独的模块和一个很长的工作子例程。

我决定把它切成小块。

我现在有六个模块,其中几个模块包含多个子例程(比如 6 个或更少)。例如,一个模块包含我的所有功能(如 10 个功能)。一个子程序(RT_CMM_DATA_COMPILER_MAIN)定义了几个变量并调用其他模块,如下所示:

Sub RT_CMM_DATA_COMPILER_MAIN()

    Public Path As String
    Public wkbTemp As Workbook
    Public StartTime As Double
    Public CurrentDateTime As Date
       'Etc....

       'Do some stuff....

    Call RT_SETUP_WKBTEMP
    Call RT_COMPILE_TABLE_HEADER
    Call RT_RUN_LOG
    Call RT_SAVE_WORKBOOKS

       'Do some stuff....

    Application.Quit

End Sub

Sub LogError(ErrorMsg As String)

    wkbErrorLog.Activate

    On Error Resume Next

    Range("A" & LRow).Value = CurrentData_FilePath
    Range("B" & LRow).Value = CurrentDateTime
    Range("C" & LRow).Value = ErrorMsg
        'Etc....

    wkbErrorLog.Save
    wkbErrorLog.Saved = True

    Application.Quit

    Application.DisplayAlerts = True
    Application.EnableEvents = True

End Sub

这使得代码的处理变得更加容易,但有一个例外。我不确定如何处理错误处理。例如,我的部分代码检查文件是 txt 还是 csv 文件。如果两者都不是,我希望它转到Sub LogError(ErrorMsg As String)。我的意图是制作一个可供所有各种模块和子例程使用的单一错误处理程序。

Sub RT_SETUP_WKBTEMP()

    If File_Extension = "txt" Then
        Call RT_FORMAT_TXT_FILE
    ElseIf File_Extension = "csv" Then
        Call RT_FORMAT_CSV_FILE
    Else
        Call LogError("Not a .csv or .txt file")
    End If

        'Do some more stuff.....

End Sub

但是,我看到因为Sub RT_SETUP_WKBTEMP()“调用”错误处理程序子例程,它在运行完错误处理程序子例程后返回到停止的Sub RT_SETUP_WKBTEMP()。我不想要这个。我希望程序在运行完错误处理程序子程序后结束。

【问题讨论】:

  • 在不涉及重构代码的情况下,您可以使用Exit Sub statement 甚至End statement 立即终止宏的执行——但您应该注意,这种类型的立即关闭不是一定是一个“干净”的出口,您可以在其中保存/擦除/撤消中间数据或您的程序已完成一半的其他事情。
  • Peter 的建议应该有效,只是为了澄清这一点,您应该将“Exit Sub”语句放在调用之后和“End If”之前。如果您希望在调用子程序时始终终止执行,您可以将“结束”语句放在 LogError() 子程序的最后。不过请记住彼得的警告。
  • 谢谢...我希望收到一个可能如此简单的解决方案。哪个会更好...退出潜艇?还是结束?或者使用它们之间的优点/缺点/区别是什么?另外,您说“没有可能重构您的代码”。你这是什么意思?有没有更好/不同的方式来组织我的代码?
  • 好的...我想通了...在第一个模块中,我将“on error goto error handler”放在第一个模块中。错误处理程序调用“Sub LogError(ErrorMsg As String)”,然后在子运行后它返回到错误处理程序并且程序结束......最后,我将 if 语句更改为 (Err.Raise Number:=vbObjectError + 513 , 说明:="不是 .csv 或 .txt 文件")。实际上,人为地创建了一个错误,将程序自动从子模块发送到母模块中的错误处理程序。
  • 您可能想查看函数,它们可以返回值。在大多数情况下,您应该避免使用全局变量。

标签: excel vba error-handling


【解决方案1】:

正如您在comment 中已经指出的那样,您可以引发自定义错误并使用错误处理程序进行处理。您还可以使用 On Error... 记录整个调用堆栈。一旦发生错误,当前过程中的 On Error... 不再适用,错误处理将传递给调用过程,您可以从中编写另一个错误日志条目:

Public Path As String
Public wkbTemp As Workbook
Public StartTime As Double
Public CurrentDateTime As Date
   Etc....

Sub RT_CMM_DATA_COMPILER_MAIN()
    Do some stuff....

    On Error GoTo ErrHandlerMain
    Call RT_SETUP_WKBTEMP
    Call RT_COMPILE_TABLE_HEADER
    Call RT_RUN_LOG
    Call RT_SAVE_WORKBOOKS

    Do some stuff....
ErrorExit:
    'Clean up and exit
    On Error Resume Next
    Application.Quit

    Application.DisplayAlerts = True
    Application.EnableEvents = True

    Exit Sub

ErrHandlerMain:
    Call LogError("Error in Sub RT_CMM_DATA_COMPILER_MAIN")
    Resume ErrorExit 'Go to the clean-up code and Exit Sub
End Sub

Sub RT_SETUP_WKBTEMP()
    Const iCUSTOM_ERROR As Integer = 513 
    On Error GoTo ErrHandlerSetup
    If File_Extension = "txt" Then 
        Call RT_FORMAT_TXT_FILE 
    ElseIf File_Extension = "csv" Then 
        Call RT_FORMAT_CSV_FILE 
    Else
        'This error will be handled by ErrHandlerSetup
        Err.Raise vbObjectError + iCUSTOM_ERROR
    End If

    'Do some more stuff.....

    Exit Sub

ErrHandlerSetup:
    Call LogError("Error in Sub RT_SETUP_WKBTEMP: Not a .csv or .txt file")

    'Raise another error, which will be handled by ErrHandlerMain in Sub RT_CMM_DATA_COMPILER_MAIN
    Err.Raise vbObjectError + iCUSTOM_ERROR
End Sub

Sub LogError(ErrorMsg As String)
    'Modified to not include any clean-up code
    wkbErrorLog.Activate

    On Error Resume Next

    Range("A" & LRow).Value = CurrentData_FilePath
    Range("B" & LRow).Value = CurrentDateTime
    Range("C" & LRow).Value = ErrorMsg
        Etc....

    wkbErrorLog.Save
    wkbErrorLog.Saved = True

End Sub

这种情况下的错误日志将如下所示:

Error in Sub RT_SETUP_WKBTEMP: Not a .csv or .txt file
Error in Sub RT_CMM_DATA_COMPILER_MAIN

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-04-13
    • 2014-05-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-19
    • 2018-07-26
    • 2017-01-29
    相关资源
    最近更新 更多