[英]VBA on Excel "Out of Memory" error
我在 Excel 2010 上,在一張公認的非常大的工作表上(400k 行 X 20 列)。
我的代碼旨在:
我將兩個變量數組定義為變體,並嘗試通過復制工作表的內容兩次來初始化它們。
第一個副本有效,但到第二個副本時,我遇到了“內存不足”的錯誤。
如果有解決方法,有什么想法嗎? 或者這只是 VBA/Excel 的限制。
有沒有辦法不預先定義/初始化目標數組,而是讓它隨着標准的每個成功限定而“增長”? (在這個規模上)。
Sub CopyPending()
Dim LastRow As Long
Dim LastCol As Integer
Dim AllRange() As Variant
Dim CopyRange() As Variant
Dim i As Long
Dim x As Long
Dim z As Long
LastCol = 21
LastRow = ActiveSheet.UsedRange.Rows.Count
AllRange = Range(Cells(2, 1), Cells(LastRow, LastCol)).Value
CopyRange = Range(Cells(2, 1), Cells(LastRow, LastCol)).Value ''' ERROR TRIGGER
i = 1
x = 1
z = 1
For i = LBound(AllRange) To UBound(AllRange) - 1
If AllRange(i, 7) = "TestCriteria" Then
For z = 1 To LastCol
CopyRange(x, z) = AllRange(i, z)
Next z
x = x + 1
End If
Next i
With Sheets(2)
.Range(.Cells(2, 1), .Cells(x, LastCol)).Value = CopyRange
End With
End Sub
正如您對帖子的評論所示,此錯誤來自工作記憶不足。
每個 Variant 類型變量占用 16 個字節,這就是您的代碼需要大量內存的原因。 因此,解決此問題的一種方法是增加計算機上的物理內存。
其他解決方案是按一定數量的行過濾數據。
Sub ProcessRows()
Dim originalData() As Variant
Dim maxRow as Long, currentRow as Long, incrementRow
maxRow = ActiveSheet.Usedrange.Rows.Count
currentRow =1
incrementRow=5000
While currentRow < maxRow
Set originalData = Range(.Cells(currentRow,1),.Cells(currentRow+incrementRow-1,20)
your process to filter data
currentRow = currentRow +incrementRow
Wend
End Sub
當然,您可以使用逐行方法,但我假設您使用數組變量來加速代碼,因此我不建議使用逐行方法。
逐行工作非常慢,因此對於如此大的數據集,這不是一個可行的解決方案。
數組絕對是要走的路,所以選擇是:
編輯:我看到您是 400k * 20,這正在推動選項 1 的邊界。您可能別無選擇,只能重構代碼並逐批加載和處理(與逐批加載然后一起處理)
筆記:
下面通過遞歸批量加載數據,將數據批量加載到單個數組中。 試試看 - 最后仍然有一個數組的好處意味着您不必重構其余的代碼。
選項 1 示例:
Option Explicit
Sub example()
Dim myCompletedataArr
Dim myTestDataRange As Range
Set myTestDataRange = ActiveSheet.UsedRange
loadDataInBatches myTestDataRange, myCompletedataArr
Debug.Assert False
End Sub
Sub loadDataInBatches(dataRange As Range, dataArr, Optional startRow As Long = 1, Optional rows As Long = 10000)
Dim endRow As Long, i As Long, j As Long
Dim dataArrLb1 As Long, dataArrLb2 As Long, batchArrLb1 As Long, batchArrLb2 As Long
Dim batchArr, batchRange As Range
If Not IsArray(dataArr) Then
ReDim dataArr(0 To dataRange.rows.Count - 1, 0 To dataRange.Columns.Count - 1)
End If 'otherwise assume dataArr is correctly dimensioned (for simplicity)
endRow = WorksheetFunction.Min(startRow + rows - 1, dataRange.rows.Count)
If endRow <= startRow Then Exit Sub
Set batchRange = dataRange.rows(startRow & ":" & endRow)
batchArr = batchRange.Value
'cache lower bounds as we use them a lot
dataArrLb1 = LBound(dataArr, 1): dataArrLb2 = LBound(dataArr, 2)
batchArrLb1 = LBound(batchArr, 1): batchArrLb2 = LBound(batchArr, 2)
For i = batchArrLb1 To UBound(batchArr, 1)
For j = batchArrLb2 To UBound(batchArr, 2)
dataArr(startRow - 1 + i + dataArrLb1 - batchArrLb1, j + dataArrLb2 - batchArrLb2) = batchArr(i, j)
Next j
Next i
Erase batchArr 'free up some memory before the recursive call
loadDataInBatches dataRange, dataArr, endRow + 1, rows
End Sub
上面的所有建議都表明內存不足。 我的電腦有足夠的內存,我也曾經嘗試切換到 64 位 Excel。 我必須假設有一個常見的 Excel 錯誤。 對我來說最安全的方法(不保證每次都發生)如下:由於我的 Excel 文件經常崩潰的內置效果,我將 .xlsx 文件中的數據和所有宏分離到 AddIns 中。 這種不方便的方式將崩潰幾乎減少到零。 但是,每當我需要對 AddIn 進行更新時,我首先卸載 AddIn,然后修改 AddIn 的源文件,保存這個 .xlsb 文件,然后將其另存為 .xlam。 當我嘗試關閉插件的源文件(.xlsb 文件)時,系統會詢問我是要保存新副本還是覆蓋更改。 無論我采取什么選擇,我都會收到“內存不足”的消息。 有時我可以繼續工作,有時 Excel 崩潰並重新開始。 也許這個描述解釋了該消息與內存太少或分配的數據太多無關。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.