Excel -Access DB -ADO。内存泄漏->系统资源超出

问题描述 投票:0回答:3

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

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

我在这里面临的问题是内存使用量总是随着excel的增加而增加。看来access db处理也被添加到excel本身了。所以最终我得到了错误

"System Resource Exceeded"

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

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

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

看到不同的相关文章。但大多数人都在讨论同一个 Excel 文件中的数据。就我而言,内存或 Excel 文件中没有保存任何数据。

我在这里看到了微软的一篇文章,其中也谈到了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

这有点帮助。

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

vba ms-access excel-2010 adodb
3个回答
3
投票

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

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

  1. “退出 Excel”意味着必须关闭您正在使用的当前工作簿,或者

  2. “退出 Excel”意味着退出 Excel 的所有实例,以便有效地将 Excel 从内存中删除。

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

广告 2:在这种情况下,您可以使用例如Word 启动一个新的 Excel.Application 实例,并以与 1 相同的方式进行。只是希望 MS-Office 集成度不要太高,以至于 ADO DLL 在任何 Office 程序运行时都不会退出...

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


0
投票

我建议使用

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

0
投票

用这个

strSystemIDT = Trim(DirPath.Path) + "\IDT.accde" 'mde" 使用 IDTdbCnnctn .连接超时= 30 .Open "Provider=Microsoft.ACE.OLEDB.12.0 ;数据源=" & Trim(strSystemIDT) & ";Jet OLEDB:数据库密码=" & Trim(strPblcPswrdIs) & "" .Properties("Jet OLEDB:每个文件的最大锁定数") = 50000 '9500 .Properties("Jet OLEDB:独占异步延迟") = 0 .Properties("Jet OLEDB:刷新事务超时") = 25000 .Properties("Jet OLEDB:锁定延迟") = 10 '0 '00 .Properties("Jet OLEDB:锁定重试") = 20 .Properties("Jet OLEDB:最大缓冲区大小") = 100000 .Properties("Jet OLEDB:页面超时") = 25000 .Properties("Jet OLEDB:共享异步延迟") = 0 .Properties("Jet OLEDB:回收长值页面") = 0 ' .Properties("Jet OLEDB:事务提交模式") = 1 ' .Properties("Jet OLEDB:用户提交同步") = 1 结束于

© www.soinside.com 2019 - 2024. All rights reserved.