分配带数组的Range时出现VBA内存问题

Ale*_*der 2 memory excel vba memory-leaks range

我的目的是为Excel范围的单元格分配二维变量数组的值.

该分配工作正常,但我面临一个记忆问题(泄漏):当我启动Excel时,该过程需要或多或少22 Mo的Ram.运行以下代码(创建新工作簿,分配范围,关闭工作簿而不保存)后,该过程需要33 Mo的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
Run Code Online (Sandbox Code Playgroud)

Ala*_*ain 9

VBA不是C,不依赖于能够以任何方式控制Excel的内存占用.Excel在内存管理方面本身并不擅长,而且往往是你运行宏或你在这些宏中做的事情几乎无法控制Excel决定分配多少内存,或者它是否曾经决定再次释放它.

话虽这么说,你可以在代码中做一些事情来尝试减少它的混乱.

  1. Range("A1").Select

    在Excel中对它们进行操作之前选择单元格通常是不好的做法.您需要选择单元格的唯一时间是您向宏的查看器说明内容.此外,这个代码实际上可能会导致excel的某些版本出现问题,因为你刚刚添加了一个工作簿,而且没有什么可以告诉excel什么工作簿,以及它应该选择的工作表中的工作表.您应该完全删除此代码(无论如何它都不会影响您的逻辑).

  2. Set myRange = Range( ...

    此代码不是必需的,因为您只使用范围执行一个操作.您根本不需要创建myRange变量,因此您也不必担心将其设置为空,或者更重要的是 - 将其设置为空的事实实际上并没有实现任何内存方式.

  3. ActiveCellApplication.ActiveWorkbook

    同样,基于对"选择"和"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
Run Code Online (Sandbox Code Playgroud)

闭幕致辞:

除了VBA编码课程 - 请注意,打开新工作簿的行为将要求Excel分配大量新内存 - 而不是创建临时数组.即使在关闭新工作簿之后,这也是可以自由或保持存在的内存.这些增加将无法解决.请注意,Excel的内存占用量与您当前的工作簿无关,它是实例的整个生命周期(支持多个工作簿),以及它们的备份,优化的计算树,撤消历史记录等.它真的没有意义将新推出的excel实例的足迹与刚刚完成"一堆东西"的实例进行比较.

另请注意,仅仅因为Excel不决定释放该内存,它不会使它成为泄漏.Excel可能已在可循环/可重用对象中分配内存,这些对象将使用您决定打开的下一个工作簿重新填充.反复重新运行代码可能会导致每次内存略有增加,但Excel也可以跟踪一定量的实例操作历史记录.

(传闻)说明了我的观点,这里是Excel(2007)在打开一个新实例,运行代码一次,再运行9次,然后再运行40次后的内存占用情况.

在此输入图像描述

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