数据处理VBA篇:数组

有些时候我们需要用Excel处理大量的数据,这时候如果还用range引用单元格内容就会显得有点慢,这时候如果采用数组的话呢速度会快一大截,当然速度要在数据量比较大情况下才看的出来。
现在让我们来学习一下数组怎么用吧。

1.数组的声明

  • 一维数组
通过起始和终止索引号定义数组的大小
public/dim 数组名([下界 to] 上界) as 数据类型
下界不填写,默认为0.如果希望默认从1开始,则在用户窗体或模块的声明部分且在声明数组之前输入以下语句:
option base 1
  • 二维数组
public/dim 数组名(第一维上界,第二维上界) as 数据类型   #未指定起始索引号,默认起始索引号为0
或
public/dim 数组名(第一维下界 to 第一维上界,第二维下界 to 第二维上界) as 数据类型
  • 动态数组
第一步:在用户窗体或模块或过程中用dim或public声明一个没有下标的数组(不能省略括号)即:dim/public arr() as  数据类型
注:VBA中不允许在public或dim语句中使用变量来指定数组的大小,但是在redim中却可以用变量来指定数组的大小
第二步:在过程中用redim重定义数组的大小
redim [preserve] 数组名(下标)[as 数据类型]
redim 不能在将一个数组定义为某种数据类型之后改为其他数据类型
Sub 生成幸运号码()
    Dim l()
    Dim n As Integer, x As Integer, y As Integer
    n = InputBox("输入要生成的幸运号码的个数", "幸运号码")
    ReDim l(n, 7)
    For x = 1 To n
        For y = 1 To 7
            Randomize
            l(x, y) = Int(10 * Rnd)
        Next
    Next
    For x = 1 To n
        For y = 1 To 7
            Debug.Print l(x, y);
        Next
     Debug.Print
    Next
End Sub

2.更加简单的数组创建

  • 用array函数创建常量数组
sub test()
     dim arr as variant   #使用array函数创建数组时,该数组应声明为一个variant类型的变量
     arr = array(1,2,3,4,5,6,7,8,9,10)
     msgbox "arr数组的第2个元素是:" & arr(1)  #使用array函数创建的数组索引号默认从0开始,除非使用option base 1.
end sub
  • 使用split函数创建数组
将一个字符串按指定的分隔符拆分,将各部分结果保存到一个一维数组中
Sub test()
     Dim a As String, arr As Variant      '使用split函数创建数组,该数组必须声明为variant类型的变量
     a = "小米,华为,OPPO,苹果,三星"
     arr = Split(a, ",")       '按照","将字符串分割
     MsgBox "arr数组的第3个元素为:" & arr(2)     '使用split函数创建的数组索引号默认从0开始,无论是否使用option base 1
End Sub
  • 通过将单元格区域的值赋给数组
sub test()
     dim arr as variant
     arr = range("a1:c3").value
     range("e1:g3").value = arr
end sub

3. 数组的维数:

总结:二维是由行和列表示的数组,如ARR(3,2)表示数组中第3排第2列的元素。而一维数组只是由一个元素决定,如ARR(4)表示数组中第4个元素

4. 动态数组的声明例子:

Sub darr()
  Dim arr()  '声明一个动态的arr数组(不知道它能盛多少数据)
  Dim k
  k = Application.WorksheetFunction.CountIf(Range("a2:a6"), ">10") '计算大于10的个数
  ReDim arr(1 To k)  '再次声明arr的大小,正好盛下k数量的值
  For x = 2 To 6
    If Cells(x, 1) > 10 Then
      m = m + 1
      arr(m) = Cells(x, 1)  '通过循环把大于10的数字装入数组
    End If
  Next x
  MsgBox arr(2)
End Sub

5. 数组的合并和字符串拆分(Join & Split):

  • 多个字符的合并和字符串按规律的拆分是经常遇到的,如:

**A-REW-E-RWC-2-RWC 按分隔符-拆分成6个字符放在一个数组中 **

有一组数array(23,45,7,1,76)想用分隔符-连接成一个字符串

上面两种情况VBA提供了一对函数,即:

split(字符串,"分隔符") 拆分字符串
join(数组,"分隔符")   用分隔连接数组的每个元成一个字符串   
Sub t1()
      Dim arr, myst As String
      myst = "A-REW-E-RWC-2-RWC"
      arr = Split(myst, "-")  '按-分隔成一组数装入数组中
      MsgBox arr(0) '显示数组的第一个数(分隔后的数组最小下标为0,不是1),显示结果为A
      MsgBox Join(arr, ",") '再用","把数组的每个值连接成一个字符串,结果为"A,REW,E,RWC,2,RWC"
End Sub

值得注意的是:split和join只能对一维数组进行操作,如果是单元格或二维数组怎么办?只有一条途径,想办法转换为一维数组:

Sub t2()
     Dim ARR
     ARR = Application.Transpose(Range("a1:a3")) ‘用转置的方法,把单元格一列数据转换成一维数组
     MsgBox Join(ARR, "-")
End Sub

7. Filter函数实现数组筛选:

数组的筛选就是根据一定的条件,从数组中筛选符合条件的值,组成一个新的数组,实现数组筛选的VBA函数是:

Filter函数

  用法:Filter(数组, 筛选的字符,  是否包含) 

Sub DD()
     arr = Array("ABC", "A", "D", "CA", "ER")
     arr1 = VBA.Filter(arr, "A", True) '筛选所有含A的数值组成一个新数组
     arr2 = VBA.Filter(arr, "A", False) '筛选所有不含A的数值组成一个新数组
     MsgBox Join(arr2, ",") '查看筛选的结果
End Sub

注意:遗憾的是函数只能进行模糊筛选,不能精确匹配。

8. VBA数组各种Excel函数应用

他山之石,可以攻玉,VBA中除可以利用的VBA函数外,还可以调用众多的Excel工作表函数对数组进行分解、查询和分析等,调用工作表函数可以省去循环判断的麻烦,进而提高运行效率。

  • 数组的最值
1、Max和Min
工作表函数Max和Min是求最大值和最小值的函数,同样在VBA中也可以求数组的最大值和最小值。如:
Sub t()
arr = Array(1, 35, 4, 13)

MsgBox Application.Max(arr)  '最大值

MsgBox Application.Min(arr)   '最小值

End Sub
2、large和small
工作表函数large和small 是返回一组数的第N大和第N小,对VBA数组同样适用,如:
Sub t1()
     arr = Array(1, 35, 4, 13)
     MsgBox Application.Large(arr, 2) '第2大值
     MsgBox Application.Small(arr, 2)  '第2小值
End Sub
  • 数组的统计与求和
1、Sum
Sum函数可以在工作表中求,同样也可以对VBA数组求和,如:
Sub t2()
         arr = Array(1, 35, 4, 13)
         MsgBox Application.Sum(arr)  '对数组进行求和
End Sub
2、Count和Counta

                    Count和Counta可以统计数组中数字的个数和数字+文本的个数。

                   Sub t3()
                        arr = Array(1, 35, "a", 4, 13, "b")
                        MsgBox Application.Count(arr)  '返回数字的个数4
                        MsgBox Application.CountA(arr)  ‘返回数组文本和数字的总个数
                   End Sub
  • 数组的查询和拆分

1、Mach查询数组

Match函数可以查询一个指定值在一组数中的位置,它也可以用于VBA数组的查询。如:

                 Sub t4()
                        arr = Array(1, 35, 4, 13)
                        MsgBox Application.Match(4, arr, 0)  '查询数值4在数组Arr中的位置
                End Sub

2、Index拆分数组
数组的拆分在VBA中是一个难题,如果是按行拆分数组,除了用循环外也只能借用API函数完成了。幸好我们可以借用工作表函数index达到按列拆分数组,即多列构成的数组,你可以任意拆分出一列构成新的数组。方法是:Application.Index(数组, , 列数) ,例:

Sub t2()
          arr2 = Range("A1:B4") ‘把单元格区域A1:B4的值装入数组arr2
          arr3 = Application.Index(arr2, , 2)  '把数组第2列拆分出来装入新数组arr3中,新数组为二维数组
           MsgBox arr3(2, 1)  '取出新数组第2行的值
 End Sub

四、数组维数的转换
Transpose转置数组在工作表中可以把行列转换。在VBA中同样也可以做到转换的效果。

1、一维转二维。

Sub t9()
           arr = Array(1, 35, "a", 4, 13, "b")
           arr1 = Application.Transpose(arr)
           MsgBox arr1(2, 1) ‘转换后的数组是1列多行的二维数组
End Sub

2、二维数组转一维。

                  Sub t2()
                       arr2 = Range("A1:B4")
                       arr3 = Application.transpose(Application.Index(arr2, , 2)) '取得arr2第2列数据并转置成1维数组
                      MsgBox arr3(2,)
                  End Sub

五、数组索引号
用ubound函数求出数组的最大索引号
用lbound函数求出数组的最小索引号

sub test()
     dim srr(1 to 10,1 to 100) as interger
     dim a as interger,b as interger
     a = ubound(arr,1)  '行的最大索引号
     b = ubound(arr,2)   '列的最大索引号
end sub

求数组包含的元素个数

ubound(数组)-lbound(数组)+1

注:在转置时只有1列N行的数组才能直接转置成一维数组
思考题:我要把a1:c1中的内容用“-”连接起来,下面代码中为什么用了两次transpose

Sub t10()
     arr = Range("A1:C1")  '二维数组
     MsgBox Join(Application.Transpose(Application.Transpose(arr)), "-")
End Sub
  • VBA数组与单元格区域的关系(要点):
    1、VBA“眼”中的单元格区域,全部都是二维的,不存在一维。单元格区域直接导入内存形成的VBA数组,全部都是二维VBA数组,不会形成VBA一维数组;
    2、由单元格区域导入内存形成的VBA数组的最小下标,都是1(无论是行下标还是列下标);
    3、单行单元格区域的值,经过二次转置会“脱离”单元格区域而形成“一行”纯数值,其对应VBA数组是一维数组;
    一维VBA数组,可以直接赋值到一行单元格区域或者一列单元格区域
    单行的二维VBA数组,也可以直接赋值到一行单元格区域,但是赋值到一列单元格区域的话必须用transpose函数进行转置
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 160,165评论 4 364
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,720评论 1 298
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,849评论 0 244
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,245评论 0 213
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,596评论 3 288
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,747评论 1 222
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,977评论 2 315
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,708评论 0 204
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,448评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,657评论 2 249
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,141评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,493评论 3 258
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,153评论 3 238
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,108评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,890评论 0 198
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,799评论 2 277
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,685评论 2 272

推荐阅读更多精彩内容

  • 函数可以应用于数组,不需要进行循环。 一 函数在数组中的应用 1.1 数组的最值 Sub s() Dim arr1...
    肉丸子豆阅读 1,248评论 0 3
  • VBA学习笔记 笔记摘抄自EXCEL精英培训-蓝色幻想 VBA学习笔记01(链接)VBA学习笔记02 (链接) 目...
    天天向上的orange阅读 3,369评论 2 32
  • 1.1 VBA是什么 直到90年代早期,使应用程序自动化还是充满挑战性的领域.对每个需要自动化的应用程序,人们不得...
    浮浮尘尘阅读 21,500评论 6 49
  • 本例为设置密码窗口 (1) If Application.InputBox(“请输入密码:”) = 1234 Th...
    浮浮尘尘阅读 13,287评论 1 20
  • 十一月的第二天,我终于打开了我的笔记本安静的坐在桌前,敲击着键盘,我离上一次打开电脑已经间隔了两个星期。 两周前的...
    蔷小薇薇阅读 270评论 0 0