Excel VBA类对象未定义
我已将Excel工作簿中所有事件的处理集中在一个名为“组件”的类中。 该类将移动到单独的“xlam”文件和Excel工作簿中引用的“xlam”文件中 “组件”类定义如下:Excel VBA类对象未定义,excel,vba,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
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
1.0版类
开始
多用途=-1'真
结束
属性VB_Name=“组件”
属性VB_GlobalNameSpace=False
属性VB_createable=False
属性VB_PredeclaredId=True
属性VB_Exposed=False
将事件工作簿作为工作簿公开_
使用事件SheetConfig作为工作表_
TableConfig作为ListObject_
TableVerValues1作为ListObject_
TableVerValues2作为ListObject_
作为ListObject的TabledValue_
TablerValue作为ListObject
...
私有子类_Initialize()
关于错误转到错误处理
toggleappupdatefalse
设置工作簿D=ActiveWorkbook
设置SheetConfig=WorkbookSD.Worksheets(工作表配置)
Set TableConfig=SheetConfig.ListObjects(表配置)
...
专用子表配置_激活()
关于错误转到错误处理
...
错误处理:
如果错误号为0,则
报告错误
如果结束
端接头
请注意“Attribute VB_PredeclaredId=True”以确保声明类的对象。有点像一个表单是怎么做的
因此,我在这个类和WithEvents中声明了我想要处理事件的所有对象。
“组件”在“Class_Initialize”事件中初始化
我在代码的其他地方通过“Component.XXXX”引用此类中的对象和方法。以下是“xlam”文件中另一个模块的示例:
公共函数FindCnfg(pTerm作为字符串,pSearchBy作为SearchBy)作为范围
将lTable设置为ListObject_
lRow作为射程_
只要
关于错误转到错误处理
Set FindCnfg=Nothing
设置lTable=Components.TableConfig
如果lTable.DataBodyRange为空,则
退出功能
如果结束
选择Case pSearchBy
Case SearchBy.ID
lCol=1
案例检索键
lCol=2
其他情况
RaiseError ErrorCode.INVALID_参数
结束选择
设置lRow=lTable.DataBodyRange.Columns(lCol).Find(What:=pTerm,LookIn:=xlFormulas,LookAt:=xlWhole,SearchOrder:=xlByRows)
如果不是lRow,那就什么都不是了
设置lRow=lRow.EntireRow
设置FindCnfg=lRow
如果结束
错误处理:
设置lTable=Nothing
设置lRow=Nothing
如果错误号为0,则
RaiseError错误编号,“FindCnfg”,错误描述
如果结束
端函数
我使用“On Error GoTo X”捕捉任何地方的错误
在正常情况下,这一切都很好,事件都得到了处理
但偶尔,我会收到一个错误,指出对象“组件”未定义,或者事件处理在没有警告或错误的情况下停止一起工作
如果我手动输入开发工具并运行引用“组件”的方法,它会再次工作
我怀疑这个问题与预先声明的“组件”对象的初始化有关
有人知道如何防止这些零星的不稳定吗?
也许有一种不同的方法可以确保“组件”的对象始终可用。问题似乎有多个根本原因。 1-全局变量未定义。 2-Office 2016有多个bug,包括Workbook.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(nameOfWB):
这两个变化极大地提高了稳定性。我不再因为未定义的变量而出现随机错误。问题似乎有多个根本原因。 1-全局变量未定义。 2-Office 2016有多个bug,包括Workbook.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(nameOfWB):
这两个变化极大地提高了稳定性。由于未定义的变量,我不再有随机错误。介于
VERSION 1.0 CLASS
和属性VB\u Exposed=False
之间的代码不是有效的VBA代码。在VBA编辑器中看到该代码部分了吗?请澄清你能不能也提供一个?@peh对我来说就像是类模块的导出。在IDE中不可见,但在文本中查看导出文件时有效editor@chrisneilsen是的,我看到了,这就是为什么我问他是否看到VBE中的代码部分。因为我看到有人导出模块,而不是正确导入模块,所以我在记事本中打开了文件并复制了内容。我的问题旨在确保这种情况不会在这里发生。@Pᴇʜ:正如“克里斯·尼尔森”所描述的那样。这是一种出口。我在上面添加了一个事件处理示例。“Components”类的其余部分非常简单。只是通常的事件处理。我想知道是否在工作簿完全加载之前初始化了类,从而导致一些未定义的行为。您可以尝试在工作簿\打开事件中手动创建类;甚至可能使用Application.OnTime Now+TimeValue(“00:00:01”),“CreateComponentClass”
来确保一切就绪。根据创建对象的位置,可能需要全局声明变量,并在.xlam
中包含工厂方法,因为外接程序中的类最多只能是publicnotcreateable
。VERSION 1.0 CLASS
和属性VB_Exposed=False
之间的代码不是有效的VBA代码。在VBA编辑器中看到该代码部分了吗?请澄清
Workbooks.Open Filename:=lPath
Set WB = Workbooks(nameOfWB)