VBA: 什么是多维数组:从4维数组说起。兼3维数组和数组嵌套的区别

结论:

本文涉及内容

  • 从4维数组看对多维数组的认识
  • 3维数组和数组嵌套的区别
  • 以及3维数组与redim()的使用注意点

 

数组的dim arr1() 或 redim arr1()

  • 数组可以dim 或者redim
  • 只有在循环过程中,不断的redim 我觉得才是动态数组!
  • 数组在redim arr1() 那一刻就被定义了,之后无法被改变
  • 如果数组已经 dim arr1() 后面就不能在redim 了
  • 但是redim 可以重复进行,所以也可以在循环过程中 redim 

 

低级错误1:多维数组和数组嵌套是一回事吗?NO

  • 多维数组不同于数组嵌套
  • 多维数组,是数组结构的定义,书写的方式是 array(x,y) ---准确的写法是 array(0 to x, 0 to y)
  • 数组嵌套,是数组的某个元素的构成允许嵌套,书写的方式是  array()()
  • 还是理解的不深,以后还需要再思考

 

低级错误2:两种语法区分

  •  下面两者傻傻分不清楚
  • dim array1(1,1,1)       这个是 dim array1(0 to 1 ,0 to 1,0 to 1) 的简写,定义的是1个3维数组
  • 错误写法   dim array(1,1,1,1) 不允许使用保留字
  •  arr1=array(1,1,1,1)       这个是用1个一维数组array(1,1,1)赋值给一个变量arr1

 

 1 什么是 多维数组?

1.1 从1个4维数组举例说起

  • 定义4维数组
  • 简单的静态方法  dim arr1(a,b,c,d)
Sub test1001ccc()
'静态数组的方法定义4维数组
 
Dim arr1(1, 1, 1, 1)
x = 1
For i = 0 To 1
    For j = 0 To 1
        For K = 0 To 1
            For m = 0 To 1
                    arr1(i, j, K, m) = x
                    x = x + 1
                    Debug.Print "arr1(" & i & "," & j & "," & K & "," & m & ")=" & arr1(i, j, K, m) & "   ";

            Next
            Debug.Print
        Next
        Debug.Print
    Next
    Debug.Print
Next
End Sub

 

1.2 从4维数组的内容展示,尝试对4维数组的理解

这个是上面那个4维数组的内容展示

arr1(0,0,0,0)=1   arr1(0,0,0,1)=2   
arr1(0,0,1,0)=3   arr1(0,0,1,1)=4   

arr1(0,1,0,0)=5   arr1(0,1,0,1)=6   
arr1(0,1,1,0)=7   arr1(0,1,1,1)=8   


arr1(1,0,0,0)=9   arr1(1,0,0,1)=10   
arr1(1,0,1,0)=11   arr1(1,0,1,1)=12   

arr1(1,1,0,0)=13   arr1(1,1,0,1)=14   
arr1(1,1,1,0)=15   arr1(1,1,1,1)=16   

  •  dim arr1(1,1,1,1) 这个是个4维数组
  • 可以理解arr1(a,b,c,d) 每个 a  b  c d  代表1维
  • 也可以理解从数组的内容展示分组,每1维的展示关系,有这种逻辑的包含关系(是不是非要用3维坐标系思考的一种谬误?)
  • 但是数据的完整真实,确实一层层存在这种包含关系啊
  • 头脑上始终存在一个3维坐标系

  

 

1.3 极限情况下:每1维都只有1长度,还是多维数组吗? YES

如果只有每个维度只有1,整个数组只有1个元素呢,还是多维数组吗?我觉得是

  • 下面的还是3维数组
  • 可以理解维一个单位维1的小立方体?
Sub test1001ddd()
'静态数组的方法定义3维数组
 
Dim arr1(0, 0, 0)
x = 1
For i = 0 To 0
    For j = 0 To 0
        For K = 0 To 0
                    arr1(i, j, K) = x
                    x = x + 1
                    Debug.Print "arr1(" & i & "," & j & "," & K & ")=" & arr1(i, j, K) & "   ";

        Next
        Debug.Print
    Next
    Debug.Print
Next
End Sub

 

    

 

2 三维数组的正常定义

2.1 定义为静态数组

2.1.1 静态数组的定义

  • 静态数组
  • 所谓的静态,就是指在使用数组以前,先界定数组的 维数,边界大小等等
  • 比如 dim arr1(3,3,3)  其实完整的写法是  dim arr1(0 to 3, 0 to 3, 0 to 3) ,下面展示了这两种写法是等同的
  • 接下来的问题:
  • 静态数组定义的数组,还可以被redim吗?NO, 下面有实验

 

2.1.2 对3维数组的展示

  • 其实从数组的维数来看,我不自觉的映射了,3维空间和3维坐标系的先入为主的思路

 

展示方式1

Sub test1001a()
'静态数组的方法定义三维数组
 
Dim arr1(3, 3, 3)
N = 1
For i = 0 To 3
    For j = 0 To 3
        For K = 0 To 3
            arr1(i, j, K) = N
            Debug.Print "arr1(" & i & "," & j & "," & K & ")=" & arr1(i, j, K)
            N = N + 1
        Next
    Next
Next
End Sub

展示方式2

Sub test1001b()
'静态数组的方法定义三维数组
 
Dim arr1(3, 3, 3)
N = 1
For i = 0 To 3
    For j = 0 To 3
        For K = 1 To 3
            arr1(i, j, K) = N
            Debug.Print "arr1(" & i & "," & j & "," & K & ")=" & arr1(i, j, K);
            N = N + 1
        Next
        Debug.Print
    Next
    Debug.Print
Next
End Sub

Sub test1001c()
'静态数组的方法定义三维数组
 
Dim arr1(0 To 3, 0 To 3, 0 To 3)
N = 1
For i = 0 To 3
    For j = 0 To 3
        For K = 1 To 3
            arr1(i, j, K) = N
            Debug.Print "arr1(" & i & "," & j & "," & K & ")=" & arr1(i, j, K);
            N = N + 1
        Next
        Debug.Print
    Next
    Debug.Print
Next
End Sub

 

2.1.3 静态数组,可以redim吗? NO

  • 事实证明,已经 dim arr1() 过的数组,不能再被redim

 

2.2 在使用前一次性redim  和刚开始就 dim 感觉没啥区别吧,我感觉这只是 redim 并不是动态数组

  • 在循环外部一次性redim() 好数组的大小
  • 我感觉,这时候无论 redim(i,j,k) 这种,或者是 redim  arr3(3,3,3) 本质没区别
  • 都是使用数组前定义
  • 其实和 dim arr3(3,3,3) 也没啥区别把
Sub test1003a()
'动态数组的方法定义三维数组
'如果再循环外面,redim 数组会比较麻烦
Dim arr3()
a = 3
i = 3
j = 3
K = 3
ReDim arr3(i, j, K)
For i = 1 To 3
    For j = 1 To 3
        For K = 1 To 3
            arr3(i, j, K) = a
            Debug.Print "arr3(" & i & "," & j & "," & K & ")=" & arr3(i, j, K)
            a = a + 3
        Next
    Next
Next
Debug.Print
 
End Sub

和上面一样

Sub test1003b()
'动态数组的方法定义三维数组
'如果再循环外面,redim 数组会比较麻烦
Dim arr3()
a = 3
ReDim arr3(3, 3, 3)
For i = 1 To 3
    For j = 1 To 3
        For K = 1 To 3
            arr3(i, j, K) = a
            Debug.Print "arr3(" & i & "," & j & "," & K & ")=" & arr3(i, j, K)
            a = a + 3
        Next
    Next
Next
Debug.Print
 
End Sub

 

2.3 展示错误示例

  • 如果redim() 在循环外,且redim不合适则会 报错“越界”.比如 k=2,
  • 数组在redim arr1() 那一刻就被定义了,之后无法被改变
  • 比如 redim(i,j,k) 后面改 i, j ,k 无意义了!!当时 i j k 没赋值,就相当于 redim (0,0,0)
  • 记住 数组必须 redim () 当时那一刻数组就界定了。

 

错误例子1:虽然redim arr(i,j,k) ,数组已经被确定了,虽然 i,j,k  在redim 之后赋值,也不能改变数组了!

Sub test1004a()

'这是一个错误示例,能看出arr3(0,0,0)可以,但是到 arr3(0,0,1)会报错了!
'在循环外redim数组,相当于dim为静态了
'redim 数组会比较麻烦,需要一定redim准确,或足够大

Dim arr3()
a = 3

ReDim arr3(i, j, K)
'如果不在redim之前给变量赋值,相当于变量还是为空,也就是redim(0,0,0)
'这种redim是无意义的
i = 3
j = 3
K = 3

For i = 0 To 3
    For j = 0 To 3
        For K = 0 To 3
            arr3(i, j, K) = a
            Debug.Print "arr3(" & i & "," & j & "," & K & ")=" & arr3(i, j, K)
            a = a + 3
        Next
    Next
Next
Debug.Print
 
End Sub

错误例子2:上面的例子和直接 redim arr(i,j,k) ,完全不给 i , j ,k 赋值一样,因为vBA 默认变量不定义,初值为0

Sub test1004d()
Dim arr3()
a = 3
ReDim arr3(i, j, K)
'错误例子
'如果不在redim之前给变量赋值,相当于变量还是为空,这种redim是无意义的

For i = 0 To 3
    For j = 0 To 3
        For K = 0 To 3
            arr3(i, j, K) = a
            Debug.Print "arr3(" & i & "," & j & "," & K & ")=" & arr3(i, j, K)
            a = a + 3
        Next
    Next
Next
Debug.Print
 
End Sub

而这样就是对的

  • 也就是 dim 或 redim 数组后,给数组赋值时,不要超过数组的空间就行
  • 比如下面的例子,i,j,k>=3就行
  • 但如果 i,j,k =2 也还是会报错
Sub test1004c()  '这个是对的
Dim arr3()
a = 3
i = 4   '只要大于等于3就行
j = 4
K = 4
ReDim arr3(i, j, K)

For i = 0 To 3
    For j = 0 To 3
        For K = 0 To 3
            arr3(i, j, K) = a
            Debug.Print "arr3(" & i & "," & j & "," & K & ")=" & arr3(i, j, K)
            a = a + 3
        Next
    Next
Next
Debug.Print
 
End Sub

 

2.4 在循环内部一直多次动态 redim(i,j,k)  真正实现动态数组的感觉

  • redim arr1(i,j,k) 并且 i,j,k 一直在变化
  • 如果redim() 为变量,也就是数组的大小不能确定,是变化的,适合放在循环体内redim()多次,也就是变化多次
  • 注意 redim(i,j,k) 这种,当i,j,k 没有赋值的时候,变量为空,相当于没有redim()

Sub test1002()
'动态数组的方法定义三维数组,如果redim需要用到变量,把redim放在循环体里面会好一些
'因为相当于每次循环都在灵活的 又重新redim
Dim arr2()
m = 2
For I = 1 To 3
    For J = 1 To 3
        For K = 1 To 3
            '这里的redim有意义,因为具体的值会替代变量
            ReDim arr2(I, J, K)
            arr2(I, J, K) = m
            Debug.Print "arr2(" & I & "," & J & "," & K & ")=" & arr2(I, J, K)
            m = m + 2
        Next
    Next
Next
Debug.Print
End Sub

 

 

3 问题:多维数组 和 数组的嵌套是一回事吗?NO  

   3.1 特殊写法 arr1()()() ,这个是数组的嵌套,语法定义是  Array(arr1(), arr2()) 这种

  • array() 函数的作用,就是生存一个 一维数组
  • 这种特殊写法arr1(0)(1)(1),我理解为是第1个数组元素的,range里的第1行第1列,这个是数组嵌套
  • 语法外层肯定是一个 array() 函数,比如  arr1 = Array(Range("a1:a4"), Range("b1:b4"), Range("c1:c4"))
  • Rem array()定义的都是1维数组,但元素本身是2个维数组,但是这仍是一维数组!
Sub 测试1()

Dim arr1

arr1 = Array(Range("a1:a4"), Range("b1:b4"), Range("c1:c4"))
Rem array()定义的都是1维数组,但元素本身是2个维数组,但是这仍是一维数组!

Debug.Print "arr1(0)(1)(1)=" & arr1(0)(1)(1)

For I = 1 To UBound(arr1)
   Debug.Print "arr1(" & I & ")(2)(1)=" & arr1(I)(2)(1) '写成arr(i)会报类型不匹配,因为数组维数不对
Next I

'这种特殊写法arr1(0)(1)(1),我理解为是第1个数组元素的,range里的第1行第1列

For Each I In arr1(0)
   Debug.Print I;
Next
Debug.Print

For Each I In arr1(1)
   Debug.Print I;
Next
Debug.Print

For Each I In arr1(2)
   Debug.Print I;
Next
Debug.Print

End Sub

 

3.2 这才是三维数组的   dim arr(i,j,k)  或 redim (0 to i, 0 to j , 0 to k)  多维数组靠定义出来,只有定义为多维数组的才是多维数组

  • 多维数组靠定义出来,只有定义为多维数组的才是多维数组
三维数组的表示问题,和之前的不同了
Sub test_3d()

Dim arr1(1 To 2)
Dim arr2(1 To 2, 1 To 2)
Dim arr3(1 To 2, 1 To 2, 1 To 2)
Dim arr4

arr1(1) = 1
arr2(1, 1) = 10
arr3(1, 1, 1) = 100
'arr4(1)(1)(1) = 100  '错误


Debug.Print arr1(1)
Debug.Print arr2(1, 1)
Debug.Print arr3(1, 1, 1)
'Debug.Print arr4(1)(1)(1)


End Sub

 

3.3 测试多维数组和 数组嵌套的不同

Sub test1()

Dim arr1
Dim arr2
Dim arr3
Dim arr4
Dim arr5(3, 4, 5)


arr1 = Range("b1:b3")
Debug.Print arr1(3, 1)
'Debug.Print arr1(3)(1)

arr2 = Range("b1:b3").Value
Debug.Print arr2(3, 1)
'Debug.Print arr2(3)(1)

arr3 = Array(Range("a1:a3"), Range("b1:b3"))
'Debug.Print arr3(0, 1, 1)
Debug.Print arr3(1)(1)(3)

'arr4 = Array(Range("a1:a3"), Range("b1:b3")).Value   '报错
''Debug.Print arr4(0, 1, 1)
'Debug.Print arr4(1)(1)(3)


arr5(0, 0, 0) = 111
Debug.Print arr5(0, 0, 0)
'Debug.Print arr5(0)(0)(0)

End Sub

 

3.4 显示3维数组 和嵌套数组里的内容,比较

3.4.1 多维数组显示,很方便

Sub testarr222()

Dim arr222()
ReDim arr222(2, 2, 2)
a = 1

'For i = LBound(arr222, 0) To UBound(arr222, 0)  '这样写报错
For i = LBound(arr222) To UBound(arr222)         '这样写OK
    For j = LBound(arr222, 1) To UBound(arr222, 1)
        For K = LBound(arr222, 2) To UBound(arr222, 2)
            arr222(i, j, K) = a
            a = a + 1
            Debug.Print arr222(i, j, K);
        Next
        Debug.Print
    Next
    Debug.Print
Next

Debug.Print "arr222(1, 1, 1)=" & arr222(1, 1, 1)
'Debug.Print arr222(1)(1)(1)

End Su

 

 

3.4.2 嵌套数组的显示,需要先清楚 嵌套结构,且无法直接 debug.print 被嵌套的数组内容

Sub testarr333()

Dim arr333()

arr11 = Array(1, 2, 3)
arr12 = Array(4, 5, 6)
arr13 = Array(7, 8, 9)
arr101 = Array(arr11, arr12, arr13)


arr21 = Array(10, 11, 12)
arr22 = Array(13, 14, 15)
arr23 = Array(16, 17, 18)
arr102 = Array(arr21, arr22, arr23)

arr31 = Array(19, 20, 21)
arr32 = Array(22, 23, 24)
arr33 = Array(25, 26, 27)
arr103 = Array(arr31, arr32, arr33)

arr333 = Array(arr101, arr102, arr103)


'For Each i In arr333
'   Debug.Print i
'Next


'For i = LBound(arr333) To UBound(arr333)
'    Debug.Print arr333(i)
'Next
'Debug.Print arr333(1)(1)      'debug.print 不能直接显示数组
'Debug.Print arr333(1, 1, 1)   '不是多维数组,不能这样

For i = LBound(arr333(0)(0)) To UBound(arr333(0)(0))
    Debug.Print arr333(0)(0)(i)
Next


Debug.Print "arr333(1)(1)(1)=  " & arr333(1)(1)(1)



End Sub

 

 

  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值