如何调整循环中的数组?

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

所以我从这个基本的示例脚本开始,它返回一个值的matrix(从上面的网站获取):

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 

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

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

所以现在假设我想调整数组的大小。 我试着改变这个function:

 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,所以我不认为我有任何诊断为什么上面只返回#VALUE 。 我究竟做错了什么?

在我的testing中,在直接窗口中调用此方法会抛出索引超出范围的错误。 然后我通过代码,问题是以下行:

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

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

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

为了解决这个问题,你必须在开始遍历数组并填充数组之前设置数组维的最终大小(所以你永远不会减小大小)。 但是维度的大小可以是dynamic的,例如像这样的方法参数提供:

 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 )来获得3×4范围的单元格。

 =Test(3; 4) 

从ReDim声明的MSDN页面:

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

所以问题是试图重新排列第一R或第一维)。 你不能用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 

我已经看到这在循环中使用更多的“行”到一个二维数组,但转置有限制,这是额外的处理,尽pipe在内存中。