VBA 为什么你redim() 动态二维数组总出错?因为 redim 动态数组不太适合和循环搭配

1总结

1.1 如何避免出错

  • 如果是想生成一个二维数组,最后用静态声明,或则二次声明redim 一个足够大的动态数组

 

1.2 出错的原因是什么?

  • redim时只有最后1维可变化,redim不太适合和循环搭配,即使用 redim preserve也不行!
  • 你装数据时一般都会有一个充当计数器的变量,这个变量最后的值就是数组中装入值的数量
  • 一般是声明一个足够大的静态数组,或二次声明一个足够大的动态数组,
  • 动态的二维数组用redim 修改大小,切记第一维在第一次扩容的时候就定死了,以后只能修改第二维。
  • 再次扩容第二维的时候,记得加 preserve关键字,否则数组中的原有数据就会丢失。
  • 但是用 redim preserve 扩容的时候,又要注意,维度的数只能增加不能减少,所以不适合 for i=1 to 3 for j=1 to 3 这种循环套循环,因为j这个最后一维总是在循环从小变大,也会有变小重置的时候,就会出问题

 

1.3 下面是详细的试错过程

 

 

2 如果二维数组定义为静态数组,生成数组和生成后打印数组内容,都很方便

Sub test901()
'如果二维数组,定义为静态数组,生成数组 和 生成后打印数组内容,都很方便
Dim arr1(3, 3)

For I = 0 To 3
   For J = 0 To 3
       arr1(I, J) = I * J
       Debug.Print "arr1(" & I & "," & J & ")= " & arr1(I, J) & "  ";
   Next
   Debug.Print
Next
Debug.Print


For I = LBound(arr1) To UBound(arr1)
    For J = LBound(arr1, 2) To UBound(arr1, 2)
        Debug.Print "arr1(" & I & "," & J & ")= " & arr1(I, J) & "  ";
    Next
    Debug.Print
Next
Debug.Print

End Sub

 

 

 

3  如果定义二维数组,是动态数组,但redim时,一次定位到足够大/或准确大小

 


Sub test902()
'如果定义二维数组,是动态数组,但redim时,一次定位到足够大/或准确大小,也没问题,比较清晰

Dim arr2()
ReDim arr2(3, 3)
For I = 0 To 3
   For J = 0 To 3
       arr2(I, J) = I * J
       Debug.Print "arr2(" & I & "," & J & ")= " & arr2(I, J) & "  ";
   Next
   Debug.Print
Next
Debug.Print


For I = LBound(arr2) To UBound(arr2)
    For J = LBound(arr2, 2) To UBound(arr2, 2)
        Debug.Print "arr2(" & I & "," & J & ")= " & arr2(I, J) & "  ";
    Next
    Debug.Print
Next
Debug.Print


End Sub

 

4 如果定义一个二维数组为动态数组,但又在循环时赋值,redim不适合这么动态变量 redim,容易出现下面的问题

  • 动态数组用redim,比如redim arr4(i,j)
  • 因为 i ,j  都在循环就会各种出问题
  • 用 redim arr4(i,j) 必出现越界问题,  因为非最后一维,i  这一维在redim 时是不能变得
  • 用 redim preserve 也容易出现越界问题,(因为 redim preserve 需要后面得数组空间比之前的大,而循环时很容易出现变小不匹配)

Sub test903()
'如果定义一个二维数组为动态数组,但又在循环时赋值,redim不适合这么动态变量 redim,容易出现下面的问题


Dim arr4()
For I = 0 To 3
   For J = 0 To 3
'        ReDim Preserve arr4(I, J)
        ReDim arr4(I, J)
        arr4(I, J) = I * J
        Debug.Print "arr4(" & I & "," & J & ")= " & arr4(I, J) & " ";
   Next J
   Debug.Print
Next I
Debug.Print


For I = LBound(arr4) To UBound(arr4)
    For J = LBound(arr4, 2) To UBound(arr4, 2)
        Debug.Print "arr4(" & I & "," & J & ")= " & arr4(I, J) & " ";
    Next
    Debug.Print
Next


End Sub

 

 

5  为什么 动态redim 二维数组会有问题?原因是

  • 需要理解arr4(1 To 3, 1 To J)中arr(1 to 4, ) 其实是固定数组,一次性一步!把维度展开了,而不是逐步展开
  • 动态数组,redim时,数组的非最后1维不能变化,变了直接报错越界
  • 动态数组,redim时,数组的最后1维也只能从小变大,如循环后又从大变小会出问题,会把之前内容redim后抹掉
  • --------所以循环不太适合redim
  • 但这时候preserve也不行,还是因为如果最后一维因为循环从大到小后,会导致preserve出错(因为preserve必须后面得包含前面的,不能变小)

 

  • 本质在于 redim 和循环 不匹配的问题!
  • 对比
  • 为什么生成数组,同时debug.print 数组内容没问题,但是数组生成完成后,显示数组内容反而有错?
  • 就是因为 for j = 1 to 3 这个二维数组的第2维的循环,redim从1到3,再次从1到3。导致之前的数组的元素被抹掉!
Sub test603()
'二维数组,动态redim
'需要理解arr4(1 To 3, 1 To J)中arr(1 to 4, ) 其实是固定数组,一次性一步!把维度展开了,而不是逐步展开



Dim arr4()
For I = 1 To 3
   For J = 1 To 3
'      ReDim Preserve arr4(I, J)              '错在没注意起始下标应该从1开始
'      ReDim Preserve arr4(1 To I, 1 To J)    '越界错误,因为preserve了,但是j又减小这种循环不适合
'      ReDim arr4(1 To I, 1 To J)             '虽然不pre不会越界,但之前的值会被抹去
        ReDim Preserve arr4(1 To 3, 1 To J)   'vba的二维数组,只支持最后1维变大小,其他维不能变否则显示越界,j作为维度之一,只能单向变大,不应该变小的'
        arr4(I, J) = I * J                     '可在这里设置断点,添加监视变量,监视arr4
   Next J
Next I


For I = LBound(arr4) To UBound(arr4)
    For J = LBound(arr4, 2) To UBound(arr4, 2)
        Debug.Print "arr4(" & I & "," & J & ")= " & arr4(I, J) & " ";
    Next
    Debug.Print
Next
Debug.Print


'总结
'数组的非最后1维不能变化,变了直接报错越界
'数组的最后1维也只能从小变大,如循环后,又从大变小会出问题,会把之前内容redim后抹掉
'但preserve也不行,还是因为如果最后一维因为循环从大到小后,会导致preserve出错(因为preserve必须后面得包含前面的,不能变小)



End Sub

 

 

 

 

  • 7
    点赞
  • 43
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值