Class 模块函数中的错误处理
Error handling in a Class Module Function
我的工作簿中有几个 Class 模块。 Class 模块 1 中的 public 函数之一依赖于 Class 模块 2 中函数的数据,这种情况发生了四次。如果对象从 Class 2 中丢失,程序就会崩溃(如预期的那样)。我很难正确调试代码,因为我似乎只能从主子例程中退出程序。我更愿意从 Class 函数中终止程序,但我不知道这是否可能(如果是的话,我们可以在这里压缩它)。我目前在主子程序中使用 On Error 语句,但这些语句没有及时执行,因为 Class 1 中的函数四次从 Class 2 中获取数据。
Class 模块 1 函数
Function oload(ByVal pload As Double, ByVal cord As cCordCol, ByVal grid As cGridCol)
' cord is a scripting.dictionary of Class Module Objects (cCord)
' grid is a scripting.dictionary of Class Module Objects (cGrid)
n1 = grid.Item(pg1).toGlobal(cord)
n2 = grid.Item(pg2).toGlobal(cord)
n3 = grid.Item(pg3).toGlobal(cord)
n4 = grid.Item(pg4).toGlobal(cord)
' do something here
oload = sum_Ploads
End Function
n1 到 n4 上方是我调用 Class 模块 2 的 public 函数的地方。
下面是 Class 模块 2 函数
Function toGlobal(ByVal cord As cCordCol)
On Error Resume Next
ctype = cord.Item(Me.cord1).sys
' Missing Coordinate System Error
If Err.Number <> 0 Then
i = MsgBox("The definition of Coordinate " & Me.cord1 & " was missing from the Bulk Data " & Chr(10) & _
"File. Include this Coord in the .bdf and re-execute the program.", vbOKOnly, "Runtime Error")
' *** TERMINATE MAIN SUBROUTING HERE ***
End If
这将引发一个消息框,指示缺少一个对象,特别是 (me.cord1) 部分 - 这是 scripting.dictionary 中的一个项目。我想在这里终止程序。
主要子程序(大大减少)在这里:
Sub main()
' lookup Element ID, Calc OLOAD, Sum Load Set OLOAD
On Error GoTo PROC_ERR
If dict_quad.Exists(EID) Then dict_oload.Item(LS).add_to_oload (dict_quad.Item(EID).oload(pload, dict_cord, dict_grid))
If dict_tria.Exists(EID) Then dict_oload.Item(LS).add_to_oload (dict_tria.Item(EID).oload(pload, dict_cord, dict_grid))
PROC_ERR:
If Err.Number <> 0 Then Exit Sub
End Sub
我这里有很多嵌套操作。您可以看到 "goto" 语句在 "oload" 函数完成之前不会执行。 "oload" 函数在完成计算之前调用了 "toGlobal" 函数四次。
如何在 "toGlobal" 函数中首次出现缺失对象后终止子例程?
您的 On Error Resume Next
语句吞没了 toGlobal
中的错误并阻止它进入 "bubbling up" 调用堆栈。您可以选择 "re-throw" 错误。在 VBA 中执行此操作比其他语言稍微笨拙一些,但仍然可行。
例如,您可以将 toGlobal
函数更改为如下所示:
Function toGlobal(ByVal cord As cCordCol)
On Error Resume Next
ctype = cord.Item(Me.cord1).sys
' Missing Coordinate System Error
If Err.Number <> 0 Then
i = MsgBox("The definition of Coordinate " & Me.cord1 & " was missing from the Bulk Data " & Chr(10) & _
"File. Include this Coord in the .bdf and re-execute the program.", vbOKOnly, "Runtime Error")
' *** TERMINATE MAIN SUBROUTING HERE ***
'Save info from the error object (it will get cleared in the On Error statement below)
Dim ErrNum As Long: ErrNum = Err.Number
Dim ErrMsg As String: ErrMsg = Err.Description
Dim ErrSrc As String: ErrSrc = Err.Source
'Reset error handling to allow errors to bubble up the call stack
On Error Goto 0
'"Re-throw" the error
Err.Raise ErrNum, "toGlobal:" & ErrSrc, ErrMsg
End If
另一种选择是从 class 模块中删除 On Error Resume Next
语句,这样错误就会自然地冒出来。这是我通常会采用的方法,除非有一些令人信服的理由偏离它。
我的工作簿中有几个 Class 模块。 Class 模块 1 中的 public 函数之一依赖于 Class 模块 2 中函数的数据,这种情况发生了四次。如果对象从 Class 2 中丢失,程序就会崩溃(如预期的那样)。我很难正确调试代码,因为我似乎只能从主子例程中退出程序。我更愿意从 Class 函数中终止程序,但我不知道这是否可能(如果是的话,我们可以在这里压缩它)。我目前在主子程序中使用 On Error 语句,但这些语句没有及时执行,因为 Class 1 中的函数四次从 Class 2 中获取数据。
Class 模块 1 函数
Function oload(ByVal pload As Double, ByVal cord As cCordCol, ByVal grid As cGridCol)
' cord is a scripting.dictionary of Class Module Objects (cCord)
' grid is a scripting.dictionary of Class Module Objects (cGrid)
n1 = grid.Item(pg1).toGlobal(cord)
n2 = grid.Item(pg2).toGlobal(cord)
n3 = grid.Item(pg3).toGlobal(cord)
n4 = grid.Item(pg4).toGlobal(cord)
' do something here
oload = sum_Ploads
End Function
n1 到 n4 上方是我调用 Class 模块 2 的 public 函数的地方。
下面是 Class 模块 2 函数
Function toGlobal(ByVal cord As cCordCol)
On Error Resume Next
ctype = cord.Item(Me.cord1).sys
' Missing Coordinate System Error
If Err.Number <> 0 Then
i = MsgBox("The definition of Coordinate " & Me.cord1 & " was missing from the Bulk Data " & Chr(10) & _
"File. Include this Coord in the .bdf and re-execute the program.", vbOKOnly, "Runtime Error")
' *** TERMINATE MAIN SUBROUTING HERE ***
End If
这将引发一个消息框,指示缺少一个对象,特别是 (me.cord1) 部分 - 这是 scripting.dictionary 中的一个项目。我想在这里终止程序。
主要子程序(大大减少)在这里:
Sub main()
' lookup Element ID, Calc OLOAD, Sum Load Set OLOAD
On Error GoTo PROC_ERR
If dict_quad.Exists(EID) Then dict_oload.Item(LS).add_to_oload (dict_quad.Item(EID).oload(pload, dict_cord, dict_grid))
If dict_tria.Exists(EID) Then dict_oload.Item(LS).add_to_oload (dict_tria.Item(EID).oload(pload, dict_cord, dict_grid))
PROC_ERR:
If Err.Number <> 0 Then Exit Sub
End Sub
我这里有很多嵌套操作。您可以看到 "goto" 语句在 "oload" 函数完成之前不会执行。 "oload" 函数在完成计算之前调用了 "toGlobal" 函数四次。
如何在 "toGlobal" 函数中首次出现缺失对象后终止子例程?
您的 On Error Resume Next
语句吞没了 toGlobal
中的错误并阻止它进入 "bubbling up" 调用堆栈。您可以选择 "re-throw" 错误。在 VBA 中执行此操作比其他语言稍微笨拙一些,但仍然可行。
例如,您可以将 toGlobal
函数更改为如下所示:
Function toGlobal(ByVal cord As cCordCol)
On Error Resume Next
ctype = cord.Item(Me.cord1).sys
' Missing Coordinate System Error
If Err.Number <> 0 Then
i = MsgBox("The definition of Coordinate " & Me.cord1 & " was missing from the Bulk Data " & Chr(10) & _
"File. Include this Coord in the .bdf and re-execute the program.", vbOKOnly, "Runtime Error")
' *** TERMINATE MAIN SUBROUTING HERE ***
'Save info from the error object (it will get cleared in the On Error statement below)
Dim ErrNum As Long: ErrNum = Err.Number
Dim ErrMsg As String: ErrMsg = Err.Description
Dim ErrSrc As String: ErrSrc = Err.Source
'Reset error handling to allow errors to bubble up the call stack
On Error Goto 0
'"Re-throw" the error
Err.Raise ErrNum, "toGlobal:" & ErrSrc, ErrMsg
End If
另一种选择是从 class 模块中删除 On Error Resume Next
语句,这样错误就会自然地冒出来。这是我通常会采用的方法,除非有一些令人信服的理由偏离它。