7

我在网上找到了这段代码来查询Access并将数据输入到excel(2003)中,但它比应该的要慢得多:

Sub DataPull(SQLQuery, CellPaste)
Dim Con As New ADODB.Connection
Dim RST As New ADODB.Recordset
Dim DBlocation As String, DBName As String
Dim ContractingQuery As String

If SQLQuery = "" Then

Else
    DBName = Range("DBName")
    If Right(DBName, 4) <> ".mdb" Then DBName = DBName + ".mdb"

    DBlocation = ActiveWorkbook.Path
    If Right(DBlocation, 1) <> "\" Then DBlocation = DBlocation + "\"

    Con.ConnectionString = DBlocation + DBName
    Con.Provider = "Microsoft.Jet.OLEDB.4.0"
    Con.Open

    Set RST = Con.Execute(SQLQuery)
    Range(CellPaste).CopyFromRecordset RST

    Con.Close
End If

End Sub

问题是这段代码需要很长时间。如果我打开 Access 并在其中运行查询,则大约需要 1/10 的时间。有没有办法加快这个速度?或者有什么原因可能需要这么长时间?我所有的查询都是简单的选择查询,带有简单的 where 语句并且没有连接。即使是select * from [test]查询也比它应该花费的时间要长得多。

编辑:我应该指定该行

Range(CellPaste).CopyFromRecordset RST

是一个需要很长时间的人。

4

10 回答 10

3

我不是专家,但我运行几乎完全相同的代码,结果很好。一个区别是我使用Command对象以及Connection对象。你在哪里

Set RST = Con.Execute(SQLQuery)

一世

Dim cmd As ADODB.Command
Set cmd.ActiveConnection = con
cmd.CommandText = SQLQuery
Set RST = cmd.Execute

我不知道这是否或为什么会有所帮助,但也许会?:-)

于 2009-10-15T19:08:50.457 回答
2

我不认为你是在比较同类。

在 Access 中,当您查看查询的数据视图时,会发生以下情况:

  • 使用现有的打开连接(并保持打开);
  • 记录集仅由前几行部分填充(并保持打开状态);
  • 部分结果集显示在专用于任务的网格中,并针对 Access 采用的本机数据访问方法进行了优化(可能直接使用 Access 数据库引擎 DLL)。

在您的 VBA 代码中:

  • 打开一个新连接(然后关闭并释放);
  • 使用所有行完全填充记录集(然后关闭并释放);
  • 使用非本地数据访问组件将整个结果集读入 Excel 的通用 UI。

我认为最重要的一点是,Access 中的数据视图在您要求它之前不会获取整个结果集,通常是通过导航到结果集中的最后一行。ADO 将始终获取结果集中的所有行。

第二个最重要的是将提取的行(假设是完整的结果集)读入 UI 元素所花费的时间,并且 Excel 并未针对该作业进行优化。

打开、关闭和释放连接和记录集应该无关紧要,但仍然是一个因素。

我认为您需要对流程的每个步骤进行一些计时以找到瓶颈。与 Access 进行比较时,请确保您获得完整的结果集,例如检查返回的行数。

于 2009-10-16T07:49:58.600 回答
1

我建议您Recordset使用该方法显式创建而不是隐式 创建Execute。显式创建时,您可以设置对性能有影响的 CursorType 和 LockType 属性。

据我所知,您正在 Excel 中加载数据,然后关闭记录集。您不需要更新、计算记录等...所以我的建议是创建一个Recordsetwith CursorType = adOpenForwardOnly & LockType = adLockReadOnly

...
RST.Open SQLQuery, Con, adOpenForwardOnly, adLockReadOnly
Range(CellPaste).CopyFromRecordset RST
...

Recordset Object (ADO)

于 2009-10-15T19:09:18.503 回答
1

由于您使用的是 Access 2003,请改用 DAO,Jet 引擎会更快。

有关示例代码,请参见http://www.erlandsendata.no/english/index.php?d=envbadacexportdao

请注意,您永远不应该使用“As New”关键字,因为它会导致意想不到的结果。

于 2009-10-15T19:10:43.180 回答
1

我使用了您的代码,并在不到 7 秒的时间内拉入了一个包含 38 列和 63780 行的表——大约是我所期望的——并且几乎立即完成了较小的记录集。

这是你正在经历的那种表现吗?如果是这样,这与我对从 Excel 到 MDB 后端的 ADO 连接的期望一致。

如果您看到的性能比这慢得多,那么一定有一些当地的环境条件正在影响事情。

于 2009-10-16T06:21:55.393 回答
1

许多公式可能会引用查询。尝试在宏中临时打开手动计算,并在所有查询完成更新后将其关闭。

这应该会加快速度,但仍然不能解决根本问题。

于 2009-10-20T15:03:49.230 回答
0

如果您检索大量记录,它将解释为什么Range(CellPaste)需要这么长时间。(如果您在 Access 中执行查询,它不会检索所有记录,但如果您执行 CopyFromRecordset,它需要所有记录。)

CopyFromRecordset 有一个 MaxRows 参数:

Public Function CopyFromRecordset ( _
    Data As Object, _
    <OptionalAttribute> MaxRows As Object, _
    <OptionalAttribute> MaxColumns As Object _
) As Integer

尝试将其设置为较低的值(例如 10 左右)是否会改变性能。

于 2009-10-15T20:28:53.900 回答
0

以下周转或改进怎么样:

  1. 打开后,将记录集保存为 xml 文件 (rst.saveToFile xxx),然后让 Excel 重新打开它。
  2. 打开后,将记录集数据放入数组(rst.getRows xxx),然后将数组复制到活动工作表上
  3. 并且,在任何时候,最小化所有内存/访问要求:以只读方式打开记录集,只转发,一旦数据在您身边就关闭连接等。
于 2009-10-15T20:32:47.053 回答
0

我不知道它是否会有所帮助,但我正在使用 VBA 和 ADO 连接到 Excel 电子表格。

它以闪电般的速度检索记录(<5 秒),但突然之间它变得非常慢(检索一条记录需要 15 秒)。这就是让我看到你的帖子的原因。

我意识到我不小心打开了 Excel 文件(我一直在编辑它)。

一旦我关闭它,一切都再次快速闪电。

于 2013-05-13T19:41:22.563 回答
0

10 次中有 9 次出现问题与您使用的光标类型/位置有关。

在网络连接上使用动态游标会减慢数据的检索速度,即使查询执行得非常快。

如果您想快速获取大量数据,则需要在连接上使用 CursorLocation = adUseClient。这意味着您将只有一个静态本地游标,因此您不会从其他用户那里获得实时更新。

但是 - 如果您只是读取数据,您将保存 ADO 并返回到数据库中以检查每个单独的记录以检查更改。

I recently changed this as I had a simple loop, populating a list item, and each loop was taking around 0.3s. Not to slow, but even on 1,000 records thats 30 seconds! Changing only the cursor location let the entire process complete in under 1 second.

于 2015-04-29T14:03:19.193 回答