话说很长时间以来
工作表函数最让人诟病的问题之一,是它缺乏编程语言中最基本的变量表达机制,导致用户无法定义和复用公式中间的计算结果,复杂的计算逻辑只能通过函数的层层嵌套来实现。这不仅使公式变得异常冗长臃肿,还极大地降低了公式的计算性能。最终,微软设计了一种全新的工作表函数编写结构,也就是LET函数。=LET(变量名1,变量内容1,变量名2,变量内容2……,结果表达式)
上述LET函数的意思是先定义了一个变量,其名为a,其值为1。又定义了一个变量b,其值为2。最后运行表达式a+b,也就返回变量a和变量b的合计值:3。LET函数是Excel 从“电子表格计算器”向“轻量级函数式编程环境”迈出的关键一步。它彻底改变了函数的编写方式,有效避免了嵌套函数中同一函数重复出现、重复运算的问题。这不仅显著提升了公式的运算效率,还使复杂的逻辑结构层次更清晰,从而大幅增强了公式的可读性、可维护性以及调试的便捷性。举两个例子,证明上面这段官方套话的正确性
。先举一个简化公式编写、避免相同函数重复运算的小栗子。以上图所示数据为例,需要根据A:B的成绩明细,查询D列人名的成绩;如果成绩大于等于60,则返回实际成绩,否则返回字符串"不及格"。=IF(VLOOKUP(D2,A:B,2,0)>=60, VLOOKUP(D2,A:B,2,0), "不及格")
使用VLOOKUP(D2,A:B,2,0)查询D2人名的成绩,然后用IF函数判断查询结果是否符合要求。这不仅冗余,还降低了计算效率,尤其在数据量大或公式被大量复制时,性能影响更明显。而如果使用LET函数,我们可以将查找结果赋值给一个有意义的变量名,例如成绩,参考公式如下。=LET( 成绩,VLOOKUP(D2,A:B,2,0), IF(成绩>=60,成绩,"不及格"))
第3行代码判断变量成绩是否大于60,并根据判断结果返回对应值。只书写了一次,也只运行了一次。运行完成后,系统将运算结果赋值给变量成绩,在之后使用中,系统直接引用该变量的值,避免了重复运算。可能需要额外说明的是,在LET未出现之前,我们通常使用TEXT函数来合并判断逻辑,规避重复运算的问题。=TEXT(VLOOKUP(D2,A:B,2,0),"[>60]0;;不及格")
但TEXT函数返回的结果是文本值,例如应该返回的数字86,实际是文本86,这对结果数字的聚合处理,比如求和、求平均值、最大值等造成了很大麻烦,毕竟聚合函数会忽略文本数值。同时,这些文本数字也无法直接用于图表、条件格式或其他依赖数值类型的分析场景。再举一个例子,说明LET函数如何使复杂嵌套函数的表达层次更清晰
。如下图所示,有多张工作表,名字分别为财务部、销售部、IT部等,每张工作表的A列均为人名,B列为成绩。简单而言,这是一个典型的多工作表数据查询案例。我们并不知道A列的人名具体出现在哪张工作表中,这需要函数嵌套来实现。=IFERROR(VLOOKUP(A2,INDIRECT(LOOKUP(1,0/COUNTIF(INDIRECT({"财务部","销售部","IT部"}&"!a:a"),A2),{"财务部","销售部","IT部"}&"!a:b")),2,0),"查无")
该公式嵌套了6个函数,对于普通函数水平的朋友来说,无论是阅读理解,还是编写调试,都不容易。嵌套函数,它的计算顺序是由内而外的,这并不符合人类正常的思维方式,我们习惯的思维方向是从上到下,又或者说从左到右。换用LET函数来优化表达,我们可以将上述公式的复杂逻辑分解为一系列有明确意义的步骤,每个步骤都有一个对应的变量名称。=LET( _工作表,{"财务部","销售部","IT部"}, _人名出现次数,COUNTIF(INDIRECT(_工作表&"!a:a"),A2), _可用工作表,LOOKUP(1,0/_人名出现次数,_工作表), _查询区域,INDIRECT(_可用工作表&"!a:b"), _查询,VLOOKUP(A2,_查询区域,2,0), _结果容错,IFERROR(_查询,"查无"), _结果容错)
第2行代码定义了一个变量_工作表,包含了所有需要查询的工作表名称的常量数组{"财务部","销售部","IT部"}。第3行代码定义了变量_人名出现次数。使用COUNTIF函数计算指定人名,在每个工作表的A列中计算其出现的次数。第4行代码定义了变量_可用工作表,使用LOOKUP函数,查询A2人名首次出现的工作表名称。第5行代码定义了变量_查询区域,使用INDIRECT函数构建目标工作表查询区域的引用。第6行代码定义了变量_查询,使用VLOOKUP函数查询A2人名的成绩。第7行代码定义了变量_结果容错,使用IFERROR函数对VLOOKUP查无结果的情况进行容错。摊手,你看,通过LET函数,将原本嵌套很深、难以理解的公式拆解成一组逻辑清晰、按顺序执行的步骤,每个步骤都被赋予了一个有意义的名字,运行目的都很明确,而且它的计算顺序是从上而下的,逻辑层次也因此而清晰。有朋友可能会好奇,为什么以上公式变量名称前面大都增加了一个下划线_,(如 _工作表、_查询)。摊手,这并不是必须的,不是Excel的强制要求,但是它是一个良好的命名习惯。它的好处有两个,一个是快速识别变量,在复杂的公式中,一眼就能区分哪些是自定义变量,哪些是函数或单元格引用,提升阅读效率。另外一个是触发智能提示。在 LET 函数内部输入 _ 时,Excel 会自动弹出当前已定义的变量下拉列表(如下图示意),方便快速选择,减少拼写错误,显著提高编写效率。。除此之外,变量具有“前项可见性”,LET函数的后续参数表达式,可以调用前面已定义的任意变量。比如,在以上公式中,我们定义了6个变量。在第8行代码,我们可以调用前面的任意变量——这极大提高了我们函数调试的效率。换句话来说,如果公式最终返回的结果和我们预设不相符,你无需拆解整个函数结构,只需临时将返回值改为某个中间变量(例如 _可用工作表),就能立即看到该步骤的计算结果,快速定位问题所在。以下动画演示了如何查看A列人名所在工作表名等变量运算结果:有些朋友会喜欢使用a、b、c这样单纯的字母去表达变量名称,但强烈不推荐,原因很简单,单个字母容易和单元格引用地址(例如A1/B2)冲突。而使用_a、_b、_c可以避免这类问题,但这类变量名称没有具体含义,也就没有记忆点,只是追求公式看起来简洁,通常也不推荐。除此之外,LET 的另一个优势体现在参数变更的便捷性上。当公式的运算参数发生了变化,比如,由查询"财务部","销售部","IT部"三张工作表,变成了查询"财务部","销售部","IT部","生产部"四张工作表,我们只需要调整公式中的变量_工作表的内容表达式即可。无需改动后续任何逻辑——所有依赖_工作表 的步骤会自动适配新范围。这种参数“集中配置、分散使用”的模式,也是一种工程化思维的体现。=LET( _工作表,{"财务部","销售部","IT部","生产部"}, _人名出现次数,COUNTIF(INDIRECT(_工作表&"!a:a"),A2), _可用工作表,LOOKUP(1,0/_人名出现次数,_工作表), _查询区域,INDIRECT(_可用工作表&"!a:b"), _查询,VLOOKUP(A2,_查询区域,2,0), _结果容错,IFERROR(_查询,"查无"), _结果容错)
❶ 在编辑公式时,按下 Alt + Enter 可以手动换行。换行可以提升公式的可读性,完全不影响公式计算——尤其适合编写 LET、LAMBDA 等多行结构的复杂公式。❷ 一个LET函数定义的变量,只在当前单元格的公式内部使用。如果多个单元格需要复用相同的逻辑或参数(比如部门列表 {"财务部","销售部",...}),建议使用 Excel 的 「定义名称」 功能,将公共部分提取为全局名称。(▼へ▼メ)没了,今天分享的内容就这些,更多表格技巧欢迎扫码关注我们。最后祝大家工作愉快。有缘的话,咱们付费会员微信答疑交流群再见吧。👀
本文由公众号“Excel星球”首发。
点击阅读原文系统学习Excel!