当Excel只消耗70MB时,VBA“内存不足”错误

问:为什么当我的系统有足够的剩余空间(办公室是64位)

问:分裂时的数据会不会导致这种奇怪的行为?

问:如果拆分该string会造成麻烦,那么如何对存储/恢复该string的操作进行清理/恢复呢?

规格: Win 8.1 Pro + Office 2013 64bit,8GB RAM

这里是代码,它只是得到单个大(〜1-2MB)的string,并将其拆分成多个单元格,以便每个单元格的32k字符限制不会造成危害:

Public Sub SaveConst(str As String) Dim i As Long i = 0 ' Clear prior data Do While LenB(Range("ConstJSON").Offset(0, i)) <> 0 Range("ConstJSON").Offset(0, i) = "" i = i + 1 Loop Dim strLen As Long With Range("ConstJSON") .Offset(0, 0) = Left$(str, 30000) i = 1 strLen = Len(str) Debug.Print strLen Do While strLen > i * 30000 .Offset(0, i) = Mid$(str, i * 30000 + 1, 30000) Debug.Print i i = i + 1 Loop End With End Sub 

现在Len(str)报告〜270k个字符,然后我迭代了4次,然后“Out of memory”bug被踢进了。

现在,这是这个地方的错误的第n次迭代。 但是我已经简化/修改了代码,以便它有时可以工作。 对于完全相同的数据集。

更新:Thx Jean代码,我相信它的SAVING部分string导致该错误的单元格。

 .Offset(0, i) = Mid$(str, i * 30000 + 1, 30000) 

要么

 Range("ConstJSON").Resize(nPieces).Value2 = v 

两者都导致错误。

更新2:我没有任何大惊小怪的保存该string单个单元格。 但是现在这个string变得太大而不适合,分裂有时会导致这个错误“内存不足”。 示例性的string:

[…]“”ebiZlecenias“”:[{“”id“”“”“91a75940-6d3e-06f8-bcf7-28ecd49e85f2”“,”“lp”“:null,”“name”“:”“ZLECENIE GŁÓWNE“”,“”date_entered“”:“”2014-04-15 08:13:18“”,“”date_modified“”:“”2014-04-15 08:13:18“”,“”modified_user_id“ “:” “2””, “” budowa_id “”: “” 8614aab5-29da-FFAC-4865-e8c5913c729c “”, “” rodzaj “”: “” 1 “”, “” ETAP “”: “” 1" ”, “” data_akceptacji “”:空 “” OPIS “”:空 “” user_ID的 “”:空 “” data_bazowa_od “”:空 “” data_bazowa_do “”:空 “” data_rzeczywista_od “”:空, “”data_rzeczywista_do“”:null,“”archiwalny“”:null,“”deleted“”:null,“”termin_raportowania“”:null,“okres_raportowania”“:null,[…]

编辑:我相信你的标本string的问题是,一些子string以“ – ”开头。 当发生这种情况时,Excel认为内容是一个公式,这就是导致错误的原因。 格式化单元格作为文本没有解决问题,但在每个条目之前使用“单引号”,将条目强制为文本,除了在公式栏中不显示,似乎已经纠正了我的macros中的问题,即使使用上面的标本string作为“基本”string。

编辑2:似乎正在发生的是,如果string长度大于8,192个字符(公式中允许的最长的string),并且还以令Excel认为它可能是公式的令牌开始(例如: – ,+, =),写入单元格将失败,并出现内存不足错误, 即使单元格被格式化为文本。 如果先插入单引号,则不会发生这种情况。

下面是一些在更长的string上工作的代码。

下面的代码首先创build一个长string,在这种情况下,string略多于100,000,000个字符,然后将其拆分为顺序列。 没有错误:

 Option Explicit Sub MakeLongString() Dim S As String Const strLEN As Long = 100 * 10 ^ 6 Const strPAT As String = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" S = strPAT Do S = S & S Loop Until Len(S) > strLEN Debug.Print Format(Len(S), "#,###") SplitString (S) Debug.Print Range("a1").End(xlToRight).Column End Sub Sub SplitString(STR) Dim R As Range Dim strLEN As Long Set R = [a1] Dim I As Long strLEN = Len(STR) Do Until I > strLEN R(1, I / 30000 + 1) = "'" & Mid(STR, I + 1, 30000) I = I + 30000 Loop End Sub 

我刚刚运行了一个testing,其中写入的范围是一个多单元格区域,目标是按照偏移方法设置的,而且它也跑到完成而没有错误,填入前四行。

 Sub SplitString(STR) Dim R As Range Dim strLEN As Long Set R = [a1:a4] Dim I As Long strLEN = Len(STR) Do Until I > strLEN R.Offset(, I / 30000) = "'" & Mid(STR, I + 1, 30000) I = I + 30000 Loop End Sub 

这是值得一试的:首先将string拆分成一个数组,然后将整个数组一次性打到表单上。

 Const pieceLength As Long = 3000 Dim s As String Dim i As Long Dim nPieces As Long Dim v As Variant s = ... ' whatever your string is... nPieces = WorksheetFunction.Ceiling(Len(s) / pieceLength, 1) ReDim v(1 To nPieces, 1 To 1) For i = 1 To nPieces v(i, 1) = Mid(s, (pieceLength * i) + 1, pieceLength) Next i Range("ConstJSON").Resize(nPieces).Value2 = v 

我还没有testing过你的代码,所以不能准确地说出它到底有什么问题,但是我知道一次一个地写入(或读取)单个单元格是慢而且昂贵的。 从数组读取/写入大量单元格以及操作数组(而不是单元格)通常要好得多。