首页 > 解决方案 > Excel VBA 类对象未定义

问题描述

我将 Excel 工作簿中所有事件的处理集中在一个名为“组件”的类中。该类被移动到单独的“xlam”文件和 Excel 工作簿中引用的“xlam”文件。

“组件”类定义如下:

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
END
Attribute VB_Name = "Components"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False

Public WithEvents WorkbookSD As Workbook, _
       WithEvents SheetConfig As Worksheet, _
       TableConfig As ListObject, _
       TableVerValues1 As ListObject, _
       TableVerValues2 As ListObject, _
       TableDValues As ListObject, _
       TableIGRValues As ListObject
...

Private Sub Class_Initialize()
  On Error GoTo ErrorHandling
  ToggleAppUpdate False
  Set WorkbookSD = ActiveWorkbook
  Set SheetConfig = WorkbookSD.Worksheets(SHEET_CONFIG)
  Set TableConfig = SheetConfig.ListObjects(TABLE_CONFIG)
...

Private Sub SheetConfig_Activate()
  On Error GoTo ErrorHandling
  ...
ErrorHandling:
  If Err.Number <> 0 Then
    ReportError
  End If
End Sub

请注意“属性 VB_PredeclaredId = True”,以确保声明类的对象。有点像表单是如何做到的。

所以我在这个类和WithEvents中声明了我想要处理事件的所有对象。“组件”在“Class_Initialize”事件中初始化。

我在代码的其他地方通过“Component.XXXX”引用了这个类的对象和方法。这是“xlam”文件中另一个模块的示例:

Public Function FindCnfg(pTerm As String, pSearchBy As SearchBy) As Range
  Dim lTable As ListObject, _
      lRow As Range, _
      lCol As Long
  On Error GoTo ErrorHandling
  Set FindCnfg = Nothing
  Set lTable = Components.TableConfig  
  If lTable.DataBodyRange Is Nothing Then
    Exit Function
  End If
  Select Case pSearchBy
    Case SearchBy.ID
      lCol = 1
    Case SearchBy.Key
      lCol = 2
    Case Else
      RaiseError ErrorCode.INVALID_PARAM
  End Select
  Set lRow = lTable.DataBodyRange.Columns(lCol).Find(What:=pTerm, LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByRows)
  If Not lRow Is Nothing Then
    Set lRow = lRow.EntireRow
    Set FindCnfg = lRow
  End If
ErrorHandling:
  Set lTable = Nothing
  Set lRow = Nothing
  If Err.Number <> 0 Then
    RaiseError Err.Number, "FindCnfg", Err.Description
  End If
End Function

我使用“On Error GoTo X”到处捕捉错误。

在正常情况下一切正常,事件得到处理。

但是时不时地,我会收到一个错误消息,指出对象“组件”未定义或事件处理在没有警告或错误的情况下停止工作。

如果我手动输入开发人员工具并运行引用“组件”的方法,它会再次起作用。

我怀疑这个问题与预先声明的“组件”对象的初始化有关。

有谁知道如何防止这些零星的不稳定性?也许另一种方法可以确保“组件”的对象始终可用。

标签: excelvba

解决方案


这个问题似乎有多个根本原因。1-全局变量未定义。2- Office 2016 有多个错误,包括 Workbooks.Open(我在我的代码中使用)。

为了解决 1,我将全局变量替换为返回变量的函数并使用该函数而不是全局变量:

Private lComponents As Components

Function MyComponents() As Components
  If lComponents Is Nothing Then
    Set lComponents = New Components
  End If
  Set MyComponents = lComponents
End Function

要解决 2,请不要将 Workbooks.Open 的返回值分配给任何变量。相反,调用 Workbooks.Open,然后将变量分配给 Workbooks(nameOfWB):

Workbooks.Open Filename:=lPath
Set WB = Workbooks(nameOfWB) 

这两个变化大大提高了稳定性。由于未定义的变量,我不再有随机错误。


推荐阅读