乐于分享
好东西不私藏

变量x加个括号,WPS突然就听话了!到底发生了什么?

变量x加个括号,WPS突然就听话了!到底发生了什么?

上周在微信答疑群里,有位朋友发来一张截图,咨询了一个问题。A列是一长串快递运单号,中间夹杂着若干空行,他想把这些空行快速填上:用其下方第一个非空运单号补齐,也就是所谓的“向上填充”。
他试了网上常见的 Map+Lambda 组合公式,在微软的Excel里跑得稳稳当当,可一放到金山WPS表格里就弹出“公式中有多余的运算数据”,回车键无法完成公式,死活不出结果。折腾了半天,最后他偶然给变量x身上套了个括号(x),公式居然奇迹的恢复正常了。群里顿时炸开了锅:“凭什么加个括号就能救回来?” 这个问题恰好撞上了我今天想聊的主题:为什么要给变量x加上括号
首先尝试用Tocol函数:

=TOCOL(A2:A8,1)

Tocol(区域, 1)

将指定区域转换为一列垂直数组,并且忽略所有空单元格。
所以此时我们就将A2:A8这个最完整最全的“原始单号”列区域,同时忽略其中的空值单元格后重新再次转置为了单列。
其实目的就是为了去掉空格,这是利用Tocol函数去空格的一种窍门方法,我们在很多案例中都会借鉴到这种技巧。
接着引入Take函数:

=TAKE(TOCOL(A2:A8,1),1)

Take(…, 1)

作用是从数组的开头提取指定的行数或列数。
在这里,Take(数组,1)的意思就是提取上一步Tocol得到的数组中的第一行(即第一个)元素“jd01”
接下来是今天这个公式的灵魂。
我们逐步构造“动态缩小范围”的逻辑。
也就是让上面的Take(Tocol(A2:A8,1),1)这个逻辑模型中的A2:A8区域动态缩小,就像下面这样,该区域的起始位置由最初的A2逐渐缩小,而区域的结束位置则保持最后的A8固定不变。缩小变化过程如下:

A2:A8

A3:A8

A4:A8

A5:A8

A6:A8

A7:A8

A8:A8

按照上面的思路,为了让大家看清数据是如何流动的,我们将这个“动态缩小范围”逐步代入Take+Tocol中进行观察学习:
①当遍历到A3时,范围是A3:A8,提取到该范围的第一个非空值 jd01:

=TAKE(TOCOL(A3:A8,1),1)

②当遍历到A4时,范围是A4:A8,提取到该范围的第一个非空值 jd01:

=TAKE(TOCOL(A4:A6,1),1)

③当遍历到A5时,范围是A5:A8,提取到该范围的第一个非空值 sf66:

=TAKE(TOCOL(A5:A8,1),1)

④当遍历到A6时,范围是A6:A8,提取到该范围的第一个非空值 sf66:

=TAKE(TOCOL(A6:A8,1),1)

⑤当遍历到A7时,范围是A7:A8,提取到该范围的第一个非空值 yt88:

=TAKE(TOCOL(A7:A8,1),1)

⑥当遍历到A8时,范围是A8:A8,提取到该范围的第一个非空值 yt88:

=TAKE(TOCOL(A8:A8,1),1)

我们发现,如果能让起初的“A2:A8”范围逐渐动态缩小的话:

A2:A8

A3:A8

A4:A8

A5:A8

A6:A8

A7:A8

A8:A8

我们就能按照Take+Tocol的这个非常经典且巧妙的Excel和WPS数组公式,解决“向上填充空行”的问题。实际上逻辑是向上填充,但实现方式是单列数据跳过空值后截取第一个值的思路。

如下图所示,构造的动态取值结果就是“向上填充空行”的结果:
所以我们可以将“A2:A8”的起始位置用变量x表示。当公式遍历到某个单元格x时,x:A8就构成了一个动态的引用范围:

TAKE(TOCOL(x:A8,1),1)

然后用标准的lambda自定义公式:
Lambda(x,x参与的逻辑式)
封装成上面的逻辑后就变成这样的:
Lambda(x,Take(Tocol(x:A8,1),1))
最后用上map超级遍历函数:

=MAP(A2:A8,lambda(x,TAKE(TOCOL(x:A8,1),1)))

map函数是驱动上面lambda工作的关键引擎,它会将第一参数A2:A8遍历区域中的每个值依次传递给变量x进行lambda的自定义(Take+Tocol)的计算,实现向上填充效果。

理论上这样完全没问题,逻辑清晰,找不到任何破绽,但是小编目前使用的金山WPS表格,提示“公式中有多余的运算数据”,导致无法回车键一键出结果。
如果我们单独对变量x加上括号变成(x)后,金山WPS版本下就能一键出结果了:

=MAP(A2:A8,LAMBDA(x,TAKE(TOCOL((x):A8,1),1)))

其实这个弊端只会出现在金山WPS表格中,如果大家使用的是微软的Office Excel,这个公式是完全没问题的。

那么为什么同样一个公式,在WPS表格与微软Excel里会被区别对待呢?
这是Excel与WPS公式引擎在Lambda参数类型处理上的差异导致的,本质是一个“引用保留”的问题。
Lambda形参x在两家表格引擎里的身份不同。
在微软Excel里:
Map(A2:A8,Lambda(x,…))在遍历时,x保留了单元格引用的属性,即x仍然是一个引用类型,比如$A$2、$A$3等形式。
所以当你写x:A8时:x比如引用的是$A$2,A8是引用$A$8,冒号运算符会把两个引用拼成一个动态范围$A$2:$A$8。Excel的引用引擎原生就支持这种“引用+冒号+引用”的拼接,x:A8符合规则,不需要括号。
在金山WPS表格里:
Map+Lambda在传参时,把x先求值变成了“”,而不是保留“引用”。
也就是说遍历到A2时:
Excel里的x=$A$2(引用)
WPS里的x=“jd01”(值)
这时候问题就来了:冒号“:”作为范围运算符,左边期待的是一个引用,但WPS给过来的是个具体值“jd01”。于是WPS的解析器懵了:
值是不能跟“:A8”拼成范围的啊,你这公式是不是写错了?
于是抛出了“公式中有多余的运算数据”的错误提示框。
那为什么加上括号后(x)就救回来了?
(x)在金山WPS的解析器里触发了一个微妙的行为:括号强制让x回到“引用语义”后重新参与运算,或者说括号改变了优先级,让解析器先把x当成一个独立单元,再去跟“:A8”做范围拼接时,走的是另一套语法路径,避开了“值+冒号+引用”的冲突判断。
所以这里“加括号”的动作绝对不是多此一举,是在金山WPS里给Lambda的形参补引用身份的惯用手法,只是很多人没有细致思考过这个问题。如果公式要在WPS和Excel两家通吃,保留(x)这种写法是最稳的。

(如果您还有其它方面的问题,可后台消息框回复“提问”进行咨询)

学习Excel/你可以不常用/但不能不会用/如果你没有天赋/那就一直重复/当你快到本能反应的时候/你的重复就是别人眼中的天赋/冲破捆绑/展翅翱翔

map遍历scan遍历reduce迭代

pivotby降维byrow函数let函数

pivotby函数groupby函数

makearraymakearray

Excel视频大全①/Excel视频大全②

数据转换大全/Excel大全/正则大全