Excel VBA中的对象
VBA 中对象到底是什么?
前面我们已经学了不少 VBA 的基础内容。
变量怎么定义,循环怎么写,判断怎么分支,字符串怎么处理,这些都算是 VBA 里面很核心的基本功。你学到这里,其实已经可以写出一些小程序了。比如做个判断、跑个循环、统计个结果,或者批量处理一点简单数据,这些都没什么问题。
而且说实话,如果你本来就是 Excel 用得比较熟的人,公式、透视表也已经玩得很熟了,很多时候你可能会冒出一个很真实的想法:
我表也会做,公式也会写,透视表也拉得飞快,那我还学这个“对象”干啥呢?
这个问题问得特别正常。
因为如果 VBA 的本事只是“算算账”“做做统计”“处理一下单元格里的数字”,那我确实会更建议你去狠狠钻公式、钻透视表。那两套东西在很多数据计算场景里,本来就非常强,而且上手比 VBA 更直接。
但 VBA 真正厉害的地方,其实不在“算”。
它真正厉害的地方在于:它能控制东西。
它不只是让你算出一个结果,它还可以让你去操作工作表、工作簿、单元格、批注、图形、文件,甚至在一定范围内去联动 Excel 之外的软件,让那些原本得靠你手动点来点去的动作,变成自动执行。
你一旦开始理解“对象”这个东西,看到的就不是单纯的 VBA 语法了,而是一个新世界。
所以这一篇,我们就专门把 VBA 里的“对象”讲清楚。
前面学的是“怎么写”,这一篇学的是“到底在操作谁”
前面那些变量、循环、判断,其实更像是编程语言内部的基础能力。
比如:
-
变量,是拿来记数据的 -
判断,是拿来分情况处理的 -
循环,是拿来重复执行的
这些都很重要,但它们更多解决的是一个问题:
代码该怎么组织。
而对象解决的,是另一个问题:
你这段代码,到底在操控谁。
你平时在 Excel 里做的很多事,本质上都不是“计算”,而是“操作”。
你会去:
-
改某个单元格的内容 -
给一整行上颜色 -
复制一张工作表 -
删除一个批注 -
保存一个工作簿 -
批量打开某个文件夹里的文件
这些动作,光靠 If 和 For 是做不出来的。你得先找到那个被操作的目标,然后再告诉它该干什么。
而这个“被操作的目标”,在 VBA 里,就是对象。
所以你可以先把对象理解得非常接地气一点:
对象,就是 Excel 这个世界里那些能被你点名、能被你操作的东西。
你可以先把对象想成“一个能被你指挥的东西”
这个概念别想太复杂。
打开 Excel 以后,你眼前看到的那些东西,其实很多都可以被当成对象。
比如:
-
Excel 程序本身,可以看成一个对象 -
一个工作簿,是对象 -
一张工作表,是对象 -
一个单元格区域,是对象 -
一个图表,是对象 -
一个批注,也是对象
只要这个东西能被单独拿出来描述,能被读取,能被修改,能被执行某种操作,它大概率就可以被当成对象看。
所以 VBA 并不是在对着空气发命令。它每一步都得先找到一个具体目标,再去改它、读它、让它执行动作。
这就是对象最朴素的理解。
为什么 VBA 一讲到对象,很多人会突然开始迷糊
因为前面学语法的时候,大家的注意力都放在“这一句怎么写”上。
但对象这一层进来以后,问题就变了。
你不只是要知道语句怎么写,你还得知道:
-
这句代码在操作谁 -
这个谁,属于哪一类东西 -
它身上有哪些信息能读 -
它又能执行哪些动作
也就是说,从这里开始,你学的不再只是“说话方式”,而是在学“你到底在跟谁说话”。
这一层一旦没转过来,后面看 VBA 代码就很容易只剩“记格式”。
比如看到:
-
1
Range("D2").Value = "已联系"
如果你没有对象意识,就会把它当成一种固定写法去背。
但你只要把那个点号 . 读成“的”,整句话马上就顺了:
把 D2 这个对象的 Value 属性,改成“已联系”。
这时候代码就不再是死格式了,而是有了意思。
类、对象、属性、方法,这四个词到底怎么理解
这几个词经常一起出现,也是很多人一开始最容易混的地方。
先别急着背定义,我还是用生活里的例子讲。
1. 会议室这个例子,其实很适合讲对象
假设一家公司里有很多会议室。
“会议室”这个概念,本身就是一种类型。在面向对象里,这个类型就叫类。
而具体存在的那些会议室,比如:
-
3 号会议室 -
培训室 -
小洽谈间
这些就是对象。
也就是说:
-
类,是一个模板,是一个类型 -
对象,是这个类型下一个个具体存在的实例
接着往下看。
每个会议室都会有一些信息,比如:
-
名称 -
容纳人数 -
所在楼层 -
是否空闲 -
有没有投影
这些东西,在面向对象里就叫属性。
而会议室还可以做一些事,比如:
-
预订 -
取消预订 -
开灯 -
关设备
这些东西,就叫方法。
你会发现,这样理解特别顺:
-
属性,更像“它是什么样” -
方法,更像“它能做什么”
放到 Excel 里也是一样。
“工作表”是一个类。“客户跟进表”“订单明细表”“库存统计表”这些具体工作表,就是对象。
它们也会有自己的属性,比如名字、是否隐藏、行数列数。它们也会有自己的方法,比如复制、删除、选中。
你可以用一个很笨但很好用的方法区分属性和方法
初学的时候,有个办法特别实用:
属性通常更像名词,方法通常更像动作。
比如下面这几句:
-
1 -
2 -
3
Range("B2").Value = "待回访"Range("B2").Font.Bold = TrueRange("B2").ClearContents
这里的:
-
Value是属性 -
Font是属性 -
Bold也是属性
因为它们描述的是这个对象的状态。
而 ClearContents 是方法,因为它表示的是一个动作:清空内容。
所以你读代码的时候,可以先别急着背术语,先问自己一句:
这里是在描述它,还是在让它做事?
如果是在描述它,大概率就是属性。如果是在让它做事,大概率就是方法。
再用一个更实际的例子:班级管理系统
会议室这个例子已经挺形象了,但如果想更明显地看出“面向过程”和“面向对象”的区别,我觉得“班级管理系统”会更贴近一点。
因为它天然就适合做对比。
先看面向过程的思路
如果按面向过程的方式去做一个班级管理系统,很多人最自然的想法会是:
先做个输入框,让用户输入学生姓名、学号、成绩这些信息。然后程序按顺序执行:
-
读取输入内容 -
检查格式对不对 -
把数据写进表里 -
计算总分或平均分 -
判断是否及格 -
更新显示结果
这种写法没有问题,而且对小程序来说也挺直接。你会很自然地把它理解成:
我要完成哪些步骤,我就一个一个写过程。
也就是说,你脑子里想的是“流程”。
再看面向对象的思路
如果换成面向对象的方式,你脑子里的重点就会变成:
这个系统里有哪些东西。
比如一个班级管理系统里,至少会有这些对象:
-
学生 -
班级 -
成绩单 -
老师 -
课程
这时候你会开始想:
“学生”这个对象,应该有哪些属性?
比如:
-
姓名 -
学号 -
性别 -
所属班级 -
各科成绩
它又应该有哪些方法?
比如:
-
录入成绩 -
修改信息 -
计算总分 -
判断是否及格
再比如“班级”这个对象,它可能会有:
属性:
-
班级名称 -
班主任 -
学生人数
方法:
-
添加学生 -
删除学生 -
统计平均分 -
输出排名
你会发现,这时候你的思考方式已经变了。
面向过程更像是在想:
我要先干什么,再干什么。
面向对象更像是在想:
这个系统里有哪些角色,每个角色该管什么事。
这两种方式都能写程序。但当系统稍微复杂一点,面向对象的思路会更清晰,因为它把数据和功能分给了不同的对象,各管各的,不容易乱成一团。
那 VBA 到底更偏哪一种
VBA 这个东西比较特别。
它不是那种纯粹、彻底的面向对象语言。你平时写的 Sub ... End Sub,本质上还是很典型的过程式写法。
也就是说,前面学的很多内容,其实都是面向过程这条线上的东西。
但问题是,当 VBA 要去控制 Excel 里的各种元素时,它又必须借助对象这套思路。
这也是为什么很多人学 VBA 的时候,会有一种明显的分界感:
前面在学“程序怎么写”,后面开始学“Excel 里的东西怎么控制”。
而连接这两块的桥,就是对象。
所以更准确一点说:
VBA 是用过程式的方式写代码,再用对象的方式去控制 Excel。
这个理解一旦有了,很多东西就会顺很多。
VBA 里的对象关系,往往是一层套一层的
VBA 里还有一个很重要的点,就是对象经常不是孤零零存在的,它们之间有层级关系。
你可以先粗略理解成这样:
-
1 -
2 -
3 -
4
Excel程序└─ 工作簿└─ 工作表└─ 单元格区域
也就是说:
-
Excel 这个程序,是一个更外层的对象 -
它里面有工作簿对象 -
工作簿里面有工作表对象 -
工作表里面又有 Range 对象
所以你写很多代码,本质上就是在一层层往下找。
比如:
-
1
Worksheets("客户跟进").Range("D2")
这句话其实就是:
先找到“客户跟进”这张工作表,再找到这张表里的 D2 这个区域。
这个关系你越往后学,越会觉得重要。因为很多代码一复杂,你最容易乱的,不是语法,而是你根本不知道自己当前在操作哪张表、哪个区域、哪个工作簿。
用一个办公场景,把对象这件事落到代码里
假设你现在有一张客户跟进表。如果某个客户的状态是“待回访”,你希望把这一行高亮出来,方便一眼看到。
表格可以先这样设:
|
|
|
|
|
|
|
|---|---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
代码可以这样写:
-
1 -
2 -
3 -
4 -
5 -
6 -
7 -
8 -
9 -
10 -
11 -
12 -
13 -
14 -
15 -
16 -
17 -
18
Sub MarkPendingCustomers()Dim ws As Worksheet 'ws 代表“客户跟进”这张工作表Dim currentRow As Range 'currentRow 代表当前整行 A:E 这段区域Dim i AsLong'i 用来记录当前处理到第几行Set ws = Worksheets("客户跟进") '先找到目标工作表对象For i = 2To5'从第2行循环到第5行SetcurrentRow=ws.Range(ws.Cells(i,1),ws.Cells(i,5)) '取出当前行 A:E 这一段区域Ifws.Cells(i,4).Value="待回访"Then'如果 D 列状态是“待回访”currentRow.Font.Bold=True'把这一行字体加粗currentRow.Interior.Color=vbYellow '把这一行底色改成黄色EndIfNext iEndSub
这段代码表面上看,当然也有循环,也有判断。但它真正的主线,其实一直在找对象、改对象:
-
ws是工作表对象 -
currentRow是区域对象 -
currentRow.Font又是一个对象 -
currentRow.Font.Bold是字体对象里的属性 -
currentRow.Interior也是一个对象型属性 -
currentRow.Interior.Color是填充颜色相关的属性
也就是说,这段代码之所以能“把待回访那一行标黄”,并不是因为循环本身有多神,而是因为它最终找到了正确的对象,然后去修改对象的属性。
这才是 VBA 真正强的地方。
说到底,对象不是为了把事情讲复杂,而是为了把事情讲清楚
很多人第一次接触对象时,会下意识觉得这是不是进入“高级内容”了。
其实不是。
在 VBA 里,对象反而是在帮你把 Excel 这个世界拆清楚。
不然你会发现,所有东西都混在一起:
单元格、工作表、工作簿、字体、颜色、批注、图表、文件……如果没有对象这套思路,你很难把这些元素之间的关系说明白,也很难稳定地去控制它们。
所以对象不是为了显得高级,而是为了回答两个特别朴素的问题:
这个东西是什么?这个东西能干什么?
把这两个问题分清楚,代码就会清楚很多。
最后再回到开头那个问题:对象值不值得学
我觉得答案其实挺明确的。
如果你现在的需求,只是做点表内计算、汇总统计、分析透视,公式和透视表真的已经很强了,而且很多时候效率也更高。这个没必要硬抬 VBA。
但如果你开始想做这些事:
-
批量改表 -
批量处理工作簿 -
自动生成格式 -
自动复制、保存、打印 -
自动在多个对象之间联动 -
甚至让 Excel 去调用别的软件一起干活
那对象这一步,你迟早都得过。
因为前面的变量、循环、判断,只是在教你“怎么组织语言”;而对象,才是在告诉你“你能指挥谁去干活”。
所以学到这里,你会慢慢发现:
VBA 真正强大的地方,不是它会算,而是它会动。
它能让 Excel 里的很多元素动起来,也能让你从“自己手动点”变成“让程序替你做”。
而对象,就是你进入这个新世界的门。
夜雨聆风