在错误退出子和返回错误分为称为错误的子

一些背景:

前体:我在其他error handling问题上查看过,但是我没有能够完全应用我的情况。 我觉得像Err.Raise是我将如何完成我将在下面描述。 但是,我不知道如何以我需要的方式来实现它。 如果我要使用Err.Raise ,我Err.Raise如何退出Sub1-15之前提出的主要子错误代码?

话虽如此,

我有一个大的Excel VBA项目,执行过多的不同的例程。 我select从一个主例程中调用所有例程,以便日后维护各个例程。 我有一个On Error处理程序在我的主要子,我想要触发如果在该主例程调用的任何例程中引发错误。

有没有办法:

  1. logging下
    • 发生的错误types
    • 错误信息
    • 小组提出了错误
  2. 在错误退出该子返回到主子,然后
    • 引发刚刚在另一个子节点发生的错误,以便调用NotifyandRepair Error Handler?

我有以下情况

 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. 如果这是不可能的,我应该如何处理这个做我喜欢的东西? 你会怎么build议(请提供一个例子,如果可以的话)

你需要在你的“子”方法中处理错误,并让它们“重新抛出”错误(在error handling程序子例程中使用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 

无论如何,我可以避免为每个Sub1-Sub15做下面的事情吗?

不是。每个程序都必须处理运行时错误,这是没有办法的。


在硬编码string中指定方法名称很烦人。 通过将每个过程封装到自己的对象中(比如一些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)作为你的错误源,并且永远不需要硬编码一个string。 您将在15个专用类模块中使用15个方法,而不是单个标准模块中的15个方法。

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

接下来,我会build议创build一个临时string并更新它,每当一个新的子进入。 如:

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

所以,无论何时处理错误,stringtemp都会保存发生的子的值。