在错误退出子上并将错误返回到调用错误子

时间:2016-02-28 14:13:56

标签: excel vba excel-vba error-handling error-logging

某些背景:

前体:我在其他错误处理问题上环顾四周,但我还没有能够完全应用我的情况的答案。我觉得Err.Raise就是如何实现我将在下面描述的内容。但是,我不确定如何以我需要的方式实现它。如果我使用Err.Raise如何在主子代码中引发错误代码之前先退出Sub1-15?

话虽如此,

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

有办法:

  1. 记录下来
    • 发生的错误类型
    • 错误消息
    • 提出错误的子
  2. On Error退出该子返回主子,然后
    • 提出刚出现在另一个sub中的错误,以便调用 NotifyandRepair 错误处理程序?
  3. 我有以下情况

    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. 如果这是不可能的,我该如何处理这件事来做我所描述的事情呢?你会建议什么(如果可以,请提供一个例子)

2 个答案:

答案 0 :(得分:3)

你需要处理你孩子的错误"方法,并让他们重新投掷"错误(在错误处理程序子例程中使用Err.Raise),以便调用者可以看到它 - 重新投掷时,将方法的名称指定为" source"。以下代码生成此输出:

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
  

无论如何,我可以避免为每个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接口并不是真正需要的,而是规范了每个DoSomething命令的调用方式。我们的想法是使用对象来实现每个过程 - 这样您就可以将TypeName(Me)作为错误源,并且永远不需要对字符串进行硬编码。您将在15个专用类模块中使用15种方法,而不是在单个标准模块中使用15个程序。

答案 1 :(得分:0)

您可以使用Err.NumberErr.Description获取有关错误的信息。

接下来,我建议创建一个临时string并在输入新子时更新它。如:

Sub Sub1()
temp= "sub1"
...
End Sub

Sub Sub2()
temp= "sub2"
...
End Sub

因此,无论何时处理错误,字符串temp都会保存它所出现的子的值。