上一期写了 SUMIFS 和 LET,今天想想,做数据时还有个查找,用的真的是太经常了,所以回想了一下自己的经历,结合自己的实践,写了本篇。
想起以前,有次做年度汇算,我用 VLOOKUP 匹配了 8000 行客户信息。结果有 200 多行返回 #N/A。我检查了很多遍,lookup_value 没问题,table_array 也没问题,最后发现是其他人在录入时,客户名称后面多了个空格。
更绝的是,有 30 行匹配错了人——如 "张三" 匹配成了 "张三丰"。因为我没把第四个参数写成 FALSE,VLOOKUP 默认搞了个近似匹配。

一、VLOOKUP 不是不会用,是它太爱坑人
语法就四个参数,看起来简单,但每个都能埋雷。
=VLOOKUP(找什么, 去哪找, 返回第几列, 精确还是模糊)说实话,我第一次学的时候觉得,这不就是 "查字典" 吗?查多了才发现,这字典会咬人。

坑 1:第四个参数不写,默认是"近似匹配"
这是最阴险的。
-- 很多人这么写 --
=VLOOKUP(A2, 客户表!A:D, 2)
-- 实际等价于 --
=VLOOKUP(A2, 客户表!A:D, 2, TRUE)TRUE 是什么意思?近似匹配。 它不是找完全一样的,而是找 "最接近的"。
你的 lookup_value 是 "张三",表里有 "张三丰",VLOOKUP 可能返回 "张三丰" 的信息,因为排序上它 "接近"。在姓名、编号、ID 查找里,这就是灾难。
正确写法:
=VLOOKUP(A2, 客户表!A:D, 2, FALSE)
-- 或者 --
=VLOOKUP(A2, 客户表!A:D, 2, 0) -- 0 就是 FALSE,两个字符,保平安我的铁律:除非你在查税率、提成比例这种分段区间,否则永远写 FALSE。 不记得就写 0,别偷懒。
坑 2:返回列号写死了,插入一列全崩
=VLOOKUP(A2, 客户表!A:D, 3, 0)这个 3 是返回查找区域的第 3 列。今天第 3 列是 "手机号",明天有人在前面插了一列 "性别",第 3 列就变成了 "地址"。所有公式结果全错,你还不知道。
我经历过一次。同事插了一列,整个表的数据错位,我汇报时拿错了手机号,当场社死。
解法:用 MATCH 动态算列号。
=VLOOKUP(
A2,
客户表!A:D,
MATCH("手机号", 客户表!$1:$1, 0), -- 自动找"手机号"在第几列
0
)这样即使插列,MATCH 会重新定位,公式不会崩。
坑 3:格式不一致,肉眼根本看不出来
这是 #N/A 的头号元凶。
你在 A2 输入的是文本 "10086",客户表第一列是数字 10086。看着一样,但 Excel 认为文本 ≠ 数字,直接返回 #N/A。
反过来也一样。
那怎么查? 选中两边单元格,用 TYPE() 函数——返回 2 是文本,返回 1 是数字。
解法:统一格式。
-- 把 lookup_value 转成数字 --
=VLOOKUP(A2*1, 客户表!A:D, 2, 0)
-- 或者转成文本 --
=VLOOKUP(A2&"", 客户表!A:D, 2, 0)更稳妥的做法: 在数据源里统一格式,别在公式里打补丁。用 "分列" 功能把文本转数字,或者设置单元格格式。
坑 4:空格和不可见字符
最恶心的一个。
"张三" 和 "张三"(后面带空格)在 Excel 眼里是两个东西。VLOOKUP 严格匹配时,有空格就匹配不上。
还有从系统导出来的数据,经常带换行符、制表符,肉眼根本看不见。
解法:用 TRIM 和 CLEAN 清洗。
=VLOOKUP(TRIM(CLEAN(A2)), 客户表!A:D, 2, 0)TRIM 去掉首尾空格,CLEAN 去掉不可见字符。如果数据源不干净,这个公式就是救命稻草。
坑 5:没锁引用,下拉公式范围跑了
=VLOOKUP(A2, 客户表!A2:D1000, 2, 0)你把这个公式往下拉 100 行,table_array 变成了 A3:D1001、A4:D1002……越查范围越小,最后几行根本查不到。
解法:绝对引用。
=VLOOKUP(A2, 客户表!$A$2:$D$1000, 2, 0)按 F4 把 A2:D1000 锁死。
我的经验:table_array 永远锁死。 lookup_value 一般只锁列($A2),这样下拉时行号变,列不变。
顺便说一句性能
-- 作死写法 --
=VLOOKUP(A2, 客户表!A:D, 2, 0)A:D 是整列,Excel 要从第 1 行扫到第 1048576 行。数据量大时,卡死你。
-- 正确写法 --
=VLOOKUP(A2, 客户表!$A$2:$D$5000, 2, 0)只扫实际数据范围。留 20% 余量,比如现在 4000 行,写到 5000。
二、XLOOKUP:终于有个正常人设计的函数了
VLOOKUP 有三大先天缺陷:
只能往右查——返回列必须在查找列右边
默认近似匹配——第四个参数不写就出错
插入列就崩——返回列号是硬编码的
XLOOKUP 把这三个问题全解决了。
语法:五个参数,但前三个就够了
=XLOOKUP(找什么, 查找范围, 返回范围, [找不到时显示啥], [匹配模式])对比 VLOOKUP:
注意:XLOOKUP 的查找范围和返回范围是分开的,不用框一个连续区域。 这意味着你可以左边找,右边返回,或者反过来。
反向查找:终于不用倒腾列顺序了
假设客户表是这样的:
你要根据手机号查客户名称。
VLOOKUP 做不到(手机号在右边,客户名称在左边),你只能把手机号列复制到最左边,或者用 INDEX+MATCH。
XLOOKUP 直接查:
=XLOOKUP("138001", 手机号列, 客户名称列, "未找到")查找范围和返回范围完全独立,这是 XLOOKUP 最大的爽点。
容错处理:找不到时不再 #N/A
VLOOKUP 找不到就甩你一脸 #N/A,然后你的报表全是红字,老板问你 "这什么意思"。
XLOOKUP 第四个参数可以直接写 "查不到":
=XLOOKUP(A2, 客户表!A:A, 客户表!B:B, "查无此人")更高级:返回多个值。
=XLOOKUP(A2, 客户表!A:A, 客户表!B:D, "未找到")如果 A2 匹配到第 5 行,它会返回 B5:D5 的三个值。在 Excel 365 里会自动溢出到相邻单元格。
找最后一个匹配项
VLOOKUP 永远返回第一个匹配项。如果表里有重复,你想找最后一次的记录,没戏。
XLOOKUP 第六个参数可以反向搜:
=XLOOKUP(A2, 日期列, 金额列, , , -1)第 4 个参数:找不到时显示什么(省略)
第 5 个参数:匹配模式(0= 精确,省略)
第 6 个参数:搜索方向(1= 从上到下,-1= 从下到上)
从下到上搜,就是找最后一个匹配。 查最新价格、最新状态时非常有用。
多条件查找:XLOOKUP 也能干
XLOOKUP 本身不支持多条件,但可以用 & 拼接:
=XLOOKUP(
A2&B2, -- 比如"张三华东"
姓名列&地区列,
销售额列
)注意:这种写法是数组运算,数据量大时会慢。 更稳的做法还是用辅助列,把姓名和地区拼成一列,再查。
三、兼容性:公司电脑打不开 XLOOKUP 怎么办?
XLOOKUP 是 Excel 2021 / Microsoft 365 和 WPS 新版才有的。 如果你要发文件给用 Office 2016 的同事,打开直接报 #NAME?。
方案一:IFERROR 降级(临时)
=IFERROR(
XLOOKUP(A2, 客户表!A:A, 客户表!B:B, "未找到"),
-- 降级为 VLOOKUP --
IFERROR(
VLOOKUP(A2, 客户表!$A:$B, 2, 0),
"未找到"
)
)能跑 XLOOKUP 就用,跑不了自动降级 VLOOKUP。
方案二:INDEX+MATCH(兼容所有版本)
如果你需要反向查找,又不能用 XLOOKUP,这是万能替代:
=INDEX(返回列, MATCH(查找值, 查找列, 0))MATCH 找到查找值在第几行
INDEX 返回对应行的返回列值
比 VLOOKUP 灵活,比 XLOOKUP 兼容,就是写起来长。
四、实战:一个客户信息匹配系统
假设你有两张表:
表 1:订单表
表 2:客户表
需求:在订单表后面自动带出客户名称、地区、手机号。
VLOOKUP 写法(兼容旧版)
-- 客户名称 --
=IFERROR(VLOOKUP($B2, 客户表!$A$2:$D$1000, 2, 0), "未找到")
-- 地区 --
=IFERROR(VLOOKUP($B2, 客户表!$A$2:$D$1000, 3, 0), "未找到")
-- 手机号 --
=IFERROR(VLOOKUP($B2, 客户表!$A$2:$D$1000, 4, 0), "未找到")问题:VLOOKUP 算了三遍,客户表扫了三遍。
XLOOKUP 写法(推荐)
-- 客户名称 --
=IFERROR(XLOOKUP($B2, 客户表!$A$2:$A$1000, 客户表!$B$2:$B$1000, "未找到"), "")
-- 地区 --
=IFERROR(XLOOKUP($B2, 客户表!$A$2:$A$1000, 客户表!$C$2:$C$1000, "未找到"), "")
-- 手机号 --
=IFERROR(XLOOKUP($B2, 客户表!$A$2:$A$1000, 客户表!$D$2:$D$1000, "未找到"), "")更高级的:用 LET 减少重复查找
=LET(
客户编号, $B2,
客户表范围, 客户表!$A$2:$A$1000,
客户名称, XLOOKUP(客户编号, 客户表范围, 客户表!$B$2:$B$1000, "未找到"),
地区, XLOOKUP(客户编号, 客户表范围, 客户表!$C$2:$C$1000, "未找到"),
手机号, XLOOKUP(客户编号, 客户表范围, 客户表!$D$2:$D$1000, "未找到"),
"客户:" & 客户名称 & CHAR(10) &
"地区:" & 地区 & CHAR(10) &
"电话:" & 手机号
)或者:XLOOKUP 直接返回多列
=XLOOKUP($B2, 客户表!$A$2:$A$1000, 客户表!$B$2:$D$1000, "未找到")在 Excel 365 里,这个公式会自动向右溢出三列,分别返回客户名称、地区、手机号。一个公式顶三个。
五、速查表:建议贴在显示器边上
写在最后
Excel 里有个规律:越老的函数,坑越多;越新的函数,越像人话。
VLOOKUP 从 1985 年活到现在,设计上的缺陷——默认近似匹配、只能右向查、列号硬编码——是历史包袱,不是用户智商问题。 你出错不是因为你笨,是因为这函数设计得反人类。
XLOOKUP 终于把这些包袱扔了,但兼容性又是新的大山。你学会了,发给同事打不开,等于白学。
我的建议:
自己用、团队都用新版 → 直接 XLOOKUP,别犹豫
要发给别人、不知道对方版本 → INDEX+MATCH,最稳
数据量小、求快 → VLOOKUP 写清楚 FALSE 和绝对引用,也能活
数据量大、逻辑复杂 → Power Query,别在单元格里雕花
下次再遇到 #N/A,别急着骂公式。先看看是不是空格、格式、近似匹配这三个老流氓在作怪。
你被 VLOOKUP 坑得最惨的一次是什么?我的是把 "FALSE" 写成了 "FLASE",查了半天发现拼写错误,当场想嘎 ~
VLOOKUP 的坑,我替你们踩完了
本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。
赞赏支持
如果觉得文章对你有帮助,可以请作者喝杯咖啡 ☕
评论交流
欢迎留下你的想法