Vba &引用;对象无效或不再设置";使用变量引用集合时
在回答的过程中,我编写了一个简单的函数来测试MS Access表是否包含所提供数组中的所有字段:Vba &引用;对象无效或不再设置";使用变量引用集合时,vba,ms-access,Vba,Ms Access,在回答的过程中,我编写了一个简单的函数来测试MS Access表是否包含所提供数组中的所有字段: 函数ValidateFields(strTbl作为字符串,arrReq作为变量)作为布尔值 模糊fld Dim fldTmp As字段 上错下错 对于arrReq中的每个fld 设置fldTmp=CurrentDb.TableDefs(strTbl).Fields(fld) 下一个fld ValidateFields=True 错误: 退出功能 端函数 ?验证字段(“可诱惑的”、数组(“字段1”、
函数ValidateFields(strTbl作为字符串,arrReq作为变量)作为布尔值
模糊fld
Dim fldTmp As字段
上错下错
对于arrReq中的每个fld
设置fldTmp=CurrentDb.TableDefs(strTbl).Fields(fld)
下一个fld
ValidateFields=True
错误:
退出功能
端函数
?验证字段(“可诱惑的”、数组(“字段1”、“字段2”、“字段3”))
假的
但是,这正如预期的那样执行,为了提高效率,我尝试为每个循环将Fields集合分配给之外的变量:
Function ValidateFields(strTbl As String, arrReq As Variant) As Boolean
Dim fld
Dim fldTmp As Field
Dim colFld As Fields
Set colFld = CurrentDb.TableDefs(strTbl).Fields
On Error GoTo err
For Each fld In arrReq
Set fldTmp = colFld(fld)
Next fld
ValidateFields = True
err:
Exit Function
End Function
现在,如果我注释掉On Error
语句,我将收到以下错误,突出显示行Set fldTmp=colFld(fld)
,作为原因:
运行时错误“3420”:
对象无效或不再设置
为什么变量colFld
会在每个循环的中丢失其值?这里的问题是:
CurrentDb
创建当前打开数据库的DAO.Database
对象。您的TableDef
就是其中的一员
但是,由于您没有存储该对象,因此在您将tabledef复制到对象之后,它会立即关闭并释放,并且成员也会随之释放
存储数据库对象,成员也将保持:
Function ValidateFields(strTbl As String, arrReq As Variant) As Boolean
Dim fld
Dim fldTmp As Field
Dim colFld As Fields
Dim db As DAO.Database
Set db = CurrentDb
Set colFld = db.TableDefs(strTbl).Fields
On Error GoTo err
For Each fld In arrReq
Set fldTmp = colFld(fld)
Next fld
ValidateFields = True
err:
Exit Function
End Function
这里的问题是:
CurrentDb
创建当前打开数据库的DAO.Database
对象。您的TableDef
就是其中的一员
但是,由于您没有存储该对象,因此在您将tabledef复制到对象之后,它会立即关闭并释放,并且成员也会随之释放
存储数据库对象,成员也将保持:
Function ValidateFields(strTbl As String, arrReq As Variant) As Boolean
Dim fld
Dim fldTmp As Field
Dim colFld As Fields
Dim db As DAO.Database
Set db = CurrentDb
Set colFld = db.TableDefs(strTbl).Fields
On Error GoTo err
For Each fld In arrReq
Set fldTmp = colFld(fld)
Next fld
ValidateFields = True
err:
Exit Function
End Function
可能还需要添加一个奇怪的事实,即DAO.Recordset有一个`.Parent`属性,该属性防止数据库的副本(通常等于dbengage(0)(0))被销毁,因为该副本仍然是Recordset.Parent中的一个引用,指向该副本。还有警告不要在循环中使用(例如,对于n=1到10000 CurrentDb.Execute SQL Next n
)应该是强制性的。对象实例的范围对此也很重要。也许可以添加一个奇怪的事实,即DAO.recordset有一个阻止数据库复制的“.Parent”属性(通常等于dbengage(0)(0))由于仍保留在记录集中的引用而被销毁。父项指向该副本。警告不要在循环中使用(例如,对于n=1到10000 CurrentDb.Execute SQL Next n
)应该是强制性的。对象实例的范围对此也很重要。请注意,*-vba标记是。我不太喜欢这个过程,但它已经完成,不值得对抗。请注意,*-vba标记是。我不太喜欢这个过程,但它已经完成,不值得对抗。