错误: 当您通过使用 ActiveX 数据对象 (ADO) 查询打开 Excel 工作表时,内存泄漏发生

文章翻译 文章翻译
文章编号: 319998 - 查看本文应用于的产品
展开全部 | 关闭全部

本文内容

症状

检索一个 Microsoft ActiveX 数据对象 (ADO) 时从内存泄漏,在 Excel 中打开的 Excel 工作表的记录集将出现在 Excel 的过程中。重复的查询可能最终会导致 Excel 在内存不足,无法运行,并引发错误,或导致 Excel 停止响应。

解决方案

通过关闭并释放 ADO 对象,无法回收所使用的 ADO 查询内存。要退出 Excel 是唯一的方法释放内存。

如有可能,请在仅在该文件不是在 Excel 中打开时,查询 Excel 工作表。

如果工作表必须保持打开状态 (例如在不断允许动态重新计算工作表数值) 使用下列方法之一解决该问题:

方法 1

  • 要将 Excel 数据导出到一个新的工作表中使用 SELECT INTO 语法在 Jet OLE DB 提供程序。有关使用 SELECT INTO 语法导出数据的其他信息请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
    295646如何将数据从 ADO 数据源传输到 Excel 用 ADO

方法 2

  • 使用 Excel 对象模型中的 工作簿 对象的 副本另存为 方法以编程方式保存打开的 Excel 文件,以新名称。然后,您可以查询以前从 ADO 应用程序的新名称保存该文件的副本。

状态

Microsoft 已经确认这是在本文开头列出的 Microsoft 产品中的错误。

更多信息

重现行为的步骤

  1. 创建或定位具有行和列,可使用 ADO 查询的数据的 Excel 工作表。例如对于您可以使用 Excel 从示例罗斯文 Access 数据库导入客户表。
  2. 在 Visual Basic 6.0 中创建标准 EXE 项目。默认状态下,创建 Form1。设置对 ADO 的引用。
  3. 将模块添加到该的项目,然后输入应用程序编程接口 (API) 调用,您可以检查内存使用情况,使用性能监视器计数器为下面的声明:
    Option Explicit
    
    'Performance monitor functions for Visual Basic from PDH.DLL
    Declare Function PdhVbOpenQuery Lib "pdh.dll" _
        (ByRef QueryHandle As Long) As Long
    Declare Function PdhCloseQuery Lib "pdh.dll" _
        (ByVal QueryHandle As Long) As Long
    Declare Function PdhVbAddCounter Lib "pdh.dll" _
        (ByVal QueryHandle As Long, ByVal CounterPath As String, _
        ByRef CounterHandle As Long) As Long
    Declare Function PdhRemoveCounter Lib "pdh.dll" _
        (ByVal CounterHandle As Long) As Long
    Declare Function PdhCollectQueryData Lib "pdh.dll" _
        (ByVal QueryHandle As Long) As Long
    Declare Function PdhVbGetDoubleCounterValue Lib "pdh.dll" _
        (ByVal CounterHandle As Long, ByRef CounterStatus As Long) As Double
    Declare Function PdhVbIsGoodStatus Lib "pdh.dll" _
        (ByVal StatusValue As Long) As Long
    Declare Function PdhVbGetOneCounterPath Lib "pdh.dll" _
        (ByVal PathString As String, ByVal PathLength As Long, _
        ByVal DetailLevel As Long, ByVal CaptionString As String) As Long
    Declare Function PdhVbCreateCounterPathList Lib "pdh.dll" _
        (ByVal DetailLevel As Long, ByVal CaptionString As String) As Long
    Declare Function PdhVbGetCounterPathFromList Lib "pdh.dll" _
        (ByVal Index As Long, ByVal Buffer As String, _
        ByVal BufferLength As Long) As Long
    Declare Function PdhVbGetCounterPathElements Lib "pdh.dll" _
        (ByVal PathString As String, ByVal MachineName As String, _
        ByVal ObjectName As String, ByVal InstanceName As String, _
        ByVal ParentInstance As String, ByVal CounterName As String, _
        ByVal BufferSize As Long) As Long
    					
  4. 将命令按钮添加到 Form1,然后再插入事件中的下面的代码。此代码重复查询 Excel 文件,并显示在调试 (即时) 窗口中的内存使用情况
        Dim cn As ADODB.Connection
        Dim rs As ADODB.Recordset
        Dim i As Integer
        Dim max As Integer
        Dim r As Long
        Dim hPDHQuery As Long            'Handle to performance monitor query
        Dim hPDHCounter As Long          'Handle to performance monitor counter
        Dim strCounterPath               'Path to performance monitor counter
        Dim lngCounterStatus As Long     'Status of counter when checked
        Dim dblPrivateBytes As Double    'Value of counter when checked
        Set cn = New ADODB.Connection
    'Jet connection string.
        cn.Open "Provider=Microsoft.Jet.OLEDB.4.0;" & _
            "Data Source=" & App.Path & "\test.xls;" & _
            "Extended Properties=Excel 8.0"
        'Initialize PDH query object.
        r = PdhVbOpenQuery(hPDHQuery)
        'Initialize counter.
    'Edit the value of the "strCounterPath" variable.
        strCounterPath = "\\<computername>\Process(Excel)\Private Bytes"
        r = PdhVbAddCounter(hPDHQuery, strCounterPath, hPDHCounter)
        'Gather data.
        r = PdhCollectQueryData(hPDHQuery)
        'Get counter value and process data.
        dblPrivateBytes = PdhVbGetDoubleCounterValue(hPDHCounter, _
            lngCounterStatus)
        If PdhVbIsGoodStatus(lngCounterStatus) Then
            Debug.Print "Memory used by Excel: " & CLng(dblPrivateBytes)
        Else
            Debug.Print "Invalid data."
        End If
    'Edit the value of the "max" variable.
        max = 100
        ReDim alngPrivateBytes(max)
        For i = 1 To max
            Set rs = New ADODB.Recordset
            rs.CursorLocation = adUseClient
    'Edit the query to reflect the name of the worksheet.
            rs.Open "SELECT * FROM [Customers$]", cn
            Do Until rs.EOF
                rs.MoveNext
            Loop
            rs.Close
            Set rs = Nothing
            r = PdhCollectQueryData(hPDHQuery)
            'Get counter value and process data.
            dblPrivateBytes = PdhVbGetDoubleCounterValue(hPDHCounter, _
                lngCounterStatus)
            'Process data.
            If lngCounterStatus = 0 Then
                Debug.Print "Memory used by Excel: " & CLng(dblPrivateBytes)
                alngPrivateBytes(i) = CLng(dblPrivateBytes)
            Else
                Debug.Print "Invalid data."
                alngPrivateBytes(0) = 0
            End If
        Next
        cn.Close
        Set cn = Nothing
        Debug.Print "Total increase for " & max & " iterations: " & _
            (CStr(alngPrivateBytes(max) - alngPrivateBytes(0)))
        Debug.Print "Average increase per iteration: " & _
            (CStr((alngPrivateBytes(max) - alngPrivateBytes(0))) / max)
        'Clean up.
        r = PdhRemoveCounter(hPDHCounter)
        r = PdhCloseQuery(hPDHQuery)
    					
  5. 在代码中进行以下更改:

    • 编辑 Jet 连接字符串以反映 Excel 测试文件的位置。
      注意:它注释,如下所示: Jet 连接字符串。
    • 编辑要使用本地工作站名称"strCounterPath"变量的值。
      注意:它注释,如下所示: 编辑"strCounterPath"变量的值。
    • 编辑查询以反映测试数据文件中工作表的名称。
      注意:它注释,如下所示: 编辑查询以反映工作表的名称。
    • 编辑所需的重复数为"最大"的变量的值。
      注意:它注释,如下所示: 编辑"最大"的变量的值。
  6. 运行 Excel 应用程序,然后打开测试 Excel 文件。
  7. 运行 Visual Basic 应用程序。请注意没有一个稳定增加所使用的 Excel 的过程中,尽管 ADO 对象已关闭和释放内存。

参考

有关更多的信息请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
257819如何用 Visual Basic 或 VBA 中的 Excel 数据使用 ADO
有关使用 Visual Basic 中的性能计数器的其他信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应的文章:
296526信息: 收集性能数据使用 PDH 从 Visual Basic 的 api
有关 Excel 导出选项的其他信息,请单击下面文章编号,以查看 Microsoft 知识库中相应的文章:
247412信息: 从 Visual Basic 传输到 Excel 的数据验证方法
246335如何将数据从 ADO 记录集传输到 Excel 的自动化

属性

文章编号: 319998 - 最后修改: 2007年2月12日 - 修订: 3.3
这篇文章中的信息适用于:
  • Microsoft Excel 2000 标准版
  • Microsoft OLE DB Provider for Jet 4.0
  • Microsoft Excel 97 标准版
  • Microsoft Excel 2002 标准版
关键字:?
kbmt kbado kbmemory kbperformance kbprogramming kbbug kbiisam kbjet kbnofix kbprovider KB319998 KbMtzh
机器翻译
注意:这篇文章是由无人工介入的微软自动的机器翻译软件翻译完成。微软很高兴能同时提供给您由人工翻译的和由机器翻译的文章, 以使您能使用您的语言访问所有的知识库文章。然而由机器翻译的文章并不总是完美的。它可能存在词汇,语法或文法的问题,就像是一个外国人在说中文时总是可能犯这样的错误。虽然我们经常升级机器翻译软件以提高翻译质量,但是我们不保证机器翻译的正确度,也不对由于内容的误译或者客户对它的错误使用所引起的任何直接的, 或间接的可能的问题负责。
点击这里察看该文章的英文版: 319998
Microsoft和/或其各供应商对于为任何目的而在本服务器上发布的文件及有关图形所含信息的适用性,不作任何声明。 所有该等文件及有关图形均"依样"提供,而不带任何性质的保证。Microsoft和/或其各供应商特此声明,对所有与该等信息有关的保证和条件不负任何责任,该等保证和条件包括关于适销性、符合特定用途、所有权和非侵权的所有默示保证和条件。在任何情况下,在由于使用或运行本服务器上的信息所引起的或与该等使用或运行有关的诉讼中,Microsoft和/或其各供应商就因丧失使用、数据或利润所导致的任何特别的、间接的、衍生性的损害或任何因使用而丧失所导致的之损害、数据或利润不负任何责任。

提供反馈

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com