将2D数组发布到Excel工作表

时间:2016-11-09 19:51:25

标签: arrays excel vba excel-vba

该函数用作“资产类分配”引擎(在Param范围内具有约束),并在阵列的每一行上模拟投资组合模型。我尝试使用四种方法将数组发布到工作表上,每种方法都失败了。

对于资产A,B,C,D中的每个资产权重,这些参数在M3:O6中配置为{Min 5,Max 100,Step 5}。

该功能无法将2D数组粘贴到Excel中。有970个排列,所以阵列是970x5。这是一个尺寸问题吗?代码可以正常工作PrintArray AllocArray, ActiveWorkbook.Worksheets("Test").[A1]

Sub PrintArray(Data As Variant, Cl As Range) Cl.Resize(UBound(Data, 1), UBound(Data, 2)) = Data End Sub

Function ConfigureArrayFolly()

Dim Param() As Variant
Param = Range("M3:O6")

Dim AMin, AMax, AStep, BMin, BMax, BStep, CMin, CMax, CStep, DMin, DMax, DStep As Double

AMin = Param(1, 1): AMax = Param(1, 2): AStep = Param(1, 3)
BMin = Param(2, 1): BMax = Param(2, 2): BStep = Param(2, 3)
CMin = Param(3, 1): CMax = Param(3, 2): CStep = Param(3, 3)
DMin = Param(4, 1): DMax = Param(4, 2): DStep = Param(4, 3)


Dim nSim As Double: nSim = (1 + (AMax - AMin) / AStep) * (1 + (BMax - BMin) / BStep) * (1 + (CMax - CMin) / CStep) * (1 + (DMax - DMin) / DStep)
Dim nAsset As Double: nAsset = 4 ' Count {A, B, ... , F}

'Debug.Print nSim

Dim AllocArray() As Variant
ReDim AllocArray(1 To 970, 0 To nAsset)

Dim Sim As Integer: Sim = 1
Dim A As Double
Dim B As Integer
Dim C As Integer
Dim D As Integer

For A = AMin To AMax Step AStep
    For B = BMin To BMax Step BStep
    'If (A + B) > 100 Then GoTo endB
        For C = CMin To CMax Step CStep
        'If (A + B + C) > 100 Then GoTo endC
            For D = DMin To DMax Step DStep
                        ' nAsset is the count of set {a1, a2 ... an}
                        ' AllocArray(1, 2, 3) = (Sim, a1, a2)

                        'Constraints
                        If (A + B + C + D) <> 100 Then GoTo endD
                        Debug.Print Sim; A; B; C; D

                        AllocArray(Sim, 0) = Sim
                        AllocArray(Sim, 1) = A
                        AllocArray(Sim, 2) = B
                        AllocArray(Sim, 3) = C
                        AllocArray(Sim, 4) = D
                        Sim = Sim + 1

                       ' Debug.Print "Sim "; Sim; AllocArray(1, 1)
endD:
            Next D
endC:
        Next C
endB:
    Next B
Next A


' Print to sheet - Method One  (fails)
    Dim NumRows As Long: Dim NumCols As Long
    NumRows = UBound(AllocArray, 1) - LBound(AllocArray, 1) + 1
    NumCols = UBound(AllocArray, 2) - LBound(AllocArray, 2) + 1
    Set Destination = Range("D20").Resize(NumRows, NumCols).Value = AllocArray

' Print to sheet - Method Two (fails)
    'Sheets("Test").Range("D20").Value = AllocArray(1, 1)

'Print to sheet - Method Three (fails)
    PrintArray AllocArray, ActiveWorkbook.Worksheets("Test").[D20]

'Print to sheet - Method Four (fails)
    Range("D20:H989").Value = AllocArray

    Sheets("Test").Range("D20").Resize(Sim, NumCols).Value = AllocArray

    'Range(D20:G6002) = AllocArray

    ConfigureArrayFolly = nSim
    End Function

2 个答案:

答案 0 :(得分:2)

您的数组每个维度都有不同的下限。

您需要通过向UBound(Data,2)添加1来调整:

Sub PrintArray(Data As Variant, Cl As Range)
    Cl.Resize(UBound(Data, 1), UBound(Data, 2) + 1) = Data
End Sub

答案 1 :(得分:1)

一些指示。

  • 使用Range("D20").Resize(NumRows, NumCols).Value = AllocArray语法是正确的。
  • AllocArray需要使用ReDim AllocArray(1 to NumRows, 1 to NumCols)
  • 进行调整
  • 正确定义为Dim AllocArray() as Variant
  • 内容必须是DoubleString。你是混合整数和双打,我认为Excel很难用这个(我可能是错的)。将ABCD设为Double
  • Dim nAsset As Integer: nAsset = 5 ' Count {A, B, ... , F}这是一个整数,为什么定义为Double
  • 使用32位整数进行计数。 Dim Sim As Long: Sim = 1。最大Integer的值是32767,因此您可能会溢出。这可能也适用于代码中的其他Integer类型。
  • 您已经知道阵列有多大,您不需要UBound()LBound()来电。