【问题标题】:Excel -Access DB -ADO. Memory Leak-> System Resource ExceededExcel -Access DB -ADO。内存泄漏-> 系统资源超出
【发布时间】:2016-08-11 09:20:46
【问题描述】:

我正在使用 Excel VBA 清理大型 csv 文件。为此,我将 csv 文件加载到访问数据库中,然后使用 sql 查询执行所有数据转换活动。所以抽象的过程是这样的

打开 Excel --> 在开始时单击创建一个 access 数据库 --> 将 csv 文件加载到不同的表中 --> 使用 aoddb 连接在数据库上执行不同的 DDl 和 DML 语句 --> 输出最终数据。

我在这里面临的问题是内存使用量总是随 excel 上升。似乎访问数据库处理也被添加到excel本身。所以最终我得到了错误"System Resource Exceeded"

每次执行查询时。内存使用率上升,永远不会下降。查询涉及 3-4 个表中大约 10k 到 100k 条记录。

为什么内存使用量永远不会下降?

每次我执行 ddl/dml 查询时,我都会打开 adodb 连接并关闭它。我在使用后关闭所有记录集并设置为空。但是内存使用量仍然没有下降。

看到不同的文章相关。但大多数人都在讨论同一个 excel 文件中的数据。在我的情况下,没有数据保存在内存或 excel 文件中。

我在这里看到了 Microsoft 的一篇文章,其中也谈到了 excel 本身中的数据。 https://support.microsoft.com/en-us/kb/319998

请问有人知道解决方法吗?

例如:要将数据从 csv 文件加载到表中,我使用以下代码

 StrSql = "SELECT * into " & TableName & " FROM [Text;FMT=Delimited;HDR=YES;DATABASE=" & DSPath & "].[" & DSName & "]"
    ExecuteSQL StrSql


Private Function ExecuteSQL(Sql As String) As Long
  Dim Con As ADODB.Connection
  Dim I As Long

  Connect Con
  Con.Execute Sql, I
  ExecuteSQL = I
  CloseCon Con
End Function

Public Sub CloseCon(ByRef Con As ADODB.Connection)
  If Not Con Is Nothing Then
     If Con.State = adStateOpen Then
        Con.Close
        Set Con = Nothing
     End If
  End If
End Sub

Public Sub Connect(ByRef Con As ADODB.Connection)
Dim ConStr As String

If Not Con Is Nothing Then
    If Con.State = adStateOpen Then
        Exit Sub
    End If
End If
On Error GoTo err
    CloseCon Con
    Set Con = New ADODB.Connection
    ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & DBFile & ";Persist Security Info=False"
    Con.Open ConStr, , , -1
    Exit Sub
err:
End Sub

这有点帮助。

我尝试使用一个公共连接对象,而不是每次打开和关闭时都使用单独的连接对象,它从一开始就打开,仅在进程完成时关闭。这样内存消耗减少了,进程运行时间更长

【问题讨论】:

  • 为什么不直接在 Access 中完成所有这些操作?似乎不需要从 Excel 去操作 Access。
  • 我们没有安装访问用户界面。只需使用喷气发动机。所以用户可以打开excel工具并提供输入。
  • 能贴出代码吗?
  • 它在vba中有很多功能。请看上面我使用的一些示例代码
  • 仅当文件也在 Excel 中打开时才会发生内存泄漏。确保您查询的文件不是由 Excel 本身打开的。仅使用 ADO 连接打开它们。

标签: vba ms-access excel-2010 adodb


【解决方案1】:

您的代码看起来不错。问题是 Microsoft 在您的参考资料中确认:“ADO 查询使用的内存无法通过关闭和释放 ADO 对象来回收。释放内存的唯一方法是退出 Excel。

所以我们必须不时退出 Excel 以回收资源。

  1. “退出 Excel”表示必须关闭您正在从中工作的当前工作簿,或者

  2. “退出 Excel”表示退出所有 Excel 实例,以便有效地从内存中删除 Excel。

广告。 1:在这种情况下,您可以创建一个“父工作簿”来启动另一个包含 ADODB 处理的一部分的工作簿。它在部分处理后退出,您的父母开始一个新的、其他的工作簿,继续处理等等。使用一些智能剪切和粘贴来调整退出每个工作簿的时间。

广告 2:在这种情况下,您使用例如Word 启动一个新的 Excel.Application 实例并按照与 1 相同的方式进行操作。只是希望 MS-Office 没有集成到任何 Office 程序运行时 ADO DLL 不会退出...

当然,向您的 IT 部门抱怨 Microsoft 确认的错误以安装 Access UI 可能会更好。

【讨论】:

  • 嗯是的,这是有道理的。即使它涉及相当多的开销。看起来没有其他解决方法。无论如何,我发现我在问题本身中发布的连续打开和关闭连接的一个部分问题
【解决方案2】:

我建议不要使用辅助函数手动尝试优雅地管理对象,而是使用With 块来控制 VBA 中所有对象的范围。

这是使用您的代码的示例:

Private Function ExecuteSQL(DBFile As String, Sql As String) As Long
    Dim I As Long

    With Connect(DBFile)
        .Execute Sql, I
        .Close
    End With
    
    ExecuteSQL = I
End Function

Public Function Connect(ByVal DBFile As String) As ADODB.Connection
    On Error GoTo err
    Set Connect = New ADODB.Connection
    
    Dim ConStr As String
    ConStr = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & DBFile & ";Persist Security Info=False"
    Connect.Open ConStr, , , -1
    
    Return
    
err:

End Function

【讨论】:

    猜你喜欢
    • 2013-11-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-03
    • 1970-01-01
    • 1970-01-01
    • 2020-03-11
    • 1970-01-01
    相关资源
    最近更新 更多