我有一个非常技术性的问题,我无法想象答案,我想得到优化问题的建议。
在我的工作表中,我构建了很多XML行。具体来说,它们分布在整个范围内的389,256行(" A1") - >范围(" A389256&#34)。
我的目标是构建一个包含所有这些行的字符串,从而将其填充到XML文件中。我使用以下代码执行此操作:
Private Function buildFileText() As String
Dim ss As String
Dim j As Long
For j = 1 To Sheets("FileContent").Range("A1").End(xlDown).Row
ss = ss & Sheets("FileContent").Range("A" & j).Value & vbNewLine
Next j
buildFileText = ss
End Function
基本上,我只是从空字符串开始构建字符串,并逐行添加电子表格的所有内容。
什么是惊吓是这段代码执行的时间:我在For循环之前和之后放置了一个计时器,它花了 1小时44分钟执行。
我没有发现这种行为是正常的,因为虽然行数很多,但如果我尝试对10,000行进行相同的操作,则不需要一秒钟。想象它需要一秒钟,我希望整个动作大约需要 1秒* 40 = 40秒。 另一方面,如果它是一个纯粹的内存问题,我会预料到堆栈溢出并没有发生。因此,执行每个连接所需的时间似乎呈指数级增长。
我的问题:
答案 0 :(得分:2)
除了您在评论中看到的方式之外,您可能还想尝试“数组”方法
可以通过根据需要将其分成尽可能多的子数组来克服其最大数组大小限制,如下所示:
Private Function buildFileText() As String
Dim ss As String
Dim count As Long
With Worksheets("FileContent")
With .Range("A1", .Cells(.Rows.count, 1).End(xlUp))
Do While .count - count > 24684
ss = ss & Join(Application.Transpose(.Offset(count).Resize(24684).Value), vbNewLine)
count = count + 24684
Loop
buildFileText = ss & Join(Application.Transpose(.Offset(count).Resize(.count - count).Value), vbNewLine)
End With
End With
End Function
答案 1 :(得分:2)
字符串不可调整大小。将两个字符串连接在一起时,会创建一个Temp字符串来保存这两个值。然后将值分配给Temp字符串,然后将目标字符串替换为临时字符串。
"因此,执行每个连接所需的时间似乎呈指数级增长" - 它实际上以一致的速度增长。如果它呈指数增长,Excel会很快崩溃。
但问题是它正在增长,每次连接时都需要更多的内存来创建新的更大的字符串。
在您的情况下,我会使用MSXML2
来创建XML
输出。详细记录将使您的代码易于扩展。
第二个选项是实施String Builder Pattern
。 String Builders
通过初始化一个非常大的输出字符串并将新字符串写入输出字符串中的下一个位置来减少连接数。
我对Excel vba xml parsing performance的回答显示了如何使用String BUilder Pattern
将Excel表格公开为XML。 Parfiat对同一问题的回答演示了如何使用MSXML2
创建XML文件。