乐于分享
好东西不私藏

Excel VBA数组进阶三连:从“会用”到“会玩”,看完你就是办公室最靓的仔!

Excel VBA数组进阶三连:从“会用”到“会玩”,看完你就是办公室最靓的仔!

写在前面:如果你还不会数组基础,请先面壁三分钟

上篇文章发出后,有个同事问我:“大哥,我按照你的代码写了,但是报错‘下标越界’,是不是Excel瞧不起我?”

我问他:“你的数组声明的啥?”

他说:“Dim arr(1 To 10)”

我问他:“你往里塞了多少数据?”

他说:“11行…”

朋友,数组不是海绵宝宝,挤不下别硬塞啊!

如果你连数组的声明、赋值、读取都还迷迷糊糊,建议先翻回去补课。今天这篇文章,是给那些已经能用数组跑起来,但想跑得更骚的同学准备的。

第一课:一维数组 vs 二维数组,你还在傻傻分不清?

很多同学学了数组,依然搞不清什么时候用一维,什么时候用二维。

一维数组:就是一根烤串。一串羊肉串,你只能从第一块吃到最后一块,顺序排列。

二维数组:是一张火锅桌。横着数有座位,竖着数也有座位,想坐哪桌坐哪桌。

看代码:

‘ 一维数组:适合处理单行或单列

Dim 烤串(1 To 10) As String

烤串(1) = “羊肉”

烤串(2) = “牛肉”

‘ 这叫串串香

‘ 二维数组:适合处理表格区域

Dim 火锅桌(1 To 5, 1 To 4) As String

火锅桌(2, 3) = “毛肚”  ‘ 第2行第3列,毛肚的位置

‘ 这叫火锅局

灵魂拷问:当你从Excel区域取值时,得到的是几维数组?

arr = Range(“A1:A10”).Value   ‘ 这是几维?

brr = Range(“A1:D10”).Value   ‘ 这是几维?

crr = Range(“A1”).Value       ‘ 这又是啥?

答案:

A1:A10:虽然只有一列,但VBA会把它变成二维数组!(10行,1列)

A1:D10:标准的二维数组 (10行,4列)

A1:只有一个单元格,VBA会把它变成二维数组!(1行,1列)

扎心真相:从工作表取出来的数据,永远是二维数组,哪怕只有一行一列。

这就是为什么很多新手写 arr = Range(“A1:A10”).Value 后,想用 arr(1) 取值,结果报错——你应该用 arr(1, 1)!

第二课:数组的“降维打击”,学会了你就是大神

既然从工作表取出来的永远是二维数组,那我想处理一列数据怎么办?

方案A:硬着头皮用二维

arr = Range(“A1:A10”).Value

For i = 1 To 10

    Debug.Print arr(i, 1)  ‘ 永远记得加个逗号1

Next i

方案B:降维打击(Transpose大法)

arr = Range(“A1:A10”).Value

‘ 使用WorksheetFunction.Transpose进行降维

一维数组 = Application.Transpose(arr)

For i = 1 To 10

    Debug.Print 一维数组(i)  ‘ 现在可以像烤串一样直接取了

Next i

注意:Transpose是Excel的工作表函数,在VBA里用Application.Transpose调用。它能把:

单列二维数组 → 一维数组(列转行)

单行二维数组 → 一维数组(行转列)

二维区域 → 转置(行列互换)

但是:Transpose有容量限制(约65537个元素),超了会报错。这是Excel的历史包袱,别问,问就是微软的锅。

第三课:动态数组的骚操作,ReDim Preserve你真的会用吗?

动态数组就像伸缩裤腰带——吃多了能放长,饿瘦了能收紧。

Dim arr() As Variant

ReDim arr(1 To 5)  ‘ 先来5个位置

‘ 填数据…

For i = 1 To 5

    arr(i) = i * 10

Next i

‘ 突然发现还要再加3个位置

ReDim Preserve arr(1 To 8)  ‘ Preserve保留原有数据,裤腰带放长三格

但是:ReDim Preserve有个巨坑——它只能修改最后一维的大小!

什么意思?

‘ 二维数组

Dim brr() As Variant

ReDim brr(1 To 5, 1 To 3)

‘ 想增加列数?可以!

ReDim Preserve brr(1 To 5, 1 To 4)  ‘ 没问题,最后一维从3变4

‘ 想增加行数?报错!

ReDim Preserve brr(1 To 6, 1 To 3)  ‘ 报错!不能改第一维!

为什么?

微软说:这是底层设计,我也没办法。(其实就是懒)

解决方案:要么一开始把行数估计大一点,要么用Transpose把行列互换后再Preserve,完事儿再转回来。

这操作就像脱裤子放屁,但有时候真管用:

‘ 骚操作:先转置,让想增加的那一维变成最后一维

brr转置 = Application.Transpose(brr)

ReDim Preserve brr转置(1 To 3, 1 To 6)  ‘ 现在可以增加行了(原列)

brr = Application.Transpose(brr转置)     ‘ 再转回来

警告:这招慎用,数据量大了转两次挺费时间。但面试时说出来,面试官会觉得你是个狠人。

第四课:数组与字典的“神仙组合”,查找速度快到飞起

数组处理数据快,但有个致命弱点——查找慢。

你想在10000个数据里找“张三”,用数组得循环10000次。虽然比单元格循环快,但还是不够优雅。

这时候,字典(Dictionary) 出场了。

把字典想象成酒店前台:

数组:你得一间一间敲门问“张三住哪?”

字典:前台小姐姐一秒告诉你“308房”

组合拳打法:

‘ 先引用:工具→引用→勾选 Microsoft Scripting Runtime

Sub 数组加字典()

    Dim arr As Variant

    Dim dic As New Dictionary

    Dim i As Long

    ‘ 把数据装进数组

    arr = Range(“A1:B10000”).Value

    ‘ 遍历数组,把关键信息存进字典

    For i = 1 To UBound(arr)

        ‘ 把姓名作为key,所在行号作为item

        dic(arr(i, 1)) = i

    Next i

    ‘ 秒查“李四”在哪一行

    If dic.Exists(“李四”) Then

        MsgBox “李四在第” & dic(“李四”) & “行,他的成绩是” & arr(dic(“李四”), 2)

    Else

        MsgBox “查无此人”

    End If

End Sub

威力:

数组负责批量运输数据

字典负责秒级查找数据

两者结合,又快又准

这就好比:你开着卡车(数组)把一仓库货拉到分拣中心,然后让AI机器人(字典)帮你找货。这才是现代办公的姿势!

第五课:数组与数组之间的“联姻”,你必须要懂的合并技巧

有时候,你需要把两个数组合并成一个。

比如:

数组A:员工姓名

数组B:员工工资

想要:姓名+工资一一对应的二维数组

青铜操作:循环赋值

Dim arr(1 To 10, 1 To 2)

For i = 1 To 10

    arr(i, 1) = 姓名数组(i)

    arr(i, 2) = 工资数组(i)

Next i

王者操作:利用Index函数(需要想象力)

‘ 假设有两个一维数组

姓名 = Array(“张三”, “李四”, “王五”)

工资 = Array(5000, 8000, 6000)

‘ 构建二维数组

ReDim 结果(1 To 3, 1 To 2)

For i = 1 To 3

    结果(i, 1) = 姓名(i)

    结果(i, 2) = 工资(i)

Next i

‘ 没有捷径,该循环还得循环

但是:如果想把两个二维数组横向拼接(加列),或者纵向拼接(加行),那就有意思了。

纵向拼接(加行):

‘ 数组A:1-5行,数组B:6-10行

ReDim 结果(1 To 10, 1 To 列数)

For i = 1 To 5

    For j = 1 To 列数

        结果(i, j) = 数组A(i, j)

    Next j

Next i

For i = 1 To 5

    For j = 1 To 列数

        结果(i + 5, j) = 数组B(i, j)

    Next j

Next i

横向拼接(加列):

‘ 数组A:1-3列,数组B:4-6列

ReDim 结果(1 To 行数, 1 To 6)

For i = 1 To 行数

    For j = 1 To 3

        结果(i, j) = 数组A(i, j)

    Next j

    For j = 1 To 3

        结果(i, j + 3) = 数组B(i, j)

    Next j

Next i

核心思想:数组合并,本质上是手动搬家。没有一键合并的函数,得自己当搬运工。

第六课:数组内存管理,让你的代码再快50%

数组用得好不好,关键看你会不会清理内存。

坏习惯:

Sub 坏习惯()

    Dim arr As Variant

    arr = Range(“A1:D10000”).Value

    ‘ 处理数据…

    ‘ 结束时啥也不干

End Sub

‘ 子程序结束后,arr还在内存里赖着不走

好习惯:

Sub 好习惯()

    Dim arr As Variant

    arr = Range(“A1:D10000”).Value

    ‘ 处理数据…

    ‘ 用完就扔

    Erase arr  ‘ 清空数组,释放内存

    ‘ 或者

    Set arr = Nothing  ‘ 对象用这个,数组用Erase

End Sub

什么时候重要:

处理小数据:无所谓

处理十万行以上:不释放内存,运行多次后Excel会崩

循环里反复创建数组:必须释放,不然内存泄漏

进阶技巧:用Nothing vs Erase

Erase arr:把数组里的数据清空,数组本身还在(可以ReDim重用)

Set arr = Nothing:彻底销毁对象(用于字典、集合等)

数组的生死:

出生:Dim或ReDim

活着:arr = 数据

失忆:Erase

超度:子程序结束 or Set arr = Nothing

记住了:写完代码,记得给数组办身后事。这是专业和业余的分水岭。

第七课:实战案例——用数组制作“超级查询器”

学了这么多,不来个硬核实战说不过去。

需求:有两个工作表,“数据源”有10万行销售记录,“查询表”有1000个产品ID,需要快速找出每个产品的销量。

青铜做法:

For i = 1 To 1000

    ID = Sheets(“查询表”).Cells(i, 1)

    For j = 1 To 100000

        If Sheets(“数据源”).Cells(j, 1) = ID Then

            Sheets(“查询表”).Cells(i, 2) = Sheets(“数据源”).Cells(j, 2)

            Exit For

        End If

    Next j

Next i

‘ 运行时间:下班前点运行,第二天早上看结果

王者做法(数组+字典):

Sub 超级查询器()

    Dim 数据源 As Variant

    Dim 查询表 As Variant

    Dim dic As New Dictionary

    Dim i As Long

    Dim startTime As Double

    startTime = Timer

    ‘ 1. 把数据源装进数组

    数据源 = Sheets(“数据源”).Range(“A1:B” & Sheets(“数据源”).Cells(Rows.Count, 1).End(xlUp).Row).Value

    ‘ 2. 建立字典索引

    For i = 1 To UBound(数据源)

        ‘ 假设A列是ID,B列是销量

        If Not dic.Exists(数据源(i, 1)) Then

            dic(数据源(i, 1)) = 数据源(i, 2)

        End If

    Next i

    ‘ 3. 处理查询表

    查询表 = Sheets(“查询表”).Range(“A1:B” & Sheets(“查询表”).Cells(Rows.Count, 1).End(xlUp).Row).Value

    For i = 1 To UBound(查询表)

        If dic.Exists(查询表(i, 1)) Then

            查询表(i, 2) = dic(查询表(i, 1))

        Else

            查询表(i, 2) = “未找到”

        End If

    Next i

    ‘ 4. 写回结果

    Sheets(“查询表”).Range(“A1:B” & UBound(查询表)).Value = 查询表

    ‘ 5. 清理

    Erase 数据源

    Erase 查询表

    Set dic = Nothing

    MsgBox “查询完成,耗时:” & Timer – startTime & “秒”

End Sub

效果:

青铜:几分钟到几小时

王者:0.5秒以内

这就是为什么说:用数组和不用数组,是两个物种。

写在最后:数组之路,道阻且长,行则将至

今天的进阶课就到这里。

如果你看到这里还没关掉,说明你是个有追求的人。你不再满足于“能跑就行”,你想的是“更快、更稳、更骚”。

数组的终极奥义,不是记住那些语法,而是理解:

数据在哪里处理最快? 在内存里。

怎么把数据弄进内存? 用数组。

怎么在内存里玩出花? 数组+字典+算法。

课后作业:

把你之前写的单元格循环代码,全部改成数组操作

试着用字典去重(提示:把数据丢进字典,key自动去重)

挑战:10万行数据,找出所有重复项并标记,限时1秒

评论区交作业,我会随机翻牌点评。要是你的代码够骚,我喊你一声大哥!

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » Excel VBA数组进阶三连:从“会用”到“会玩”,看完你就是办公室最靓的仔!

猜你喜欢

  • 暂无文章