【发布时间】:2013-11-18 19:07:50
【问题描述】:
在运行了 100,000 次迭代的模拟后,我尝试将每次迭代的值转储到一列中。这是代码的要点:
Sub test()
Application.ScreenUpdating = False
Dim totalgoals() As Variant, ko As Worksheet, out As Worksheet, iter As Long
Set ko = Sheets("KO Sim")
Set out = Sheets("Monte Carlo")
iter = out.Range("P2").Value
For i = 1 To iter
ko.Calculate
If i = 1 Then
ReDim totalgoals(1 To 1, 1 To 1) As Variant
totalgoals(1, 1) = ko.Range("F23").Value
Else
ReDim Preserve totalgoals(1 To 1, 1 To i) As Variant
totalgoals(1, i) = ko.Range("F23").Value
End If
Next i
out.Range("U1:U" & iter) = Application.WorksheetFunction.Transpose(totalgoals)
Application.ScreenUpdating = True
End Sub
这会在倒数第二行引发类型不匹配错误,因为 Transpose 只能处理长度不超过 2^16 (~64,000) 的数组。那么,我应该如何解决这个问题?我最有效的选择是什么?
我将代码设置为将值存储在一个数组中只是为了方便输出,但似乎这不适用于这么多值。我会更好地坚持使用数组并只编写自己的转置函数(即循环遍历数组并将值写入新数组),还是从一开始就使用不同的类会更好,比如集合,如果我最终还是要遍历结果?
或者更好的是,有没有办法做到这一点不必再次循环遍历这些值?
编辑:
我提供了一个不好的例子,因为ReDim Preserve 调用是不必要的。因此,请在必要时考虑以下内容。
ReDim totalgoals(1 To 1, 1 To 1) As Variant
For i = 1 To iter
ko.Calculate
If ko.Range("F23") > 100 Then
If totalgoals(1, 1) = Empty Then
totalgoals(1, 1) = ko.Range("F23").Value
Else
ReDim Preserve totalgoals(1 To 1, 1 To UBound(totalgoals, 2) + 1) As Variant
totalgoals(1, UBound(totalgoals, 2)) = ko.Range("F23").Value
End If
End If
Next i
out.Range("U1").Resize(UBound(totalgoals, 2),1) = Application.WorksheetFunction.Transpose(totalgoals)
【问题讨论】:
-
自己在 VBA 中转置。
-
另外,在 VBA 中循环非常快。从 VBA 与 Excel 交互不是。所以只要你只是在做 VBA 的东西,重新循环应该不是问题。