四、数组
为什么要学习数组?换句话说,他有什么优势?
那我们先来一个直观的感受:
例9:请向当前表格的a1至j30000单元格区域中填入1至100间的随机整数。
由前面的知识,画出流程图:
VBA提供了Rnd 函数返回小于 1 但大于或等于 0 的随机数,如果要生成某区间的随机整数可用Int((上限 –下限 + 1) * Rnd + 下限),由流程图我们很容易写出以下代码:
Sub test1() '名称为test1的程序
Dim i1%, i2%, t As Single ' 定义两个整型变量和一个单精度型变量
t = Timer '记下当前的时刻
Cells.Clear '清空当前表的所有单元格
For i1 = 1 To 10 'i1从1循环到10,步长为1
For i2 = 1 To 30000 'i2从1循环到30000,步长为1
Cells(i2, i1) = Int(Rnd * 100 + 1) '向单元格中填入随机整数数
Next '下一个i2
Next '下一个i1
MsgBox Timer - t '显示当前时刻与t的差
End Sub '结束
代码中我们增加了t = Timer和MsgBox Timer – t两句用于检查此段代码花费了多少时间,应该能明白吧?
现在我们思路完全不变,改成用数组来做:
Sub test2()
Dim i1%, i2%, t As Single
Dim arr1(1 To 30000, 1 To 10) As Integer ‘定义数组arr1
t = Timer
Cells.Clear
For i1 = 1 To 10
For i2 = 1 To 30000
arr1(i2, i1) = Int(Rnd * 100 + 1) ‘生成的随机数写入数组arr1
Next
Next
Range("a1:j30000") = arr1 '将数组arr1的元素值填入单元格a1至j30000区域中
MsgBox Timer - t
End Sub
比较一下两段代码,基本上一样,是吧?可是他们花费的时间呢?
还有更夸张的:记得以前刚开始用VBA时写一个类似于vlookup功能的代码,运行了一个小时还没完成实在等不下去了只好强行中断了它,后来改成数组大约是3秒左右,最后改成数组+字典,就没超过1秒了。怎么样?激发起数组兴趣没有?
数组为什么快?究其原因,第一段代码直接向单元格中写入数据,写了10*30000次;第二段代码使用数组进行过渡,他先将数据写入数组,最后通过一句Range("a1:j30000") = arr1一次性将数组中的数据写入到单元格区域,从而达到的提高速度的目的。这就是空间换时间(数组是要占空间的哟)。
从这个示例我们可以得到以下知识:
其一,利用数组来减少对单元格的操作,可以大大提高速度,这就是我们为什么要学数组的原因之一。
其二,又见到了三个函数:取整函数int(返回不大于其参数的最大整数,即int(5.9)返回5,int(-5.1)返回-6)、随机数函数rnd(返回大于等于0且小于1的随机小数)、时间函数timer(返回从午夜开始到现在经过的秒数)。如果要生成某区间的随机整数可用Int((上限 –下限 + 1) * Rnd + 下限)(如要生成10到20的随机整数就用int(11*rnd+10)
见识了数组的作用,那么什么是数组?如何使用呢?下面我们从头来讲:
---------------------------------------------------------------------------
前面讲了变量,变量就是用于存放数据的内存单元。一个变量存放一个数据。
而数组,书上讲是多个类型相同的元素组成的集合,他用一个统一的数组名称和下标来唯一确定数组中的元素。
太深奥了,不便于老百姓理解!数组数组,就是数据的组合嘛。说简单点:
1、一维数组:
公交车在出厂时安放了从1号编到50号的50个座位。王美女上车来司机把她安到了5号座位,这样5号座位就是王美女,下一站王美女下车了,上来了张帅哥、刘大头,司机把张帅哥、刘大头依次安到5号和10号位,这样5号就变成了张帅哥、10号位成了刘大头。这就就是个数组,而且是大小为50个元素的一维数组:安放了从1号编到50号的50个座位就是dim arr1(1 to 50),王美女坐到5号位就是arr1(5)= "王美女",后来张帅哥、刘大头依次坐到5号和10号位就是arr1(5)= "张帅哥"(张帅哥占了5号位王美女就消失了)、arr1(10)= "刘大头"……
这样的例子还有很多很多:银行里面办理业务排的号;足球比赛时运动员背上还是有大大的数字:一个序号……
象这样,他们就是一维数组:只有一个下标。在VBA中使用
Dim 数组名(n1 to n2) as 数据类型
来定义一维数组。其中as 数据类型与前面的讲的变量完全一样,此处不在解释;n1和n2都是整数(即正整数、负整数、0都可以,而不见得如上面的都从1开始),但需要满足n1<=n2,定义出的元素个数为n2-n1+1。要引用其中的元素时,就用数组名(整型数字),这个整型数字的取值范围就从n1到n2的范围内。
以dim arr1(-10 to 10)为例:数组名为arr1;元素个数为21个(为什么是21而不是20?),依次为arr1(-10)、arr1(-9)、arr1(-8)、……arr1(-1)、arr1(0)、arr1(1)、……arr1(9)、arr1(10),括号中的-10、-9等等数字就叫数组的下标(由于每个数组元素的下标只有一个,叫一维数组;这些下标都是整数,编程中常用整数或整型变量来表示这些下标);且都为Variant型(因为省略了as 类型)。其实质是在内存中开辟了一段连续的21个内存单元,分别用arr1(-10)、arr1(-9)、arr1(-8)、……来指向这些内存单元(相当于定义了21个变量)。
----------------------------------------------------------------------------
2、二维数组及多维数组
除了这种只有一个下标的外,还有两个下标的:我们的大会议室中安放了很多排、每排很多个座位,这时我们常常要给他编上号:1排、2排……,每一排又有1号、2号……要指定某个座位时就可用3排5号、10排8号等等这样的两个数字来唯一确定。对应到VBA中这就是一个二维数组:
Dim 数组名(n1 to n2,n3 to n4) as 数据类型
含义与一维数组基本雷同。其中n1<=n2,n3<=n4,元素个数为(n2-n1+1) *(n4-n3+1)
前例中的Dim arr1(1 To 30000, 1 To 10) As Integer就定义了一个大小为30000*10的integer类型的数组。对应的元素的引用就是arr1(1,1)、arr1(1,2)、……arr1(2,1)、arr1(2,2)、……arr1(30000,9)、arr1(30000,10)。看到了吧,每个元素都是两个下标,中间用,分开。
-----------------------------------------------------------------------
多维数组:还是前面的会议室,共有30排每排40个座,这是二维的;可是我们有5个这样完全一样的会议室,分别编号的一会议室、二会议室……如果要指定三会议室12排6号我们就可用会议室(3,12,6),这不就是三维了吗?要是我们有很10层楼,每层楼都是这样5个完全一样的会议室,如果要指定7楼三会议室12排6号我们就可用会议室(7,3,12,6),这又是几维呢?……还有很多很多。不过VBA提供的数组最多可达64维,不能超过64哈,实际编程中用得最多的还是一维和二维。
在实际编程中,有时我们在设计代码时没法确定数组的大小,而需要在运行过程中根据实际需要才能定,这时我们常常先定义为动态数组(即不确定他的大小)然后再修改他的大小:
Sub test()
Dim arr1() '定义数组arr1为动态数组
Dim i1%, i2%
i1 = InputBox("输入数组的最小下标", , 0)
i2 = InputBox("输入数组的最大下标", , 100)
ReDim arr1(i1 To i2) '重新定义数组arr1的大小
End Sub
对于redim大家可以去认真看看帮助文件,在这里我们暂时不多说他,在后面的实例中我们再讲。
至此,我们将一些堆积木的规则及个别积木块展示出来了,下面,我们将再增加一些积木块,运用前面讲的规则来堆我们希望得到的“珍品”,共同努力吧!
以下我们给先出几个“积木块”然后用他来堆一个“产品”,这当中将着重从思路分析上入手,对实例进行多角度的分析,然后对每一种分析都写出相应的代码。想达到的目的:让大家逐渐掌握如何根据编程的基本思想方法来分析问题、解决问题。同时大家要切记:不要为眩目的代码所迷惑,要明白思路为上、写具体代码为下,也就是说重点是在思想方法上而不是在一行行的代码上。
一、积木块(说得很简略,具体参考帮助或
http://www.excelpx.com/thread-8822-1-1.html):
Len(字符串|变量名)包含字符串内字符的数目,或是存储一变量所需的字节数。如Len("示例A")返回3;x% = 1615后Len(x)返回2(x为integer,占2 个字节)
Mid(字符串,起始位置[,字符个数]):从字符串的起始位置开始取指定数量的字符。如mid("asdfghj",3,2)返回"df"
Val(字符串) 返回去掉字符串内的空白、制表符和换行符之后的数字(位于非数字之后的数据则不能返回)。如Val("1615 .198th 213 N.E.")返回1615.198,213没返回是因为它在非数字th这之后
Like:用来比较两个字符串。没有比
http://www.excelpx.com/thread-8822-1-1.html第七楼写的好的了,仔细去看看吧。对其它的在此贴中都有非常好非常好的解释,字符串处理的必看贴之一。
InStr([起始位置字串1,字串2) 从起始位置开始在字串1中找字串2最先出现的位置;当起始位置省略时从字串1的第一个字符开始找;没找到时返回0。
Replace(字串1,字串2,字串3[,开始位置[,替换次数]])把字串1中从开始位置所包含的字串2用字串3来替换,替换次数表示当有很多都符合条件时则只替换替换次数所限定的最早出现的那几个,其余的则不替换。有开始数字时,开始数字前的字符没有了;开始位置默认为1,替换次数默认为所有。
----------------------------------------------------------