vba - 出错时退出子程序并将错误返回给调用错误子程序的子程序

标签 vba excel error-handling error-logging

一些背景:

前体:我已经查看了其他错误处理问题,但我无法完全将答案应用于我的情况。我觉得 Err.Raise 是我完成下面将要描述的内容的方法。但是,我不确定如何以我需要的方式实现它。如果我要使用 Err.Raise 在主子中引发错误代码之前,我该如何先退出 Sub1-15?

话虽如此,

我有一个大型 Excel VBA 项目,它执行大量不同的例程。我选择从一个主例程中调用所有例程,以便以后维护各个例程。我的主子程序中有一个 On Error 处理程序,如果从该主例程调用的任何例程中抛出错误,我希望触发该处理程序。

有没有办法:

  1. 记录
    • 发生的错误类型
    • 错误消息
    • 引发错误的子
  2. 发生错误时退出该子程序以返回主子程序,然后
    • 引发另一个子系统中刚刚发生的错误,以便调用 NotifyandRepair 错误处理程序?

我有以下情况

Sub MainSub()
    On Error GoTo NotifyandCorrect
    Call Sub1
    Call Sub2
    ...
    Call Sub15
    Exit Sub
NotifyandCorrect:
    'Send copy of faulty file, the error code and Sub that caused it
    'Then stop macro execution completely
End Sub

Sub Sub1()
    On Error Exit Sub1 and raise current Error in MainSub(?)
    'Perform data checks
End Sub

Sub Sub2()
    On Error Exit Sub2 and raise current Error in MainSub(?
    'Modify data groups
End Sub

Sub Sub15()
    On Error Exit Sub15 and raise current Error in MainSub(?
    'Clean up work
End Sub

我是否可以避免对 Sub1-Sub15 中的每一个执行如下操作?

Sub MainSub()
        On Error GoTo NotifyandCorrect
        Call Sub1
        Call Sub2
        ...
        Call Sub15
        Exit Sub
    NotifyandCorrect:
        'Send copy of faulty file, the error code and Sub that caused it
        'Then stop macro execution completely
    End Sub
    ...
    ...
Sub Sub15()
    On Error Goto HaltExecution
    'Clean up work
    Exit Sub
HaltExecution:
    'Note Error message & type
    'Note that Sub15 is where error occurred
    End Sub

结束问题

  1. 这可能吗?
  2. 如果这是不可能的,我应该如何处理这个问题以执行我所描述的操作?您有什么建议(如果可以,请提供示例)

最佳答案

您需要处理“子”方法中的错误,并让它们“重新抛出”错误(在错误处理程序子例程中使用 Err.Raise),以便调用者能够看到它- 重新抛出时,将方法的名称指定为“源”。以下代码产生此输出:

5            Invalid procedure call or argument        DoSomething1
9            Subscript out of range      DoSomething2
Public Sub MainSub()
    On Error GoTo ErrHandler

    DoSomething1
    DoSomething2

    Exit Sub
ErrHandler:
    Debug.Print Err.Number, Err.Description, Err.Source
    Resume Next
End Sub

Private Sub DoSomething1()
    On Error GoTo ErrHandler

    Err.Raise 5

    Exit Sub
ErrHandler:
    Err.Raise Err.Number, "DoSomething1", Err.Description
End Sub

Private Sub DoSomething2()
    On Error GoTo ErrHandler

    Err.Raise 9

    Exit Sub
ErrHandler:
    Err.Raise Err.Number, "DoSomething2", Err.Description
End Sub

Is there anyway I can avoid having to do something like below for each of Sub1-Sub15?

没有。每个过程都必须处理运行时错误,没有办法绕过它。

<小时/>

在硬编码字符串中指定方法名称很烦人。通过将每个过程封装到其自己的对象中(例如,某些 ICommand 实现),您可以利用 TypeName 函数实现相同的结果:

模块1

Option Explicit

Public Sub MainSub()
    On Error GoTo ErrHandler

    RunCommand New DoSomething1
    RunCommand New DoSomething2

    Exit Sub
ErrHandler:
    Debug.Print Err.Number, Err.Description, Err.Source
    Resume Next
End Sub

Private Sub RunCommand(ByVal command As ICommand)
    command.Execute
End Sub

ICommand(类模块)

Public Sub Execute()
End Sub

DoSomething1(类模块)

Option Explicit
Implements ICommand

Private Sub ICommand_Execute()
    On Error GoTo ErrHandler

    Err.Raise 5

ErrHandler:
    Err.Raise Err.Number, TypeName(Me), Err.Description
End Sub

DoSomething2(类模块)

Option Explicit
Implements ICommand

Private Sub ICommand_Execute()
    On Error GoTo ErrHandler

    Err.Raise 9

ErrHandler:
    Err.Raise Err.Number, TypeName(Me), Err.Description
End Sub

实际上并不需要 ICommand 接口(interface),但它正式化了每个 DoSomething 命令的调用方式。我们的想法是使用一个对象来实现每个过程 - 这样您就可以将TypeName(Me)作为错误源,而无需对字符串进行硬编码。您将在 15 个专用类模块中拥有 15 个方法,而不是在单个标准模块中拥有 15 个过程。

关于vba - 出错时退出子程序并将错误返回给调用错误子程序的子程序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35683567/

相关文章:

ios - 使用 CKPartialErrorsByItemIDKey 恢复错误

asp.net - 经典的ASP错误捕获-可以直接使用ASP.Net页面完成吗?

Excel VBA : can delete validation but not add new one

string - 如何在字符串vba中包含引号

Excel VBA 复制

sql - 存储过程中的多个表需要通过vba在excel中生成

excel - 比较两列并导出唯一值

ruby-on-rails-3 - 发送有关RubyOnRails中的错误的电子邮件

vba - EXCEL VBA : comparing day & month only from all the date

python - 是否可以搜索特定的键/值条目,如果找到,则删除整个字典?