错误退出 sub 和 return 错误到 sub 调用错误的 sub
On error exit sub and return error to sub that called erroneous sub
一些背景:
先行者: 我已经查看了其他错误处理问题,但我无法将答案完全应用到我的情况中。我觉得 Err.Raise
是我将如何完成我将在下面描述的内容。但是,我不确定如何以我需要的方式实施它。如果我要使用 Err.Raise
在主子中引发错误代码之前我将如何先退出 Sub1-15?
也就是说,
我有一个大型 Excel VBA 项目,它执行大量不同的例程。我选择从一个主例程调用所有例程,以便稍后维护各个例程。我的主子中有一个 On Error
处理程序,如果从该主例程调用的任何例程中抛出错误,我想触发它。
有没有办法:
- 记录下
- 发生的错误类型
- 错误信息
- 引发错误的子
- On Error exit that sub to return to the main sub, 然后
- 引发另一个子中刚刚发生的错误,以便调用 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
结束问题
- 这可能吗?
- 如果这不可能,我应该如何处理它才能像我描述的那样做?你有什么建议(如果可以请举个例子)
您可以使用 Err.Number
和 Err.Description
获取有关错误的信息。
接下来,我建议创建一个临时 string
并在输入新子时更新它。如:
Sub Sub1()
temp= "sub1"
...
End Sub
Sub Sub2()
temp= "sub2"
...
End Sub
因此,无论何时处理错误,字符串 temp 都会保存它发生的子项的值。
您需要在 "child" 方法中处理错误,并让它们 "re-throw" 错误(在错误处理程序子例程中使用 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
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(class 模块)
Public Sub Execute()
End Sub
DoSomething1(class 模块)
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(class 模块)
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
命令的方式。这个想法是有一个 object 来实现每个过程 - 这样你就可以将 TypeName(Me)
作为错误源,并且永远不需要对字符串进行硬编码。您将在 15 个专用 class 模块中包含 15 个方法,而不是在单个标准模块中包含 15 个过程。
一些背景:
先行者: 我已经查看了其他错误处理问题,但我无法将答案完全应用到我的情况中。我觉得 Err.Raise
是我将如何完成我将在下面描述的内容。但是,我不确定如何以我需要的方式实施它。如果我要使用 Err.Raise
在主子中引发错误代码之前我将如何先退出 Sub1-15?
也就是说,
我有一个大型 Excel VBA 项目,它执行大量不同的例程。我选择从一个主例程调用所有例程,以便稍后维护各个例程。我的主子中有一个 On Error
处理程序,如果从该主例程调用的任何例程中抛出错误,我想触发它。
有没有办法:
- 记录下
- 发生的错误类型
- 错误信息
- 引发错误的子
- On Error exit that sub to return to the main sub, 然后
- 引发另一个子中刚刚发生的错误,以便调用 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
结束问题
- 这可能吗?
- 如果这不可能,我应该如何处理它才能像我描述的那样做?你有什么建议(如果可以请举个例子)
您可以使用 Err.Number
和 Err.Description
获取有关错误的信息。
接下来,我建议创建一个临时 string
并在输入新子时更新它。如:
Sub Sub1()
temp= "sub1"
...
End Sub
Sub Sub2()
temp= "sub2"
...
End Sub
因此,无论何时处理错误,字符串 temp 都会保存它发生的子项的值。
您需要在 "child" 方法中处理错误,并让它们 "re-throw" 错误(在错误处理程序子例程中使用 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
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(class 模块)
Public Sub Execute()
End Sub
DoSomething1(class 模块)
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(class 模块)
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
命令的方式。这个想法是有一个 object 来实现每个过程 - 这样你就可以将 TypeName(Me)
作为错误源,并且永远不需要对字符串进行硬编码。您将在 15 个专用 class 模块中包含 15 个方法,而不是在单个标准模块中包含 15 个过程。