分类 学习笔记 下的文章

在掌握了XLOOKUP的基础用法后,这里有一些高级技巧,涵盖多条件查找、二维交叉查询、通配符匹配、错误处理、动态数组溢出等进阶场景。

一、多条件查找(多条件联合查询)

当需要根据多个条件(如同时满足“部门”和“职位”)来查找一个值时,XLOOKUP可以通过连接符将多个条件合并为一个查找值,实现精准匹配 。
核心原理:将查找值与查找列都通过 & 连接成一个组合键,再进行比较。

示例:根据“产品类别”与“销售额度”查找对应的折扣率 。

=XLOOKUP(B2&C2, DiscountTable!A:A&DiscountTable!B:B, DiscountTable!C:C, 0)

说明:
B2&C2:将“产品类别”和“销售额度”合并为一个查找键。
DiscountTable!A:A&DiscountTable!B:B:将查找范围中的类别列和销售额度列也合并为组合键。
这种写法支持任意数量的条件,只需将更多列用 & 连接即可 。

二、二维交叉查询(双方向查找)

二维交叉查询用于查找行与列交汇处的值,例如根据“产品名称”和“月份”找到对应的销售额。XLOOKUP通过嵌套方式实现这一功能 。

示例:查找某产品在特定月份的销售数据。

=XLOOKUP(H2, B4:B20, XLOOKUP(H3, C3:N3, C4:N20))

工作原理:
内层 XLOOKUP:在月份标题行 C3:N3 中查找 H3(目标月份),返回对应的整列数据(C4:N20 中该月份所在列)。
外层 XLOOKUP:在产品列 B4:B20 中查找 H2(目标产品),然后从内层返回的月份列中提取对应值。
优势:相比传统的 INDEX+MATCH 组合,XLOOKUP嵌套的写法更直观,易于阅读和维护 。

三、通配符匹配(模糊查找)

当需要查找包含特定字符或以特定字符开头/结尾的文本时,XLOOKUP支持通配符匹配,需将 match_mode 参数设置为 2 。
通配符规则:

*:匹配任意数量的字符。
?:匹配单个字符。
~:将通配符转义为普通字符(如查找文本中的 * 本身)。
示例:查找所有以“Lap”开头的产品价格。

=XLOOKUP("Lap*", A2:A50, B2:B50, "未找到", 2)

注意:match_mode 默认值为 0(精确匹配),此时 * 和 ? 会被当作普通字符处理。务必设置 match_mode = 2,否则通配符不会生效,这是最常见的错误之一 。

四、近似匹配与区间查找

XLOOKUP的 match_mode 参数支持近似匹配,可用于处理阶梯定价、税率区间、佣金比例等场景 。

-|-|-
match_mode值 | 匹配行为 | 适用场景
-1|精确匹配,若无匹配则返回下一个较小的值|阶梯折扣、税率区间
1|精确匹配,若无匹配则返回下一个较大的值|成绩评级、达标判定
示例:根据销售数量查找对应的折扣率。

=XLOOKUP(45, A9:A12, B9:B12, "无折扣", -1)

说明:当销售数量为45时,查找表中有0、10、50、100四个档位。-1 模式会返回小于等于45的最大档位(即10)对应的折扣率(5%)。

五、逆向查找与最后一次匹配

  1. 逆向查找(向左查找)
    XLOOKUP支持任意方向的查找,不受VLOOKUP只能向右查找的限制 。

示例:根据“客户ID”(在D列)查找“客户名称”(在A列)。

=XLOOKUP(F2, D2:D300, A2:A300)
  1. 查找最后一次匹配
    search_mode 参数设置为 -1,可以从底部向上搜索,返回最后一个匹配项 。

示例:查找某产品的最新价格更新记录。

=XLOOKUP("P001", B15:B18, C15:C18, , , -1)

适用场景:订单记录、价格变更历史、日志等需要获取最新数据的场景 。

六、错误处理与容错机制

  1. 内置 if_not_found 参数
    XLOOKUP 的第四个参数 if_not_found 可以直接定义查找失败时的返回值,无需再嵌套 IFERROR 或 IFNA 。

    =XLOOKUP(A2, B2:B100, C2:C100, "未找到")
  2. 返回空值而非错误
    若希望查找失败时返回空单元格而非错误提示,可将 if_not_found 设为 "" 。

    =XLOOKUP(A2, products[SKU], products[Price], "")

    优势:内置的 if_not_found 参数比外层包裹 IFERROR 更简洁、运算效率更高,也更符合公式逻辑 。

七、返回多列数据

XLOOKUP 的 return_array 参数可以指定多列范围,从而一次性返回多个字段 。

示例:根据员工ID一次性返回其部门、经理和入职日期。

=XLOOKUP(A2, employees[ID], employees[Department:Start Date])

说明:employees[Department:Start Date] 表示从“部门”列到“入职日期”列的多列范围。当查找匹配时,XLOOKUP会返回对应行的所有列数据,并自动溢出到相邻单元格 。

八、结合其他函数的高级应用

XLOOKUP 可以与其他函数嵌套,构建更强大的数据分析公式 。

  1. 与 SUM 结合:条件求和
    =SUM(XLOOKUP("产品类别", CategoriesRange, SalesRange))
  2. 与 ADDRESS 结合:返回单元格地址
    =ADDRESS(ROW(XLOOKUP(A2, B2:B100, B2:B100)), COLUMN(XLOOKUP(A2, B2:B100, B2:B100)))
  3. 与 CHOOSE 结合:返回非连续列
    =XLOOKUP(A2, B2:B100, CHOOSE({1,2,3}, C2:C100, E2:E100, G2:G100))
    说明:CHOOSE 函数将 C、E、G 三列(非连续)组合成一个虚拟数组,供 XLOOKUP 返回 。

九、常见错误及排查方法

-|-|-
错误类型|错误值|常见原因及解决方法
未找到匹配|#N/A|查找值不存在,或未设置 if_not_found 参数;检查拼写、空格、数据类型一致性
范围不匹配|#VALUE!|lookup_array 与 return_array 的行数或列数不一致,导致无法对齐
版本不支持|#NAME?|当前Excel版本低于2019/Office 365,不支持XLOOKUP函数
通配符无效|#N/A|未设置 match_mode = 2,* 被当作普通字符处理
精确匹配误判|错误结果|默认 match_mode = 0 为精确匹配;若需近似匹配,须显式设置 match_mode 为 -1 或 1

十、总结:XLOOKUP进阶技巧速查表

-|-|-
技巧|核心参数|一句话记忆
多条件查找|= 连接符 + &|用 & 合并条件,实现多条件联合查询
二维交叉查询|嵌套 XLOOKUP|内层查列,外层查行,返回交叉点值
通配符匹配|match_mode = 2|匹配模式设为2,开启 * 和 ? 模糊查找
近似匹配|match_mode = -1 或 1|处理阶梯区间,返回小于或大于的匹配值
逆向查找|直接指定返回列|向左向右皆可,摆脱VLOOKUP的方向限制
最后匹配|search_mode = -1|从底部向上搜索,返回最新记录
内置容错|if_not_found|第四参数自定义错误提示,无需 IFERROR
多列返回|扩展返回数组|返回多列,自动溢出到相邻单元格

一、为什么你需要XLOOKUP?

在Excel中,查找数据是日常工作中最频繁的操作之一。过去,我们依赖VLOOKUP或HLOOKUP,但它们有诸多限制:

  • VLOOKUP:查找列必须在数据表的第一列,且只能向右查找。
  • HLOOKUP:查找行必须在数据表的第一行,且只能向下查找。
  • 两者都不支持反向查找,且处理错误值(如#N/A)时不够灵活。

XLOOKUP(在Excel 2021及Office 365中引入)彻底解决了这些问题,被誉为“查找函数的终极形态”。

二、XLOOKUP的基本语法

=XLOOKUP(查找值, 查找数组, 返回数组, [未找到时的返回值], [匹配模式], [搜索模式])

-|-|-
参数|说明|是否必填
查找值|你要查找的内容|是
查找数组|在哪一列/行中查找|是
返回数组|返回哪一列/行的结果|是
未找到时的返回值|可选,匹配失败时返回自定义文本|否
匹配模式|0=精确匹配(默认),-1=小于,1=大于,2=通配符|否
搜索模式|1=从第一个开始搜索(默认),-1=从最后一个搜索,2=二分查找|否

三、XLOOKUP vs VLOOKUP:核心优势对比

-|-|-
功能|VLOOKUP|XLOOKUP
查找方向|只能向右|任意方向(左、右、上、下)
查找列位置|必须位于第一列|任意位置
返回列指定|整数(第几列)|直接指定返回数组
错误处理|需嵌套IFERROR|内置“未找到”参数
多条件查找|需辅助列|可直接用数组公式
通配符支持|支持|支持(匹配模式=2)

四、XLOOKUP的常见应用场景

场景1:经典单条件查找(替代VLOOKUP)
问题:根据员工ID查找姓名。

VLOOKUP写法:

=VLOOKUP(A2, A:D, 2, 0)

XLOOKUP写法:

=XLOOKUP(A2, A:A, B:B)

优势:无需计算列序号,直接指定返回列。

场景2:反向查找(VLOOKUP做不到)
问题:根据员工姓名查找员工ID(姓名在ID右侧)。

VLOOKUP:需要借助INDEX+MATCH组合。

XLOOKUP写法:

=XLOOKUP(B2, B:B, A:A)

优势:直接向左查找,公式更简洁。

场景3:多条件查找
问题:根据“部门”和“职位”两个条件查找“薪资”。

=XLOOKUP(1, (A:A=E2)*(B:B=F2), C:C)

说明:(A:A=E2)*(B:B=F2) 会生成一个由0和1组成的数组,只有两个条件同时满足时为1,XLOOKUP精确匹配1,返回对应的薪资。

场景4:处理查找失败的情况
问题:查找某个不存在的ID时,返回自定义提示而非错误值。

=XLOOKUP(A2, A:A, B:B, "未找到此人")

优势:无需嵌套IFERROR,公式更清爽。

场景5:从右向左查找最后一个匹配项
问题:查找某员工最后一次加班记录。

=XLOOKUP(A2, A:A, B:B, "无记录", 0, -1)

说明:第六个参数 -1 表示从数组的最后一个值开始搜索,返回最后一个匹配项,常用于“最后一次”场景。

五、XLOOKUP的局限与注意事项

-|-
局限|说明
两个数组|公式中两个数组需要保持相同大小,例如:A:A对应B:B即A列对B列;A1:A10,B11:B20,不需要都是1开始,但必需保持数组中元素个数相同。
wps office|ET 11.2及以上版本
ms office|Excel 2021及以上版本、Office 365支持
性能问题|在大数据量(>10万行)中,速度可能慢于INDEX+MATCH
精确匹配默认|不指定匹配模式时,默认为0(精确匹配),注意区分
数组公式依赖|多条件查找依赖动态数组,旧版本可能不支持

六、总结:什么时候用XLOOKUP?

-|-
场景|推荐函数
需要反向查找(向左查找)|XLOOKUP
需要多条件查找|XLOOKUP 或 INDEX+MATCH
需要处理#N/A错误|XLOOKUP
需要从右到左查找最后一项|XLOOKUP
数据量极大(>10万行)|INDEX+MATCH(性能更优)
老版本Excel(2019及以前)|INDEX+MATCH

七、一句话记忆

XLOOKUP = VLOOKUP的升级版 + HLOOKUP + INDEX+MATCH的简化版,且支持反向查找、错误处理和灵活搜索方向。

近期看大宝的作业其中有讲如何快速判断一个大数能否被整除,这里整理一下备查。

定理

a*b除以c的余数等于a除以c的余数*b除以c的余数
a*b mod c = (a mod c) * (b mod c) mod 表示取余。

原理

设:

a = k1*c + x
b = k2*c + y

则:

a*b 
= (k1*c+x)*(k2*c+y)
= k1*k2*c*c + (k1*y+k2*x)*c + x*y
= [k1*k2*c + (k1*y+k2*x)]*c + x*y

明显 [k1*k2*c + (k1*y+k2*x)]*c包含因数c,取余时可直接舍去。
故:

a*b mod c = x*y mod c

2

这个简单直接看末位能否被2整除。

3

所有数位上的数字相加能被3整除。
原理:abc = a*(3*33+1) + b*(3*3+1) +c =3*33*a + 3*3*b + a + b + c
明显3*33*a + 3*3*b能被3整除,故只用考虑 a + b + c能被3整除。

4

最后两位能被4整除。还有简便计算:ab(一个两位数),a*2 + b能被4整除。
原理:abc = a*(4*25) + b*(4*2+2) +c =4*25*a + 4*2*b + 2*b + c
明显4*25*a + 4*2*b能被4整除,故只用考虑 2*b + c能被3整除。

5

末位为05

6

同时被23整除。

7

以三位分节,然后奇减偶,结果能被7整除。还有简便计算abc(一个三位数),a*2 + b*3 + c能被7整除。

原理

1、 10 、 100、1000、10000、100000……除7的余数分别为1、3、2、6、4、5、1、3、2、6、4、5……
1 3 2 6 4 5的循环
同时6 4 5又可以写为-1 -3 -2因此可以改写为1 3 2 -1 -3 -2 1 3 2 -1 -3 -2……
即从个位起以三位分节。余数按1 3 2循环,奇数节为正,偶数节为负。
例:123456789123456
先分节:
大数|123 | 456 | 789 | 123 | 456
:-:|:-:|:-:|:-:|:-:|:-:
分节|5 | 4 | 3 | 2 | 1
所有奇数节为 1 3 5 对应 456 789 123
所有偶数节为 2 4 对应 123 456
奇减偶:(456 + 789 + 123) - (123 + 456) = 789
再运用简便计算:7*2 + 8*3 + 9 = 47 => 47/7=6 ··· 5123456789123456除以75
注:如各节加和为负则对应余数加7转换为正数

8

末三位能被8整除。简便计算abc(一个三位数),a*4 + b*2 + c 能被8整除。

原理

dabc = d*8*125 + a*(8*12+4) + b*(8+2) +c = d*8*125 + a*8*12 + b*8 + a*4 + b*2 +c
即余数等同于 a*4+b*2+c

进阶推广

任意大数除以2的n次方时,余数只需要考虑末n位
记最后n位为X(1)X(2)……X(n)
则结果为X(1)*2^(n-1) + X(2)*2^(n-2) + …… + X(n)*2^(n-n)

9

所有数位上的数字相加能被9整除。

原理

abc = a*(9*11+1) + b*(9*1+1)+c = a*9*11 + b*9*1 + a + b + c
即余数等同于 a + b + c

之前看到有个开放的项目MKPlayer,觉得蛮有意思就搞了个。
由于经常切换设备,有了同步歌单的需求。
然后发现他的设计思路是直接调取网易的歌单,或者是手工修改歌单,每次添加或删除歌曲比较麻烦。
于是就给他修改了一下。

  1. 添加了“喜欢的歌”歌单
  2. 添加爱心按钮,点击喜欢,就会前歌曲添加到喜欢歌单中,再次点击就移除
  3. 添加歌单同步按钮,可以同步到云端或从云端同步到本地
  4. 添加用户id,以识别不同的用户
  5. 修改API接口为网易云开放接口
  6. 版权因素,音乐播放逻辑与网易保持同步:版权音乐仅提供试听。

来试试吧:music.ab.cd

前段些天发现每过一段时间电脑的时间总会出现一些误差,之前总是使用自带的授时服务器(ntp)进行更新,但是经常遇到更新失败的问题,后来听liangke说他都是使用国家授时中心的ntp服务,由于是国内网络连接比较好,很快就可以同步完成。就决定也使用国内的ntp服务。

那天,想到自己手上一直荒废的域名 t.hm ,似乎还比较合适,就解析了过去。你还别说,效果还不错呢。

后来又做了个显示时间的页面 https://www.t.hm
其中使用了JQuery的AJAX和定时任务两非常实用的功能,就记在这里,说不定还用的上的。

这里主要用了两个插件:dayjs 和 jquery。

哦,还有一个很奇葩的BUG,Safari浏览器不支持解析yyyy-mm-dd格式的时间,所以需要修改时间格式(我这里用的是/代替的-)。

<script>
    // 初始化时间变量
    var localTime;

    getServerTime();
    setInterval(getServerTime, 10 * 60 * 1000); 

    // 每秒更新本地时间显示
    setInterval(updateLocalTime, 1000);

    // 函数:获取服务器时间
    function getServerTime() {
        $.ajax({
            url: 'time.php',
            type: 'GET',
            success: function(response) {
                setLocalTime();
            },
            error: function() {
                // 处理请求失败的情况
            }
        });
    }

    // 设置服务器时间为当前时间
    function setLocalTime() {
        if (serverTime) {
            localTime = new dayjs(serverTime);
        }else{
            console.log('serverTime:'+serverTime);
        }
    }

    // 函数:更新本地时间显示
    function updateLocalTime() {
        if (localTime) {
            tmp = dayjs(localTime).format('YYYY-MM-DD HH:mm:ss ZZ');
            $('#time').text(tmp);
            $("#title").text(tmp+' - t.hm 授时服务');
            localTime = dayjs(localTime).add(1,'s');
        }
        //console.error('localTime:'+localTime);
    }
</script>