在 Excel 中调试 VBA 类中的错误

问题描述 投票:0回答:1

我有一个功能与此类似的模块:

主模块

Sub Test()
  On Error Resume Next
  Dim O1 As New Class1
  O1.DoSomething
  On Error GoTo 0
End Sub

还有一些与此类似的课程:

1班

Sub DoSomething()
  FindStuff
  
  'create similar objects who perform similar operations and raise similar errors
  Dim O2 As New Class2
  O2.DoSomething
End Sub

Function FindStuff() As Stuff
  'scan the WorkBook, the file system, etc. and organize the members of the object
  If CorruptedFileSystem Then Err.Raise 514, "File system corrupted"
  If CorruptedWorkBook Then Err.Raise 515, "WorkBook corrupted"
  If Found Then Set FindStuff = FoundStuff
End Function

VBA 菜单“工具”>“选项”>“常规”选项卡中有一个错误捕获选项:

如果我将错误捕获设置为

Break in Class Module
,则
On Error Resume Next
将被忽略,并且每个
Err.Raise
将停止类内的执行。

如果我将错误捕获设置为

Break on Unhandled Errors
,那么
Err.Raise
将在主模块上的调用处停止执行,而不是在类内部。

因此,在一种情况下,我无法执行已处理错误的代码,在另一种情况下,我无法调试未处理的错误。

当项目增长并且主模块创建一个对象来打开一个创建更多对象的表单(这是另一个对象)时,问题变得难以管理。有些方法处理自己的错误,有些方法旨在中止并引发错误以由调用者管理。

有没有办法处理和调试类中的错误?

编辑

显然我的问题不够清楚。我更改了标题,我将尝试使用更清晰的示例。

模块1

Sub Test1()
  Dim O As New Class1
  O.UnhandledCall
End Sub

Sub Test2()
  On Error Resume Next
  Debug.Print 1 / 0
  Dim O As New Class1
  O.HandledCall
  On Error GoTo 0
End Sub

1班

Sub UnhandledCall()
  Debug.Print 2 / 0
End Sub

Sub HandledCall()
  Debug.Print 3 / 0
End Sub

测试1

设置

Error Trapping = Break on Unhandled Errors
并执行
Test1
。调试器不会在未处理的错误处停止
2 / 0
。相反,它会停在
O.UnhandledCall
,从而无法知道哪一行导致了错误、局部变量值是什么、堆栈等。

测试2

设置

Error Trapping = Break in Class Module
并执行
Test2
。调试器不会停在
1 / 0
,很好,因为错误已被处理。但即使错误是在调用函数内部处理的,它也会在类内部的
3 / 0
处停止,与
1 / 0
处于同一级别。

悲伤总结

因此,使用第一个设置,我看不到错误发生在哪里,使用第二个设置,我无法运行干净地处理错误的宏。

这显然是一个过于简单化的例子。我目前正在处理的现实世界案例是一个创建数十个对象的表单,一些对象检查一些文本文件,其他对象通过 COM 在 CAD 上打开绘图,其他对象与数据库通信,等等。条件不一致我想中止打开表格。

创建对象时,它们会执行数千行代码,并产生数百个托管错误。当他们在文件、图形或数据库中发现无法管理的内容时,他们会将错误处理推迟到调用者,将堆栈向上爬到应该无法打开的表单,并向上爬到应该检测到错误并执行操作的调用者。关于它的一些事情。

我希望调试器能够顺利地处理托管错误,并在有问题的行出现非托管错误时停止。相反,调试器在模块中按预期工作,但在类中,它要么在出现所有错误时停止,要么永远不会停止,无论它们是否被托管。

例如,如果我设置

Error Trapping = Break in Class Module
,所有托管错误都会中断执行,如
Test2
所示,并且我的调试会话将永远不会结束。

如果我设置

Error Trapping = Break on Unhandled Errors
那么我永远不会知道是什么触发了错误,因为调试器将遍历所有类直到第一个对象并告诉我这是导致错误的行,如
Test1
中所示。

excel vba debugging error-handling
1个回答
2
投票

正如您所注意到的,您无法仅通过调整 IDE/调试器设置来冒泡在类模块中引发的运行时错误 进行现场调试。

还有另一种方法。定义一个项目范围的条件编译值,比如

DEBUG_MODE
:

VBAProject - Propect Properties

在类模块的错误处理程序中,使用条件编译逻辑进行编程中断:

Public Function FetchResults(ByVal filter As String) As Collection
    On Error GoTo CleanFail

    Dim results As Collection
    Set results = this.Repository.Where(filter)

CleanExit:
    Set FetchResults = results
    Exit Function

CleanFail:
#If DEBUG_MODE = 1 Then
    Stop
#Else
    Err.Raise Err.Number 'rethrows with same source and description
#End If
    Set results = Nothing
    Resume CleanExit
End Sub

如果您不介意 VBE 出现在困惑的用户身上,那么您还可以使用

Debug.Assert
语句在不满足条件时中断执行:

Public Function FetchResults(ByVal filter As String) As Collection
    On Error GoTo CleanFail

    Dim results As Collection
    Set results = this.Repository.Where(filter)

CleanExit:
    Set FetchResults = results
    Exit Function

CleanFail:
    Debug.Assert Err.Number <> 0 ' will definitely break here
    Set results = Nothing
    Resume CleanExit
End Sub
© www.soinside.com 2019 - 2024. All rights reserved.