如何在循环中调整数组大小?

时间:2016-04-16 12:15:51

标签: excel vba excel-vba

我正在尝试在excel中返回一个数组。我一直在使用此网站作为参考:http://www.cpearson.com/excel/returningarraysfromvba.aspx

所以我开始使用这个基本的示例脚本,它返回一个值矩阵(取自上面的网站):

Function Test() As Variant
    Dim V() As Variant
    Dim N As Long
    Dim R As Long
    Dim C As Long
    ReDim V(1 To 3, 1 To 4)
    For R = 1 To 3
        For C = 1 To 4
            N = N + 1
            V(R, C) = N
        Next C
    Next R
    Test = V
End Function

当我使用=Test()ctrl+shift+enter键入3x4范围的单元格时,我得到了预期的结果:

1  2  3  4
5  6  7  8
9  10 11 12

现在假设我想在填充数组时调整数组大小。我尝试将功能更改为:

Function Test() As Variant
    Dim V() As Variant
    Dim N As Long
    Dim R As Long
    Dim C As Long
    For R = 1 To 3
        For C = 1 To 4
            N = N + 1
            ReDim Preserve V(1 To R, 1 To C)
            V(R, C) = N
        Next C
    Next R
    Test = V
End Function

当我使用vba IDE时,我认为我没有办法诊断为什么以上只返回{​​{1}}。我做错了什么?

2 个答案:

答案 0 :(得分:3)

来自ReDim statement上的MSDN页面:

  
      
  • 使用Preserve调整大小。如果使用“保留”,则只能调整阵列的最后一个维度。对于每个其他维度,您必须指定现有数组的边界   例如,如果您的数组只有一个维度,则可以调整该维度的大小并保留数组的所有内容,因为您要更改最后一个维度。但是,如果您的数组有两个或更多维度,则可以在使用“保留”时更改最后一个维度的大小。
  •   

所以问题是试图重新开始第一个排名 R 或第一维)。你不能用Preserve做到这一点。但是,您可以使用Preserve所需的任意内容来重新排列第二个等级( C 或第二个维度)。

ReDim Preserve V(1 To 3, 1 To 1)
For R = 1 To 3
    For C = 1 To 4
        N = N + 1
        ReDim Preserve V(LBound(V, 1) To UBound(V, 1), 1 To C)
        V(R, C) = N
    Next C
Next R

如果重新设计二维阵列的第一级是关键任务,那么首先将其转置。

ReDim Preserve V(1 To 1, 1 To 1)
For R = 1 To 3
    V = application.Transpose(V)
    ReDim Preserve V(LBound(V, 1) To UBound(V, 1), LBound(V, 2) To R)
    V = application.Transpose(V)
    For C = 1 To 4
        N = N + 1
        ReDim Preserve V(LBound(V, 1) To UBound(V, 1), LBound(V, 2) To C)
        V(R, C) = N
    Next C
Next R

我已经看到这个用在一个循环中以放置更多的行'转换成二维数组,但转置有限制,它是额外的处理,虽然在内存中。

答案 1 :(得分:2)

在我的测试中,在直接窗口中调用此方法会抛出并索引越界错误。然后我逐步完成了代码,问题是以下几行:

ReDim Preserve V(1 To R, 1 To C)

对于For R循环中的第一次运行(当R为1时),这没有问题,当内部(1 to 1, 1 to 4)循环结束时,数组的大小将为For C

但是只要For R进入第二个循环(当R为2时),它就会调整为(1 to 2, 1 to 1),因此有效地尝试减小第二个维度的大小,这会引发错误由于Preserve声明。删除Preserve语句可以消除错误,但也会导致第二维内的数据丢失。

要解决此问题,您必须先设置数组维度的最终大小,然后再开始遍历数组并填充它(因此您永远不会减小大小)。但是尺寸的大小可以是动态的,例如像这样的方法参数提供:

Function Test(MaxR As Long, MaxC As Long) As Variant
    Dim V() As Variant
    Dim N As Long
    Dim R As Long
    Dim C As Long

    'Set array size
    ReDim Preserve V(1 To MaxR, 1 To MaxC)

    'Then start filling array
    For R = 1 To MaxR
        For C = 1 To MaxC
            N = N + 1
            V(R, C) = N
        Next C
    Next R
    Test = V
End Function

然后,您可以使用此公式在数组公式(ctrl+shift+enter)中对3x4单元格范围使用该方法:

=Test(3; 4)