Excel VBA类对象获取未定义

时间:2019-02-22 08:33:11

标签: 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

请注意,为了确保声明了一个类的对象,“ Attribute 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”在各处捕获错误。

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

但是每隔一段时间,我会收到一条错误消息,指出未定义对象“ Component”,或者事件处理在没有警告或错误的情况下一起停止工作。

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

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

有人对如何预防这些偶发性不稳定有想法吗? 也许有另一种方法可以确保“组件”的对象始终可用。

1 个答案:

答案 0 :(得分:0)

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

要解决1,我将全局变量替换为一个返回该变量的函数,并使用该函数代替全局变量:

select XMLType('<root>
 <TPL>
  <fld>f7</fld><val><![CDATA[v1&v2]]></val>
 </TPL>
</root>') from dual;

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

Private lComponents As Components

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

这两个更改极大地提高了稳定性。由于变量未定义,我不再出现随机错误。