Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/excel/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Excel 使用数组分配范围时出现VBA内存问题_Excel_Vba_Memory_Range_Memory Leaks - Fatal编程技术网

Excel 使用数组分配范围时出现VBA内存问题

Excel 使用数组分配范围时出现VBA内存问题,excel,vba,memory,range,memory-leaks,Excel,Vba,Memory,Range,Memory Leaks,我的目的是用二维变量数组的值指定Excel单元格范围 分配工作正常,但我面临一个内存问题(泄漏):当我启动Excel时,这个过程或多或少需要22个内存。运行以下代码(创建新工作簿、分配范围、关闭工作簿而不保存)后,该过程需要33个月的RAM 有人知道我做错了什么吗 问候,, 亚历山大 这是密码 Option Explicit Sub test() Dim nLines As Long Dim xSize As Long Dim j As Long Dim i As Lo

我的目的是用二维变量数组的值指定Excel单元格范围

分配工作正常,但我面临一个内存问题(泄漏):当我启动Excel时,这个过程或多或少需要22个内存。运行以下代码(创建新工作簿、分配范围、关闭工作簿而不保存)后,该过程需要33个月的RAM

有人知道我做错了什么吗

问候,, 亚历山大

这是密码

Option Explicit

Sub test()
   Dim nLines As Long
   Dim xSize As Long
   Dim j As Long
   Dim i As Long

   'Creating New Empty Workbook
   Application.Workbooks.Add
   Range("A1").Select

   Application.ScreenUpdating = False

   nLines = 10000
   xSize = 200

   Dim myRange As Range
   Dim myArray() As Variant

   ReDim myArray(1 To nLines, 1 To xSize)

   'Assigning some values
   For j = 1 To nLines:
       For i = 1 To xSize:
        myArray(j, i) = i * 4 / 3#
       Next i
   Next j

   Set myRange = Range(ActiveCell, ActiveCell.Offset(nLines - 1, xSize - 1))
   myRange .Value = myArray

   'Cleaning up
    Erase myArray
    Set myRange = Nothing

    'Closing workbook without saving
    Application.ActiveWorkbook.Close (False)

    Application.ScreenUpdating = True

End Sub

VBA不是C,不要指望能够以任何方式控制Excel的内存占用。Excel本身并不擅长内存管理,通常情况下,您正在运行宏或在这些宏中执行的操作对Excel决定分配多少内存或是否再次释放内存几乎没有控制

尽管如此,您可以在代码中做一些事情来减少代码的混乱

  • 范围(“A1”)。选择

    在Excel中对单元格进行操作之前选择单元格通常是不好的做法。您需要选择单元格的唯一时间是在向宏的查看器演示某些内容时。此外,此代码实际上可能会在某些版本的excel中导致问题,因为您刚刚添加了一个工作簿,而excel无法知道应该选择哪个工作簿以及该工作簿中的哪个工作表。您应该完全删除此代码(无论如何,它不会影响您的逻辑)

  • Set myRange=Range(…)

    这段代码不是必需的,因为您只对范围执行一个操作。您根本不需要创建myRange变量,因此您也不必担心将其设置为nothing,或者更重要的是,将其设置为nothing实际上并不能实现内存方面的任何功能

  • ActiveCell
    Application.ActiveWorkbook

    同样,这些基于对“Select”和“ActiveWorkbook”的调用的非限定引用是不明确的,并且可能导致不可靠的行为,特别是当用户在同一excel实例中打开了其他电子表格时。最好存储对在开始时添加的工作簿的引用

  • 总之,我会将您的代码更改为:

    Sub test()
        Const nLines As Long = 10000, xSize As Long = 200
        Dim i As Long, j As Long
        Dim newWorkbook As Workbook
        
        Application.ScreenUpdating = False
        
        'Creating New Empty Workbook
        Set newWorkbook = Application.Workbooks.Add
        
        'Assigning some values
        Dim myArray(1 To nLines, 1 To xSize) As Double
        For j = 1 To nLines:
           For i = 1 To xSize:
            myArray(j, i) = i * 4 / 3#
           Next i
        Next j
        
        With newWorkbook.Sheets(1)
            .Range(.Cells(1, 1), .Cells(nLines - 1, xSize - 1)).Value = myArray
        End With
        
        'Closing workbook without saving
        newWorkbook.Close (False)
        
        'Cleaning up
        Erase myArray
        Set newWorkbook = Nothing
            
        Application.ScreenUpdating = True
    End Sub
    
    结束语:

    将VBA编码课程放在一边-请注意,打开新工作簿的行为将要求Excel分配大量新内存,这比创建临时数组要多得多。这是由Excel释放或保留的内存,即使在您关闭新工作簿后也是如此。这类内存增加将无法避免。请注意,内存不足Excel打印不仅与当前工作簿关联,它还与实例的整个生命周期(支持多个工作簿)关联,以及它们的备份、优化的计算树、撤消历史记录等。将新启动的excel实例的占用空间与刚刚完成“一大堆工作”的excel实例的占用空间进行比较是毫无意义的

    还请注意,仅仅因为Excel没有决定释放该内存,这并不会导致内存泄漏。Excel可能已将内存分配到可回收/可重用对象中,这些对象将被重新填充到您决定打开的下一个工作簿中。反复运行代码可能会导致每次内存略有增加,但Excel可能也会这样做我们将跟踪一定数量的实例操作历史记录

    为了(有趣地)说明我的观点,这里是Excel(2007)在打开一个新实例并运行代码一次、9次、40次之后的内存占用


    这不是你的代码的错,你没有责任担心它,如果你的业务用户担心它,他们不应该选择旧版本的Excel作为他们的目标开发平台。

    不确定Mo是什么,但是运行Excel时11 MB无法解释的RAM是很常见的,即使没有VBA…
    有人知道我做错了什么?
    你没有做错什么:)33-45 mb的ram来处理你正在创建的数组是很正常的:)下面是一篇关于“Excel内存限制-Charles Williamns”的有趣文章,你可能想读一下?谢谢你的回答。11MB(抱歉,法语是Mo)不是一个重要的漏洞,我同意,但我发布的代码只是我必须为非常大的范围做的一个例子。如果我设置xSize=2000而不是200,我会得到100 MB的泄漏。。。逐行调试代码表明,“Set myRange=Nothing”指令不会释放任何内存。有什么想法吗?FWIW,我在Excel 2010 32位、Win7 64位运行了这段代码:工作表打开并添加了这段代码,在运行宏-31Meg之前,在
    上运行宏直到中断。关闭
    行-52Meg,让宏完成-31Meg。Ie无内存泄漏我在Win7 32位上运行Excel 2007 32位。我第一次打开Excel并在“Application.screenUpdate=False”语句上中断,22 MB,运行到中断处。关闭第50 MB行,让宏完成34 MB。再次重新启动宏不会再显示任何泄漏,内存使用率稳定在34 MB。谢谢你的帮助,但我还是有点担心(不知道到底发生了什么)。+1代表“VBA不是C”和taskmgr屏幕截图。回答得很好!