VBA数组(一)
一、什么是数组 对于数组,在前面7楼的贴子里我们已经简单介绍了一些简单的概念,如果你忘记了,请回过头去花两分种读一读。 读完了也许你还是不清楚,没关系,请接着往下看。 新学期开始了,我上七(1)班数学,学生太多了,我老是记不住学生的名字,还好班主任为了便于管理,为班上的学生都编了学号,所以上课时点名我习惯性只点学生学号,我说,5号同学请上黑板演示一下你的解题过程,10号同学下课后请替老师把大家的作业收起来……下课后,在办公室,和大家聊天,我更不叫学生名字而直接统称为“七(1)班”。 待我学习了VBA的数组后,我忽然明白了,这种简化的称呼方式原来就是“数组”。 这里,我们是把一群学生聚在了一起组成了“七(1)班”(数组名)这个集合,班级里的学生我们通过“学号”(索引号)对其进行区分。上课时,我问:“5号同学是谁?”,一个同学站起来答:“我叫moon2778”,于是,我知道了,“七(1)班”这个数组里的第5个元素就是“moon2778”。用数组来表示就是“七(1)班(5)”,也就是数组名加索引号。好了,当别人果问你:“‘七(1)班(5)’的同学是谁?”时,你一定要知道,是“moon2778”。 那么,什么是数组,你知道了吧?它有什么特点,我们可以试着简单小结一下: 1、数组共享一个名字,即数组名; 2、数组是变量的集合,有多个元素; 3、数组中的元素按顺序保存在数组中,元素通过索引数字加以区分; 4、数组是变量。 二、定义数组 声名数组同声明其他变量的方式一样,唯一不同的是数组有大小,包含多个单个变量。 初一学生报名入学后开始分班级,领导说,七(1)班分50个学生(确定了班级学生的个数最多只能有50个学生,再多一个都不行,因为没有座位了。),知道有50个学生后,老师拿到学生花名册就开始给学生编学号,建学籍。1号是谁?2号是谁?……50号是谁? 这就是一个定义数组,并给数组赋值的过程,用语句来表示,可以这样: Dim 七(1)班(1 To 50) 七(1)班(1) = "张三" 七(1)班(2) = "李四" 七(1)班(3) = "王王" ..... 七(1)班(50) = "赵六" 这里,我们定义了一个50个元素的一维数组,并分别给数组的元素赋值。当然,这里用的只是一个模拟的语句。如果我们需要定义一个数组arr,存放1到100的整数集合,则代码为: 复制内容到剪贴板
其实“Dim arr(1 To 100) As Integer”我们也可以写成“Dim arr(99) As Integer”,这样,定义的数组同样是100个元素的一维数组,因为如果不指定起始索引号的话,VBA默认从0开始。代码: Sub ggsmart() 当然,你也是可以通过OPTION BASE 来修改数组默认的起始序号,在模块的第一句写上“OPTION BASE 1”这样,默认的数组起始序号就是1了。 学习累了,恰好第二节课刚下,课间操时间,顺便可以到操场练练。可是,有些同学不认真啊,这不,老师在广播里叫上了:“七年级,(1)班的第五个同学请认真一点,七年级,(2)班的第三个同学注意队形……” 天了,我惊奇地发现,原来我们生活中有这么多“数组”,可是,你知道上面的这两个同学共享了一个什么名字吗? 是的,“七年级”就是它们共有的名字。 新生分班时,校长就说了,550名新生,每班50人,分成11个班,到各个班级里,老师都给学生分了学号(1到50号),11个班级就有11个1号,也有11个50号。晕,一个班的学生名字我都记不住,如果11个班的学生全站在一起,我该怎么称呼? 我高兴了,还好,我会数组。找到“moon2278”同学,我会说“七年级,1班,5号同学”,哈,难不了我。如果“宝贝有酒窝”同学是初一(9)班的25号,没关系,我也会说“七年级,9班,25号同学”。 哇,好简单,前面加个班级的序号区分就行了。 这里,“七年级”实际上是一个由11个一维数组(11个班)组成的二维数组,它的元素的个数是11*50(11个班,每个班级50名学生)个。习惯性,大家会说它是一个11*50的二维数组。 如果要写成代码,那就是: Dim 七年级(1 To 11, 1 To 50) 七年级(1, 1) = "张三" 七年级(1, 2) = "李四" '...... 七年级(2, 1) = "钱林" 七年级(2, 50) = "林平" '...... 七年级(11, 50) = "周六" 我们说上面的数组是一个11*50的二维数组,放到表格里就相当于是一个11行50列的数组。 如果我们想定义一个二维数组,第一列存放1到100的奇数,第二列存放1到100的偶数,代码为: 复制内容到剪贴板
1到100的奇偶数.rar (6.63 KB)
把代码复制到模块里,按F5可以看到程序运行的效果。代码: Sub ggsmart() 上面,我们讲的是一维数组和二维数组,你也可以按同样的思路来理解三维、四维数组,甚至五维、六维……或者更多。 无非就是将称呼moon2278同学的方式改为“XX中学、七年级、1班、5号同学”或“XX市、XX中学、七年级、1班、5号同学”而已,如果你喜欢,你还可以将这个称呼扩展,随你了,这里不再举例。 三、动态数组 声明一个数组,必须指定数组的大小,即它是几维数组,有多少个元素。 但有些时候,我们在定义数组的时候,并不能确定数组的大小,这时,我们在首次定义数组的时候括号内为空(当然先指定一个大小也是可以的,但纯属是多余),在程序过程中用Redim语句去重新指定数组的大小,这就是动态数组。 比如一个工作表的A列存储了学生姓名,现在我们需要把把有姓“张”的学生存储在数组arr中,预先我们并不知道A列姓张的学生有三十个还是五十个,所以,我们在定义时代码可以这样: 复制内容到剪贴板
姓“张”的学生.rar (7.16 KB)
代码: Sub ggsmart() 四、其他创建数组的几种方式 其实在上面,我们已经接触了如何创建数组了。无非就是像给学生排座位一样,你坐第一排,我坐第二排,他坐第三排,然后你们大家统称为第一组。 好简单,这里,我再介绍几种上面没讲到,但常见的方法: 1、使用Array创建数组 看以下代码: 复制内容到剪贴板
这里使用Array函数将1到10的自然数赋给数组arr这里,我就不上传附件了,大家将代码复制到模块里查看效果。代码: Sub ggsmart() 引用:提醒一点:使用Array创建的数组索引号默认从0开始,当然,如果已经用“OPTION BASE 1”语句指定了的另当别论。 复制内容到剪贴板
2、使用Split创建数组代码: arr = Array("张祝", "徐国军", "陈茜", "王欢", "许松", "张小海", "陈飞", "张明元", "徐国东", "张款") Split的作用是把一个文本,根据指定的分隔符,建立一个数组。感觉就有点像我们基础操作中的“分列”。不同的是“分列”操作是将一个单元格的文本按指定的分隔符分开,存放在同行的多个单元格里,而Split的作用是将一个文本(也可以是存放在单元格里的)按指定的分隔符分开,存放在一个数组变量里。 如果你使用过“分列”,再来看这个,就简单多了。 还是上面的那串姓名“张祝,徐国军,陈茜,王欢,许松,张小海,陈飞,张明元,徐国东,张款”,只是这时,这些姓名是一个完整的字符串,此时,如果我们想把这些姓号按逗号(,)分开,存放在数组arr里,则代码为: 复制内容到剪贴板
你可以用上面的方式将生成的数组输入到单元格查看效果。当然,也可以在立即窗口里查看,这样就更方便了。代码: arr = Split("张祝,徐国军,陈茜,王欢,许松,张小海,陈飞,张明元,徐国东,张款", ",") 特别强调一点:用Split把文本转换成数组,索引号总是从0开始。不管你是否使用了Option Base语句,这点和Array不同。 3、通过Range创建数组 (1)循环给单元格赋值 比如想把A1:A100单元格的值给数组arr,则代码为: 复制内容到剪贴板
(2)直接等于单元格区域代码: Sub a() 这个很简单,直接数组名等于单元格区域就可以了。 比如想把A1:A100单元格的值给数组arr,代码还可以简单写为: 复制内容到剪贴板
好了,很简单,我就不再多说,大家自己去练习吧。代码: arr = [a1:a100] 两种方法哪种的效率高显而易见吧?呵呵……有兴趣,可以自己去比较一下。 五、UBount和LBound函数 我们定义数组时,我们可以指定数组的起始索引号不为0,而为1或其他的任意数。比如Dim arr(5 to 6)定义的这个数组起始索引号为5,共有两个元素。 那么,对于一个已经定义了的数组,我们想知道它的最大索引号(上界)和最小索引号(下界)是多少,怎么办呢?别慌,用UBound和LBound两个函数就可以了。 如,要想知道数组arr的上界是多少,则:UBound(arr) 要想知道数组arr的下界是多少,则:LBound(arr) 想知道数组有多少个元素,则:UBound(arr)- LBound(arr)+1 如: 复制内容到剪贴板
如果是一个二维数组,想知道它的上界是多少,就得指定维数,看一看下面的例子:代码: Sub ggsmart() 复制内容到剪贴板
六、Join函数代码: Sub ggmsart() Join的作用和Split的作用相反。Split是将字符按指定字符转为数组,Join是将数组以指定字符分开,连成一个字符串。如: 复制内容到剪贴板
Join的第二参数,即分隔符可以不指定,在不指定时,默认为以空格作分隔符。代码: Sub ggsmart() 七、将数组输入单元格区域 1、使用循环输入 如将存储了1到60000的数的数组写入A列,则: 复制内容到剪贴板
以上程序是使用循环,将数组里的元素逐个写入单元格,为了对比不同的输入方式的效率,我加入了计算时间的代码,有了前面的基础,相信读上面的代码对大家来说,不会太困难。代码: Sub test1() 2、批量写入 实际上用一条语句就可以将数的内容写入单元格区域中,即:单元格区域=数组名 还是上面的例子,我们可改为: 复制内容到剪贴板
这里,我们用“[a1:a60000] = Application.WorksheetFunction.Transpose(arr)”代替了上面代码For循环,在我的电脑上,程序的效率就提高了25倍以上。 数组写入单元格.rar (8.04 KB)
所以在大批量的数据需要写入时,我建议尽量不要用循环的方式写入。代码: Sub test2() 这种批量写入的方式在上面的例子里其实我已经用到了,相信大家不会陌生。 这里,我再补充两点我个人在学习过程中的心得: (1)一维数组写入单元格区域时,这个单元格必须是水平方向的,也就是一个一行多列的单元格区域,如果想写入垂直区域,必须使用工作表的Transpose函数转换一下; (2)和工作表的多单元格数组公式一样,数组写入单元格时,单元格的区域必须和数组的大小一致。 |
|