工作表的range方法是一个非常便利高效的读取写入方法,我们大家应该都经常用到range方法来将工作表中的某个区域读取到一个内存数组中,或者将某一个内存数组中的数据一次性写入到工作表中。
但是在数组和range相互操作时,有几个注意事项,不小心的话会造成错误。我们先上一个示例,比如我们希望将A1:E1这一行的数据读入到一个5个元素的一维数组中,一般我们会这么写程序
Private Sub CommandButton1_Click()
Dim myArr As Variant
ReDim myArr(1 To 5)
myArr = Sheet1.Range("A1:E1")
For i = 1 To 5
MsgBox myArr(i)
Next
End Sub
Ok,上面这个程序看起来很正确,一丁点问题都没有对不对?我们希望的结果是运行时读入A1:E1这一行5个数据到数组中,然后分别显示出来,很简单一个程序,语法完全正确。那我们来运行一下,问题来了,程序报错:下标越界!!
那么,是不是VBA一维数组不能读入一行,而是只能读入某一列的数据?改写一下程序,我们读入A1:A5这一列的数据看看:
Private Sub CommandButton1_Click()
Dim myArr As Variant
ReDim myArr(1 To 5)
myArr = Sheet1.Range("A1:A5")
For i = 1 To 5
MsgBox myArr(i)
Next
End Sub
非常令人吃惊,运行时还是报错,依旧是:下标越界!!
现在我们发现问题了,经过笔者大量的试验,可以得出以下结论:
1)在使用range读取之前,redim定义的数组维度无效,会被range方法重置。
2)在用range读取之后,数组会被重置为与读取区域一致的维度,就是说数组的列数会与range的列数相同,行数会与range的行数相同。
3)如果读取1行n列的数据,数组不会重置为类似myarr(1 to n)的形式,而是会被重置为myarr(1 to 1, 1 to n)的形式,同理读取n行1列的区域,数组会被重置为myarr(1 to n, 1 to 1)的形式。用range方法读取区域到数组,就不会产生真正的一维数组。
所以,基于以上结论,用range方法读取区域内容到数组的正确程序应该写成这样:
Private Sub CommandButton4_Click()
‘读取1行n列
Dim myArr1 As Variant
ReDim myArr1(1 To 1, 1 To 5)
myArr1 = Sheet1.Range("A1:E1")
For i = 1 To 5
MsgBox myArr1(1,i)
Next
‘读取n行1列
Dim myArr2 As Variant
ReDim myArr2(1 To 5, 1 To 1)
myArr2 = Sheet1.Range("A1:A5")
For i = 1 To 5
MsgBox myArr2(I,1)
Next
‘读取m行n列
Dim myArr3 As Variant
ReDim myArr3(1 To 5, 1 To 4)
myArr3 = Sheet1.Range("A1:D5")
For i = 1 To 5
For j=1 to 4
MsgBox myArr3(i,j)
Next
Next
End Sub