Vba &引用;对象无效或不再设置";使用变量引用集合时

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”、

在回答的过程中,我编写了一个简单的函数来测试MS Access表是否包含所提供数组中的所有字段:

函数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标记是。我不太喜欢这个过程,但它已经完成,不值得对抗。