关于vba:使用变量引用集合时”对象无效或不再设置”

“Object Invalid or no Longer Set” when using Variable to Reference Collection

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

1
2
3
4
5
6
7
8
9
10
11
Function ValidateFields(strTbl As String, arrReq As Variant) As Boolean
    Dim fld
    Dim fldTmp As Field
    On Error GoTo err
    For Each fld In arrReq
        Set fldTmp = CurrentDb.TableDefs(strTbl).Fields(fld)
    Next fld
    ValidateFields = True
err:
    Exit Function
End Function
1
2
?ValidateFields("TempTable", Array("Field1","Field2","Field3"))
False

这按预期执行,但是为了提高效率,我尝试将Fields Collection分配给For Each循环之外的变量:

1
2
3
4
5
6
7
8
9
10
11
12
13
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)

Run-time error '3420':
Object invalid or no longer set.

为什么变量colFldFor Each循环中丢失其值?


这里的问题是:

CurrentDb创建当前打开的数据库的DAO.Database对象。您的TableDef是该成员。

但是由于您没有存储该对象,因此在将tabledef复制到对象后,它会立即关闭并释放,并且成员也将被释放。

存储数据库对象,成员也将保留:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
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