公式越写越长、同事还看不懂? 教你给 Excel「造」一个自己的函数丨上集
- 2026-11-07 21:43:11
VBA 进阶系列自定义函数专题
公式越写越长、同事还看不懂?教你给 Excel「造」一个自己的函数
本文你能带走什么
① 彻底搞懂自定义函数是什么、为什么用;② 记住一套能默写出来的语法骨架;③ 6 个从简到难的完整案例,每行代码都有解析;④ 一份避坑清单 + 报错速查表;⑤ 一个可以立刻运行的练习文件。
从这一讲开始,我们学习新的内容-自定义函数。
在此之前,我们一直在「用」 Excel:用 SUM 求和,用 VLOOKUP 查表,用 TEXTJOIN 合并。这些函数都是微软写好了、封装好了、打包进 Excel 里给你的,你只能照着它规定的用法去用。从今天起,角色要换一换了——你不再只是使用者,而是制造者。
先别急着写代码,回想一下这几个让你抓狂的瞬间:
这些问题的共性是什么?你要的计算方式,Excel 恰好没提供。而自定义函数,就是解决这类问题的那把钥匙。
先建立一个清晰的概念,后面所有的代码都围着它转。
官方定义
自定义函数(User Defined Function,缩写 UDF),是你用 VBA 语言自己编写的一段小程序。写好之后,它可以像 SUM、VLOOKUP 一样,直接在单元格公式里调用,也能出现在「插入函数」的对话框里,可以设置参数提示,甚至可以带上中文说明。
单元格里写=SayHello(A2) | Excel 把参数交给 VBA | 你的代码执行运算 | 结果回到单元格里 |
内置函数 = 下馆子 菜单上的菜是厨师定好的,你只能点现成的。好处是省事、稳定;坏处是你想吃家乡口味?对不起,没有。 | 自定义函数 = 自己做菜 食材、口味、火候全由你定,做一次可以吃很久。好处是完全贴合你的业务;代价是你得先学会掌勺。 |
| 你自己 | ||
| 无限 | ||
| 也不能 | ||
新手最容易混淆的第一件事:Function 和 Sub 不是一回事
VBA 里有两种「程序块」:
Sub 过程(宏)负责干活——弹窗、改格式、删 sheet、批量操作;
Function 函数负责算数——接受输入、返回一个结果。记住一句话:Sub 出现在宏列表里,Function 出现在单元格公式里。
| 在单元格公式里调用 | ||
| 没有 | 有且必须有 | |
| 不能 | ||
把理由讲透,你才知道什么时候该掏出这张牌。
补上 Excel 的空白 凡是内置函数做不到的事(按颜色求和、中文大写、正则提取),都能自己实现。 | 把长公式变成一个名字 一条 200 字符的嵌套公式,压缩成 =PriceWithTax(A2),谁都看得懂。 |
一次编写,处处复用 逻辑只写一处,全表里几百个单元格共用。改规则只改一行代码。 | 团队口径永远一致 函数发下去,所有人算出来的结果一模一样,不会各算各的。 |
封装你的业务 know-how 税率规则、编码规则、提成算法……这些是公司的资产,写进函数就固化下来了。 | 它是通往高阶 VBA 的门 学会了 Function,参数、循环、判断、对象模型这些就都串起来了。 |
=ExtractNumber(A2) | ||
=RMBUpper(A2) | ||
=SumByColor(A2:A20,D2) | ||
=PriceWithTax(A2,0.06) | ||
=IDBirthday(A2) |
讲点实在的:什么时候不该用自定义函数
① 内置函数能一句话搞定的,就别写 UDF——慢而且没必要;② 几十万行的大数据量,VBA 逐行循环会明显卡顿,优先考虑 Power Query 或数据透视表;③ 要发给不启用宏的人看,对方打开会失效;④ 需要在公司层面长期分发,管理成本比想象中高(加载宏、信任中心、版本兼容)。会用是本事,知道什么时候不用,是更深的本事。
这段结构建议背下来,所有自定义函数都是它的变体。
"┌─ 作用域 ─┐ ┌─函数名─┐ ┌参数列表────────┐ ┌返回值类型┐Public Function MyFunc ( ByVal A As Double ) As Double声明区 Dim X As Double处理区 X = A * 2返回区 MyFunc = X '← 给函数名赋值 = 返回End Function
| Public / Private | |
| Function | |
| MyFunc | 函数名,就是你在单元格里敲的那个名字。建议用英文+驼峰,见名知义;中文名也能用,但兼容性差一些。 |
| ( ByVal A As Double ) | 参数列表,可以没有,也可以多个,多个用逗号隔开。ByVal 传值,ByRef 传址(见第 5 节)。 |
| As Double | 返回值类型。强烈建议显式声明——不写就是 Variant,既慢又容易出隐性错误。 |
| 函数名 = 值 | 返回语句。VBA 没有 Return,把值赋给「函数名本身」就是返回。这是全篇最核心的一行。 |
| End Function |
Function MyFunc(参数) As 类型 | |||
| |||
End Function |
三条铁律(默写级)
铁律一:函数名必须赋值给它自己,才有返回值。铁律二:Function 和 End Function 必须成对,中间的所有变量、逻辑都只在这对之间有效。铁律三:参数类型和返回值类型都写清楚,别偷懒省掉 As。
别光看,跟着做一遍,这一节做完你就已经入门了。
1 | 打开 VBE 编辑器 在 Excel 里按 Alt + F11(Mac 是 Option + F11),这就是写 VBA 的地方。 |
2 | 插入一个标准模块 菜单栏 插入 → 模块。左侧会多出一个「Module1」,代码就写在这里。注意:一定要插在标准模块里,而不是 sheet 代码页。 |
3 | 粘贴代码 把下面案例 1 的代码整段粘进去。 |
4 | 保存为启用宏的格式 Ctrl + S,保存类型选 Excel 启用宏的工作簿 (*.xlsm)。存成 .xlsx 的话,代码会被 Excel 直接丢掉——这是新手第二大坑。 |
5 | 回到单元格调用 在任意单元格输入 =SayHello("王大力"),回车,见证奇迹。 |
场景:麻雀虽小五脏俱全,它包含了自定义函数的全部语法要素。
'【案例】最小可用:向指定的人问好Public Function SayHello(ByVal Name As String) As StringDim Msg As StringMsg = "你好," & Name & "!这是我的第一个自定义函数。"SayHello = MsgEnd Function
Public Function SayHello (ByVal Name As String) As String | |
Dim Msg As String | |
Msg = " 你好,"& Name &" !这是我的第一个自定义函数。" | |
SayHello = Msg | 全文最关键的一行 |
End Function |
在单元格里怎么用:
=SayHello("王大力") → 你好,王大力!这是我的第一个自定义函数。 =SayHello(A2) → A2 换成谁,就向谁问好
如果你的单元格显示 #NAME?
99% 是这三个原因:① 代码没放在标准模块里(放在了 sheet 页或 ThisWorkbook);② 文件存成了 .xlsx 而不是 .xlsm;③ 宏被禁用了,顶部出现黄色安全警告条要点「启用内容」。详细排查见第 12 节速查表。
今天就先讲到这里吧!
写在最后
自定义函数是 VBA 学习路上的一道分水岭:在它之前,你只是在用 Excel;跨过去之后,你在扩展 Excel。
回顾一下今天我们走过的路——从「什么是自定义函数」,到「为什么必须自己写」,到那幅能默写的语法骨架,再到 1 个简单的实战案例。你会发现,真正的门槛从来不是语法,而是把重复的、丑陋的、容易出错的手工活,翻译成一个干净的函数名的那种意识。
下一讲预告:案例由简单到复杂逐步过渡,下一讲我们只讲案例,让你对自定义函数的理解更透彻。
这一讲暂不放配套练习文件,等下一讲完成后我会把这两讲的练习文件放到一起,期待大家继续跟进。如果这篇文章对你有帮助,点个「在看」,让更多被长公式折磨的同事看到它。