【问题标题】:Error handling in a Class Module Function类模块函数中的错误处理
【发布时间】:2015-03-05 20:53:39
【问题描述】:

我的工作簿中有几个班级模块。类模块 1 中的公共函数之一依赖于类模块 2 中的函数的数据,这种情况发生了四次。如果对象从 2 类中丢失,则程序崩溃(如预期的那样)。我很难正确调试代码,因为我似乎只能从主子例程中退出程序。我更愿意从 Class 函数中杀死程序,但我不知道这是否可能(如果可以,我们可以在这里压缩它)。我目前在主子程序中使用 On Error 语句,但是这些语句没有及时执行,因为 Class 1 中的函数从 Class 2 中获取了四次数据。

类模块 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 上方是我调用类模块 2 的公共函数的地方。

下面是类模块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

我这里有很多嵌套操作。您可以看到在“oload”函数完成之前“goto”语句不会执行。 “oload”函数在完成计算之前调用了“toGlobal”函数四次。

如何在“toGlobal”函数中第一次出现缺失对象后终止子程序?

【问题讨论】:

  • 我还没有完全通读这个,但是(一般来说)我的类 raise 错误并且我的主程序会监听它们。

标签: vba function class error-handling


【解决方案1】:

您的On Error Resume Next 语句正在吞噬toGlobal 中的错误,并防止它“冒泡”调用堆栈。您拥有的一种选择是“重新抛出”错误。在 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

另一种选择是从您的类模块中删除您的On Error Resume Next 语句,以便错误自然地冒泡。这是我通常会采用的方法,除非有令人信服的理由偏离它。

【讨论】:

  • 很好的答案,我已经多次使用过这种技术。我要补充一点,将错误源设置为“方法名称:”和 Err.Source 允许您显示导致错误的逻辑路径。
  • 谢谢,@jac,我更新了我的答案以采纳你的建议。
  • 做到了!!!当我单步执行代码时,它会从 Err.Raise 线跳到主子线。它绕过了第一个类模块函数。这太突然了,我不完全理解它是如何或为什么起作用的,但它确实有效。非常感谢。
猜你喜欢
  • 1970-01-01
  • 2014-06-28
  • 2018-10-19
  • 1970-01-01
  • 1970-01-01
  • 2011-03-09
  • 1970-01-01
  • 1970-01-01
  • 2012-10-23
相关资源
最近更新 更多