Excel 2010 VBA 入门 093 数据处理之建立数组
目录
示例
代码
数组的基本概念
数组的声明
数组的赋值与数组数据的读取
Ubound和Lbound函数获取数组的上下限
ForEach---Next循环遍历数组的注意事项
计算程序运行的时间
数组处理的极限
示例
如图所示,该表为某公司的产品销售记录。现需要根据规格型号建立汇总表,并根据单元格G2所示的规格型号汇总数量及金额,然后将结果存入H2和I2中。由于该表数据超过10万条,如何利用数组加快该查询?
规格型号 | 数量 | 单价 | 金额 | 规格型号 | 数量 | 金额 | ||
3D7A | 3 | 9.29 | 27.87 | |||||
3D7A | 7 | 9.29 | 65.03 | |||||
3D7A | 22 | 9.29 | 204.38 | |||||
8D9A | 200 | 35.4419 | 7088.38 | |||||
8D9A | 100 | 35.4419 | 3544.19 | |||||
8D9A | 100 | 35.4419 | 3544.19 | |||||
8D9A | 100 | 35.4419 | 3544.19 | |||||
3D7A | 17 | 9.29 | 157.93 | |||||
3D7A | 106 | 9.29 | 984.74 | |||||
3D7A | 62 | 9.29 | 575.98 | |||||
3D7A | 18 | 9.29 | 167.22 | |||||
3D7A | 32 | 9.29 | 297.28 | |||||
3D7A | 197 | 9.29 | 1830.13 | |||||
3D7A | 156 | 9.29 | 1449.24 | |||||
3D7A | 132 | 9.29 | 1226.28 | |||||
3D7A | 120 | 9.29 | 1114.8 | |||||
3D7A | 41 | 9.29 | 380.89 | |||||
3D7A | 37 | 9.29 | 343.73 | |||||
3D7A | 113 | 9.29 | 1049.77 | |||||
3D7A | 111 | 9.29 | 1031.19 | |||||
3D7A | 133 | 9.29 | 1235.57 |
代码
将原始数据区域读入数组中,然后循环遍历数组中的每一行元素,当规格型号与指定规格型号相同时,则累加其数量和金额至指定的变量中。
Option ExplicitSub 用数组统计()Dim Arr()Dim RowN As LongDim TotalQTY As Long '数量Dim TotalAmount As Double '金额Dim sType As String '型号'汇总条件sType = Range("G2").ValueTotalQTY = 0TotalAmount = 0Arr = Range("A1").CurrentRegion.ValueFor RowN = 2 To UBound(Arr)If Arr(RowN, 1) = sType ThenTotalQTY = TotalQTY + Arr(RowN, 3)TotalAmount = TotalAmount + Arr(RowN, 4)End IfNext RowNRange("H2").Value = TotalQTYRange("I2").Value = TotalAmount
End Sub
数组的基本概念
数组是一个特殊的变量,其表示一组数据的集合。在VBA中,允许将多个类型相同或者不相同的数据组合成一个集合,然后用其下标访问其每个元素。该集合称为数组。
数组的大小指其包含数组的个数,在内存允许的情况下,数组可以包含任意数量的元素,但不会超过数值类型数据的最大范围。借助下标可以表示数组中的元素,如一维数组表示方式如下:
Array(index)
该表达式表示数组中的一个元素。其中Array表示一个数组变量,index为其下标。数组的下标可以为正数、负数或者0,但是必须为整数。
数组下标的范围构成了数组的大小,其下标最小值称为数组的下限,下标的最大值称为数组的上限。因而,数组的大小=上限一下限+1。
数组可以具有多个下标。当数组具有多个下标时,该数组即为多维数组。多维数组的元素使用以下表达式表示:
Array(index1,index2[[,index3],...,indexn])
其中,indexl至indexn表不不同维度的数组下标。
在Excel VBA中,数组的维度最多不超过60。当使用多维数组时,可以存放的数据个数是各个维度上大小的乘积。如一个二维数组的第1维度大小为10,第2个维度的大小为20,则该数组可以存放10×20(即200)个数据。
一般地,可以将不同属性的元素存放于不同维度的数组中。比如工作表中的单元格区域,可以使用一个二维数组表示,其表示方式与使用Cells表示单元格相同,如:
Cells(RowN,ColN)
与
Array(index1,index2)
Cells表达式中的行号RowN与Array数组中的第1个维度的下标index1对应,并且Cells表达式中的列号CoIN与数组的第2个维度的下标index2对应。因而,当使用数组代替单元格对象进行运算时,可以将indexl当作行号进行处理,将index2当作列号进行处理。
数组的声明
按数组元素个数是否固定可以分为固定大小的数组和动态数组。固定大小的数组的维度以及各个维度的大小是固定的,而动态数组则可以改变维度以及各个维度的大小。固定大小的数组的声明方式如下:
Dim ArrayName(LBI To UBI [ [,LB2 To UB2] , ..., LBn To Ubn]
其中,ArrayName表示数组变量的名称。LBn和Ubn分别表示不同维度上的数组的下限和上限。不同维度上的LB及UB可以各不相同。也可以采用以下方式声明一个固定大小的数组:
DimArrayName ( UBI [ [ , UB2 ] , --., Ubn ]
该声明方式隐藏了各个维度数组下限的声明,所有维度的数组下限在默认情况下为0。
上述两种声明固定大小的数组的方式可以混合使用,当省略下限声明时,则采用系统默认的下限。如以下表达式声明了一个第1维下限为0、上限为1,以及第2维下限为2、上限为3的数组。
Dim arr(l, 2 To 3)
声明动态数组可以省略数组声明中上下限的定义,即
Dim ArrayName ()
其中,ArrayName表示数组变量的名称。
动态数组声明后不可直接使用,除非被另一个数组或者单元格区域赋值。但是动态数组允许使用Redim语句重新定义其维度和大小,在重新定义后,原数组中的元素将全部删除。Redim语句语法如下:
ReDim ArrayName (LBI To UBI [ [, LB2 To UB2] , ...,LBn To Ubn]
数组的赋值与数组数据的读取
对于已经定义大小的数组,无论是固定大小的数组还是动态数组,均可以使用数组的下标形式对数组元素进行访问,从而实现读取与赋值。当需要访问数组的所有元素时,可以使用For---Next循环,将计数器设置为下标和上标间的变化即可,如:
For Index = LB To UB'操作 Array (Index)
Next
对于动态数组而言,可以直接由另一个已经赋值的数组或者已经定义其大小的数组直接赋值。如以下语句中,Arrayl是一个已经赋值的数组,Arr表示一个动态数组,则通过以下表达式,Arr可以被赋值为Array1,其大小和数组中元素的值与在执行该表达式时的Arrayl完全一致。
Arr=Array1
对动态数组而言,可以直接从连续的单元格区域中读取值,并根据该单元格区域的大小定义数组的大小。如执行以下表达式之后,数组Arr将成为一个二维数组,并且第1维大小等于单元格区域Range的行数,第2维的大小等于单元格区域Range的列数。此外,采用此方式赋值时,第1维和第2维的下限将自动设置为1。
Arr=Range.Value
因而,对于本例,需要将整个原数据表赋值到数组中,可以有以下两种方式。
- ·利用VBA获取数据源的尺寸(行数、列数),然后定义数组的大小,再利用循环将工作表中的值读取至数组中。
- ·直接将整个单元格区域的数据赋值给动态数组。
上述两种方法中,无论是执行速度还是便捷性方面,都是第2种方法占绝对优势。并且,在数组中操作数据比直接访问单元格操作数据的速度快许多,因而当需要对连续单元格区域进行操作时,一般总是将其值赋值给数组,然后利用数组直接操作数据。在单元格的值赋值给数组之后,无须再次获取单元格区域的大小,可以使用Ubound和Lbound函数获取数组的上下限。
Ubound和Lbound函数获取数组的上下限
Ubound函数和Lbound函数可以分别获取己定义大小的数组在不同维度的上限和下限,其语法为:
UBound (arrayname [, dimension ]
LBound (arrayname [, dimension ]
其中,参数arrayname为数组变量。可选参数dimension表示获取上下限的数组维度,可以为1至60的整数,当该参数省略时,则获取第1个维度的上下限。
本例中,由于单元格区域赋值给数组后,数组的下标下限为1,因而仅需要使用Ubound函数获取数组上限,即可得到循环的界限。
ForEach---Next循环遍历数组的注意事项
无论数组维度是多少,ForEach---Next循环都可以用来读取数组中的每个元素,其语法结构如下:
dim arrayElement as variant
for each arrayElement In arrayName'读取arrayElement
Next arrayElement
其中,变量arrayElement表示数组中的元素,变量arrayName表示数组。
使用该结构需要特别注意以下两点。
- ·使用ForEach--.Next循环结构遍历数组时,其表示数组元素的变量arrayElement必须为变体型变量(Variant)。
- ·由于该结构用于数组时是按值传递变量的,因而通过该循环结构访问数组元素时,不能改变数组中的元素。
计算程序运行的时间
相对于直接逐个访问单元格进行操作而言,本例的方案在速度上获得了极大的提升,并且可以通过VBA实际测量两个程序运行所需的时间。此处需借用VBA中的Timer函数,该函数可以返回一个Single类型的数据,其表示从午夜0点起所经过的秒数。对于程序的运行速度,可以在程序语句开始运行之前读取Timer的值,然后在程序结束时读取Timer的值,最后根据两者之差计算出所经过的时间(即程序运行的时间)。参考结构如下:
Dim t As Single
t = Timer
Debug. Print Timer - t
其中,变量t用来记录程序语句开始运行之前Timer的值。最后将在VBE的“立即窗口”中得到程序运行的时间。
数组处理的极限
尽管数组的大小没有限制(仅限于内存的容量),并且数组可以帮助开发者加快程序运行的速度。然而,当数组的大小极大或者已经接近内存容量时,数组的运行效率将极大地下降。一般而言,处理十万数量级的数据,数组可以正常发挥其高速的特性。然而当数据的数量级到达百万甚至千万时,数组的运行速度可能并非呈线性增加。比如,使用数组处理1万个数据耗时0.1秒,用相同的方法处理10万个数据耗时1秒,而当用相同的方法处理1000万个数据时,耗时往往不止100秒,而可能需要耗时20 0秒甚至更多的时间,或者由于内存不够而无法进行。(具体耗费时间与具体执行程序以及各计算机的配置相关,也有可能耗时随着数据量的增加始终呈线性增加。此处仅为举例说明。)
针对以上问题,可以使用分拆的方法进行解决。开发者可以尝试将数据分为若干个组,每个组使用数组进行数据处理,然后利用循环处理数据中所有的组。比如,在Excel工作表中处理10万行100列的数据,可以尝试将10万行数据分为1万行一组,然后分组处理,而非直接将1000万个数据读入数组中。如此操作尽管增加了不少代码,但可能对数组处理数据的速度有所提升,而至关重要的是此操作可以避免由于内存不足而发生程序无法运行的情况。需特别注意的是,分组的大小由程序、计算机的配置等诸多因素决定,并不能一概而论。
Excel 2010 VBA 入门 093 数据处理之建立数组相关推荐
- Excel 2010 VBA 入门 095 数据处理之用数组实现分列
示例 如图所示,该表为某系统中导出的数据.由于该数据将原本的四列信息合并至一个单元格中,现希望利用数组对该数据进行分列,将其分为四列. 关键词;关注指数;升降幅度;升降位次 小胸钢托聚拢游泳衣;12; ...
- Excel 2010 VBA 入门 088 数据处理之汇总列数不相等的多个工作表
目录 示例 代码1 合并汇总(Consolidate)方法 Array函数 Evaluate方法构造数组 代码2 示例 如图所示,该工作簿中有若干个工资表,由于每个月发放的工资项目不同,因而造成每个工 ...
- Excel 2010 VBA 入门 087 数据处理之按单列汇总多个工作表
示例 如图所示,该工作簿中包含若干个工作表,工作表中为各个学校书籍销售明细.如 何使用VBA按其工作表中的图书名称汇总各种图书的数量? 示例数据表 序号 图书名称 版 别 年版 定价 适读范围 订 ...
- Excel 2010 VBA 入门 086 数据处理之获取交叉查询结果表
目录 示例 代码 交叉汇总表 建立交叉汇总表的步骤 建立交叉汇总表的优化 示例 如图所示,该表为某公司的销售数据表.现希望建立一个汇总表,按月份和商品名汇总收入,并将月份作为列标题而商品名作为行标题. ...
- Excel 2010 VBA 入门 081 数据处理之获取不重复的数据
目录 示例 示例数据表 代码1 去除重复值(RemoveDuplicates)方法 代码2 代码3 示例 如图所示,该表为某村人口登记表.现希望得知有哪些户的居民已登记,因而希望获取"户号& ...
- Excel 2010 VBA 入门 082 数据处理之对比两个表的数据
示例: 如图所示,该工作簿中有两个来自不同数据源的材料表,这两个表中的数据可能不同.如何使用VBA比较两张表的编号与数量,并建立一张对照表,分别列出两张表的不同:编号同时存在但数量不同:编号在其中一张 ...
- Excel 2010 VBA 入门 077 数据处理之合计汇总
目录 示例 代码1 代码2 代码3 示例 如图所示,该表为某公司年度销售表.如何使用VBA求出每个销售员的年度销售额合计以及公司月度销售合计? 销售员 1月 2月 3月 4月 5月 6月 7月 8月 ...
- Excel 2010 VBA 入门 076 数据处理之计算个人所得税
目录 个人所得税税率表(月度综合所得,适用于2019年及以后取得的综合所得) 代码 个人所得税税率表(月度综合所得,适用于2019年及以后取得的综合所得) (非居民个人工资.薪金所得,劳务报酬所得,稿 ...
- Excel 2010 VBA 入门 034 创建图片批注
目录 批注(Comment)对象 批注的添加与删除 FiIIFormat对象 OnError语句 示例: 批注(Comment)对象 Comment对象是单元格的一个属性,表示单元格的批注.Comme ...
最新文章
- Java 地位不保,落后已成定局 ?| 10月编程语言排行
- java数组长度怎么看,威力加强版
- Python基础教程(五):数字、字符串
- shell脚本应用(二)
- 用paddleocr识别汉字_汉字设计中的度量标准(三)
- Java 第四周总结
- 网络分层协议图以及各层的简介
- win7无法打开设备和打印机
- 数学概念的提出(一) —— 熵的定义式 H(x)=-log2(p(x))
- Web 开发人员和设计师必读文章推荐【系列三十】
- nohup方式 真正的后台不挂断运行程序
- 查找php超时原因_php环境搭建(正确配置nginx和php)
- RabbitMQ消息确认机制之Confirm模式总结
- 谭浩强c语言程序设计试题汇编pdf,C语言程序设计基础(谭浩强)习题.pdf
- globeimposter 解密工具_WinRAR加密和压缩伪装成GlobeImposter勒索软件,易于安全专家解密...
- 计算机并行配置,windows10无法启动应用程序提示并行配置不正确解决方法
- [Unity]Mathf.Pingpong无效解决方法
- 在为订单 7000009确定实际成本中出错
- NFC应用(二)读写器模式
- 安卓京东自动炸年兽v4.1.1
热门文章
- 基于truffle-contract库之solidity事件与合约调用完整案例!
- 生物统计学(biostatistics)学习笔记(四)统计推断(已知样本推总体)
- Keil MDK5 详细安装教程
- PWC-Net: CNNs for Optical Flow Using Pyramid, Warping, and Cost Volume
- switch 语句的参数类型
- EAO-SLAM: Monocular Semi-Dense Object SLAM Based on Ensemble Data Association
- 语义通信(Semantic Communication)
- 泽塔云CEO查乾:2019年超融合进入成熟市场,GPU云带来千亿级市场
- 【JavaMap接口】HashMap源码解读实例
- jquery管理数据