九、VBA数组

一、问题导入
问题描述:文件“DEMO-2-使用数组大幅度提升VBA代码执行效率”中有20万条记录,需要根据区域求汇总金额,用for循环处理(注意i不能定义为integer,溢出),耗时较长。
处理过程:(1)希望准确记录耗时,引入timer函数(返回从午夜到现在经过的秒数),运行前 t=timer,运行后“MsgBox Timer - t”
     (2)耗时较长的原因在于:每次循环都要到单元格“n5”中取值,若每次是取变量值,则速度大幅提高,因此dim str as string,str=range("n5")后,替换循环中的“n5”
     (3)将for循环中的单元格取数替换成变量取数,能大幅提升速度,能否将其中每次循环的到Range("g"&i)取数替换成变量?
     (4)i从2到200000,Range("g"&i)是一系列数字在一起,因此是数组,引入数组概念。定义数组:Dim arr()给数组赋值:arr=range("a1:d7"),如何取数?
     (5)用一小段区域演示数组取值arr(x,y),其中x是数组区域的行数,y是数组区域的列数;
     (6)用数组替换原代码,大幅提升速度。

二、进一步认识数组
“”认识数组“文件”:(1)数组分一维、二维、多维,上例是二维数组;
         (2)一维数组定义时应指定标号范围,如Dim arr(1 to 5),否则容易报错;
         (3)可一个一个地将一维数组的值赋给变量,如i = arr(2),也可一次赋给区域,如Range("a1:e1")=arr;
         (4)一维数组默认是行方向数组,因此只能给行区域一次性赋值,若给列区域赋值,如Range("a1:a5")=arr,结果是列区域获得的值都是arr(1);
         (5)若用区域给数组初始化,则无论区域如何,生成的是二维数组,如arr=Range("a1:a5"),虽仅一列,但赋值时需用二维方式:Range("c1")=arr(2,1)
         (6)回顾split函数截取字符,生成的结果是数组,进一步理解该函数的应用。

三、进一步认识数组(查找销量冠军)
问题描述:要完成表中“销售额最高的产品“和”该产品的销售额”,传统做法需新建辅助列进行计算后查询填入,较麻烦,有时甚至不方便操作辅助列。
处理过程:(1)引入数组,规避辅助列问题,如下左边代码;
     (2)用Application.WorksheetFunction.Max(arr)查询到最大的销售额,填入;
     (3)需找到其对应产品名称,先找其在数组中位置为:Application.WorksheetFunction.Match(Range("h3"), arr, 0) + 1,因此可得产品名称为
        Range("a" &Application.WorksheetFunction.Match(Range("h3"), arr, 0) + 1)
        tips:Match(要在表中查找的值, 可能包含所要查找的值的连续单元格区域, 0),其中0代表等于匹配,返回相应位置
     (4)上述解决过程的缺陷在于需事先确定数组大小,但往往不易确定。改进:先定义为不定arr(),再redim。(不允许直接以变量dim arr(1 to j))
     (5)了解两个函数:UBound(arr),LBound(arr),分别返回数组标号的上下限,用其可方便构造数组的循环。

Dim arr(1 to 5)
For i = 1 To 5
    arr(i) = Range("b" & i + 1) * Range("c" & i + 1)
Next
Dim arr()
Dim j, i As Integer
j = Range("a65536").End(xlUp).Row - 1
ReDim arr(1 To j)

四、排列组合计算回款信息
  凑数,用四层循环,太慢。
  改用数组: Dim arr()     arr=range("a1:a80") 容易测算运行时间减少倍数。
  注意新的跳出循环方式:GoTo 语句
  用法: 循环内找到时:GoTo 100,然后在跳出的地方写:“100     (换行)继续执行的语句”

上一篇:《SeleniumBasic 3.141.0.0 - 在VBA中操作浏览器》高级技术之九:SeleniumBasic设置代理


下一篇:Python的文件操作