通过(动态)名称声明一个新的 DAO.Recordset

Posted

技术标签:

【中文标题】通过(动态)名称声明一个新的 DAO.Recordset【英文标题】:Declare a new DAO.Recordset by (dynamic) name 【发布时间】:2015-01-31 01:53:17 【问题描述】:

这是用于创建 DAO 记录集的typical example:

Private Sub OpenOneRecordset()

        Dim dbExercise As DAO.Database
        Dim rsEmployees As DAO.Recordset

        Set dbExercise = CurrentDb
        Set rsEmployees = dbExercise.OpenRecordset("Employees")

        dbExercise.Close
        Set dbExercise = Nothing

End Sub

我想创建多个记录集,一个用于在数组中找到的每个名称:

Public Sub OpenAllRecordsets()

    Dim dbExercise As DAO.Database
    Set dbExercise = CurrentDb

    For Each varTable In arrTables

        strRecordsetName = "rst" & varTable

        ''Above is a string...
        ''How can I use the string to declare this object?

        ''  !!!!!!!!! OBVIOUSLY THIS WON'T WORK...
        Dim strRecordsetName As DAO.Recordset
        Set strRecordsetName = dbExercise.OpenRecordset(varTable)

    Next

    dbExercise.Close
    Set dbExercise = Nothing

End Sub

我看不到如何动态声明名称,然后用它来制作记录集。我认为这与TableDefs 类似,我在其中调用集合并添加成员。你觉得呢?

在第一个发布的答案之后更新:

我在递归函数中使用这些记录集。它有效,但我想减少运行时间。我一直在为所需的新记录重新创建每个记录集。

If nodeThis.hasChildNodes Then

    strTable = nodeThis.parentNode.nodeName

    Dim rsNewChild As DAO.Recordset         ' ***
    Set rsNewChild = cnn.OpenRecordset(strTable, dbOpenDynaset)  ' ***

    rsNewChild.AddNew

    '' ...populate fields
    For Each ...
        strName = nodeThis.nodeName            
        rsNewChild(strName) = nodeThis.Text
    Next

    rsNewChild.Update

    rsNewChild.close             ' ***
    Set rsNewChild = Nothing     ' ***

End If

但我知道需要哪些记录集,所以我宁愿在开始时将它们全部打开,然后根据需要调用。这会让我删除标记为*** 的行。那么问题是如何使用字符串(在函数中可用)来调用给定的记录集。

为了更正确、更有帮助地重新陈述目标:我需要获取一个字符串并使用它来调用所需的记录集:

[ BASED ON STRING ].AddNew 

对于 Barranka 的解决方案,我担心每次调用都会循环遍历该数组的资源。但我会试一试,做一些测试。

【问题讨论】:

【参考方案1】:

正如 TableDefsTableDef 对象的内置 Collection 一样,您可以创建自己的 Collection Recordset 对象并按名称引用它们,如下所示:

Dim cdb As DAO.Database, rst As DAO.Recordset, myRecordsets As Collection
Dim testArray(1) As String, tblName As Variant

' test data
testArray(0) = "People"
testArray(1) = "OtherPeople"

' build the collection
Set myRecordsets = New Collection
Set cdb = CurrentDb
For Each tblName In testArray
    Set rst = cdb.OpenRecordset(tblName, dbOpenTable)
    myRecordsets.Add rst, tblName
    Set rst = Nothing
Next

' use the members of the collection
Debug.Print myRecordsets("People").Fields("LastName").Value
myRecordsets("People").MoveNext
Debug.Print myRecordsets("People").Fields("LastName").Value
Debug.Print myRecordsets("OtherPeople").Fields("LastName").Value

Set myRecordsets = Nothing
Set cdb = Nothing

(注意Collections对象的.Add方法的参数是value, key,这与Dictionary的方式相反,其他关联数组在添加新条目时倾向于对其参数进行排序。 )

编辑回复:更新问题

这也有效

' add a new record
myRecordsets("OtherPeople").AddNew
myRecordsets("OtherPeople").Fields("LastName").Value = "NewPerson"
myRecordsets("OtherPeople").Update

【讨论】:

不错。您是否能够找到一种方法让 Intellisense 在myRecordsets("People"). 之后显示记录集方法和属性? @HansUp 在 VBA 下我不认为 IntelliSense 是一个选项,因为 VBA Collection 是任意对象的集合。 AFAIK 无法像在 VB.NET 中那样输入值(或键),我们可以在其中使用Dim myRecordsets As New Dictionary(Of String, Recordset) 接收read-to-go测试代码是一种特权。复制、粘贴、运行。 @HansUp ,您可以通过编写自定义集合类让 Intellisense 显示底层对象的成员。此类必须是Collection 对象的包装器,在文本编辑器中进行操作以允许默认成员,在这种情况下,集合的Item 属性重新转换为Recordset 对象。不过这很麻烦!【参考方案2】:

我会创建一个记录集数组:

dim rs() as DAO.Recordset
' You must redim the array with something like: ReDim rs(1 to UBound(arrTables))
dim i as Integer
' ...
i = 1
for each varTable in arrTables
    Set rs(i) = dbExcercise.openRecordset(varTable)
    i = i + 1;
next varTable

【讨论】:

听起来不错。为了向特定记录集添加记录,我是否必须遍历所有成员并根据rs(i).Name 检查我的姓名?我很确定这是 VBA 数组通常需要的……但是您知道快捷方式吗? 这是一个运行时速度问题。我有很多写操作。如果我可以独立定义记录集而不是运行循环来获取所需的记录集,那似乎更有效。 考虑使用集合或字典来保存以表名作为键的记录集,而不是数组。然后,您可以通过其表名键直接引用任何特定的记录集。 查看here 了解有关收藏的信息...我自己从未使用过它们,但这似乎是个好主意

以上是关于通过(动态)名称声明一个新的 DAO.Recordset的主要内容,如果未能解决你的问题,请参考以下文章

php中的动态函数名

window[name] 相当于动态访问 const 和 let 声明

Django 动态名称属性并在views.py 中获取值

python动态类型

ES6(2015)新的声明方式 letconst

动态创建多个数组