【问题标题】:VBA ADO Recordset .Copyfromrecordset long runtimeVBA ADO Recordset .Copyfromrecordset 长时间运行
【发布时间】:2019-05-17 00:07:25
【问题描述】:

我正在搜索可以修复此运行时构建的 VBA 代码,或有关可能导致此问题的建议。

我正在运行一个 VBA 脚本,该脚本使用 ADODB 从 SQL Server 数据库中检索数据。我已经在将数据复制到我的 Excel 工作表中的行上运行了运行时测试。运行时间是变化的;但是,我发现该行的运行时间在 3-30 秒之间:

Sheets(1).range("A8").CopyFromRecordset recordSet

记录集中的数据由 300 行和 13 列组成。

我觉得奇怪的一点是,当 excel 应用程序关闭并重新打开时,运行时似乎恢复正常。

以下是对 .copyfromrecordset 行的每个测试的运行时概念:

  • 测试 1:3 秒
  • 测试 2:3 秒
  • 测试 3:3 秒
  • 测试 4:5 秒
  • 测试 5:5 秒
  • 测试 6:6 秒
  • 测试 7:7 秒
  • 测试 8:6 秒
  • 测试 9:8 秒
  • 测试 9:10 秒
  • ...
  • 测试 20:24 秒

我对本地命令进行了测试,例如格式化单元格宽度/高度,这些运行时间恒定为 1 或 2 秒。

也许我错误地使用了记录集,或者如果没有找到解决方案,我只会减少数据库调用,这会阻止我获得最新数据。

我已经检查并检查了我认为可能是问题的任何未关闭的记录集对象,但没有任何东西是打开的。

Function Query(SQL As String)

Dim recordSet As ADODB.recordSet
Dim Field As ADODB.Field
Set recordSet = New ADODB.recordSet
recordSet.Open SQL, Conn, adOpenForwardOnly, adLockReadOnly, adCmdTxt

If recordSet.State Then

    'seting up table headers
    Dim i As Integer
    For i = 0 To recordSet.Fields.Count - 1
    Sheets(1).Cells(7, 1 + i).value = recordSet.Fields(i).name
    Next i
    Sheets(1).range("A7:M7").Font.Bold = True

    t = Now()
    'insert recordset data into cells
    Sheets(1).range("A8").CopyFromRecordset recordSet
    MsgBox Format(Now() - t, "hh:mm:ss")**

    'close recordset object
    recordSet.Close
    Set recordSet = Nothing
End If


End Function

数据库连接

Function ConnectToDB(Server As String, Database As String) As Boolean

    Set Conn = New ADODB.Connection
    On Error Resume Next

    Conn.ConnectionString = "Provider=SQLOLEDB; Integrated Security=SSPI; Data Source=" & Server & "; Initial Catalog=" & Database & ";"
    Conn.Open

    If Conn.State = 0 Then
        ConnectToDB = False
    Else
        ConnectToDB = True
    End If

End Function

【问题讨论】:

  • 这不可能是你的全部代码。你在哪里设置连接?
  • @kyle 添加 db 连接功能
  • 作为替代方案,您可以尝试“数据”选项卡 >“从其他来源”查看是否更快或 Power Query
  • 我在ADODB.CopyFromRecordset 方面拥有丰富的经验(超过几年),这是将记录集放入文件的最快方法。我运行这条线的时间从未超过 1-2 秒(即使是几千行或数据作为回报)。关闭连接不是问题,因为它们会在函数终止时自动关闭 (scope of variables)。您确定这一行花费了这么长时间(并且没有运行查询)吗?我没有在你的函数中看到任何时间跟踪该行。
  • 另外,您是否在粘贴新数据之前清理工作表?如果您只是在每次新数据时插入(或附加),那么.UsedRange 会稳步增加,这可能是工作表的性能问题。确保在粘贴时关闭 .ScreenUpdating.Calculation 和/或不可见工作表(要粘贴到的位置)。我当然希望你在那张纸上没有任何事件。否则,您也应该为该过程关闭事件。工作表或形状/控件/按钮等是否有任何保护?

标签: vba excel adodb


【解决方案1】:

我遇到了同样的问题。通过一些代码一次单步执行一行,我隔离了 CopyFromRecordset 命令的两个实例,在处理具有大约 30K - 40K 记录的记录集时大约需要 5 - 6 分钟才能完成。这是一本包含许多公式的庞大工作簿。添加行:

Application.Calculation = xlManual

到宏的开头将整个过程的时间从大约 10 - 12 分钟减少到只有 30 - 40 秒。

这可以防止 Excel 尝试重新计算大量工作簿中每个公式的值,同时将数万条记录中的每条记录复制到工作表中。宏后面还有一行代码将行为恢复为默认值:

Application.Calculation = xlAutomatic

【讨论】:

    猜你喜欢
    • 2018-04-07
    • 1970-01-01
    • 1970-01-01
    • 2016-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-29
    相关资源
    最近更新 更多