使用变量引用集合时出现“对象无效或不再设置”

Lee*_*Mac 1 ms-access vba

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

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
Run Code Online (Sandbox Code Playgroud)
?ValidateFields("TempTable", Array("Field1", "Field2", "Field3"))
False
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

现在,如果我注释掉该On Error语句,则会收到以下错误,其中Set fldTmp = colFld(fld)突出显示的行是原因:

运行时错误“3420”:

对象无效或不再设置。

为什么变量colFld会在For Each循环中丢失其值?

Eri*_*k A 5

这里的问题是:

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
Run Code Online (Sandbox Code Playgroud)

  • 也许添加一个奇怪的事实,即 DAO.Recordsets 有一个`.Parent` 属性,它可以防止数据库的副本(通常等于 DbEnginge(0)(0)`)被销毁,因为它仍然是 Recordset.Parent 中的一个引用`,指向那个副本。 (2认同)
  • 并且警告不要在循环中使用(例如`For n = 1 to 10000 CurrentDb.Execute SQL Next n`)应该是强制性的。 (2认同)