【问题标题】:How to save Access query result into an object in VBA?如何将 Access 查询结果保存到 VBA 中的对象中?
【发布时间】:2020-01-05 05:08:46
【问题描述】:

我无法将 Access 查询的整个结果写入对象。

这是一个示例代码。

Sub test()

Dim cn As Object
Dim strConnection As String
Dim rs As Object

Set cn = CreateObject("ADODB.Connection")
strConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Test.mdb;Jet OLEDB:Database Password=pass;"

cn.Open strConnection

'Write some test data
cn.Execute ("CREATE TABLE TestTable (ID int, Column_1 varchar(255), Column_2 varchar(255));")
cn.Execute ("INSERT INTO TestTable (ID, Column_1, Column_2) VALUES (1, ""Foo"", ""Bar"")")
cn.Execute ("INSERT INTO TestTable (ID, Column_1, Column_2) VALUES (2, ""Bar"", ""Foo"")")
cn.Execute ("INSERT INTO TestTable (ID, Column_1, Column_2) VALUES (3, ""FooBar"", ""BarFoo"")")

'Get the data
Set rs = cn.Execute("SELECT * FROM TestTable")

cn.Close

End Sub

在查看监视列表上的 rs 时,我似乎只得到第一行,在字段下有项目 1 = 1、项目 2 = Foo、项目 3 = 栏。

在带有 PyODBC 的 Python 上,我习惯使用 fetchall 方法,但对于 ADODB,我没有找到类似的方法。

在访问时,查询返回所有 3 行。

对象类型是否错误?我也试过“Set rs = New ADODB.Recordset”,但它也有帮助。那么如何将所有 3 行写入对象呢?

【问题讨论】:

    标签: excel vba ms-access adodb


    【解决方案1】:

    大致相当于FetchAllGetRows

    Dim cn As Object
    Dim strConnection As String
    Dim rowdata As Variant
    
    Set cn = CreateObject("ADODB.Connection")
    strConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=C:\Test.mdb;Jet OLEDB:Database Password=pass;"
    
    cn.Open strConnection
    
    'Write some test data
    cn.Execute ("CREATE TABLE TestTable (ID int, Column_1 varchar(255), Column_2 varchar(255));")
    cn.Execute ("INSERT INTO TestTable (ID, Column_1, Column_2) VALUES (1, ""Foo"", ""Bar"")")
    cn.Execute ("INSERT INTO TestTable (ID, Column_1, Column_2) VALUES (2, ""Bar"", ""Foo"")")
    cn.Execute ("INSERT INTO TestTable (ID, Column_1, Column_2) VALUES (3, ""FooBar"", ""BarFoo"")")
    
    'Get the data
    rowdata = cn.Execute("SELECT * FROM TestTable").GetRows()
    
    cn.Close
    

    通常,首选使用记录集,因为记录集仅在需要时加载数据(例如,当您使用 rs.MoveNext 时,会加载下一条记录,而不是立即加载它),并且记录集链接到数据源, so 可用于在表中插入新行。 GetRows 在 VBA 中的用例很少。

    【讨论】:

    • 虽然这基本上符合我的要求,但结果对我来说是不合逻辑的。 Rowdata(0) 包含值 1、2、3。对我来说,如果 rowdata(0) 具有值 1、Foo、Bar 会更合乎逻辑。
    • 好吧,我对此无能为力。如果您想逐行访问值,只需导航记录集,这也带来了额外的性能优势。您可以转置数组,但我强烈建议您不要转置,因为这是一项非常耗费资源的操作,需要将整个数组复制到内存中。
    • 我将了解有关记录集的更多信息,以便我可以使用您推荐的方式。感谢您的回答。
    【解决方案2】:

    首先,我不推荐 GetRows,除非你想从一个非常棒的、具有很好字段的奇妙记录集对象、movenext 等转到一个难以处理的多维数组。

    接下来:

    当您使用 rs.execute 时,您会得到一个只向前的记录集,并且您只能检查现有记录的记录计数(它始终为 -1)。因此,您只能使用 .recordCount 检查记录 - 而不是获取实际记录数。

    由于上述原因,您要在打开命令中指定“光标”类型。

    所以,使用:

    Dim strSQL     As String
    
    strSQL = "select * from tblHotels where City like 'Edmon%' "
    
    rstD.CursorLocation = adUseClient
    rstD.Open strSQL, rstDCon
    Debug.Print rstD.RecordCount
    

    还有其他几种设置游标(记录集)类型的方法,你也可以这样: rstD.CursorLocation = adUseClient,但在大多数情况下,执行命令将覆盖该设置。由于您需要额外的代码行,因此只需使用记录集的 .Open 方法即可。

    所以:

    'Get the data
    Set rs = cn.Execute("SELECT * FROM TestTable")
    

    变成

    'Get the data
    rs.Open "SELECT * FROM TestTable", cn, adUseClient
    debug.print rs.RecordCount
    

    不清楚您是否使用后期绑定,因此您必须将常量 adUseClient 替换为 3

    例如:

    'Get the data
    rs.Open "SELECT * FROM TestTable", cn, 3
    debug.print rs.RecordCount
    

    【讨论】:

    • 我收到错误 424,rs.Open 行需要对象。我尝试了你所有的例子。
    猜你喜欢
    • 1970-01-01
    • 2012-07-15
    • 2014-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多