为啥我们总说动态数组公式会把简单问题复杂化
为什么现阶段“动态数组公式”非常的高级好用,有很多的优点,带来的革命性变革对于我们处理数据产生了深远的影响,但大家还是会产生“简单问题复杂化”的这种观念呢,或者说这种误区呢?难道说微软或金山会专门研究出一些新函数让用户们实现"简单问题复杂化"的目的?
这是一个非常值得探讨的问题。因为小编也是通过今年的逐步学习才从这个观念中走出来的。
小编感觉造成这种观念的原因,可能有以下几个方面(仅代表个人观点)。
在认知与习惯的层面上:
传统函数是"单元格思维",即一个公式在一个单元格里,计算得到一个结果,然后向下或向右拖拽填充。逻辑是线性的、局部的。
新函数是"数组和编程思维",即一个公式处理一个完整的数据区域,返回一个整体结果。它要求我们从"处理一个点"转变为"定义一个过程来处理整个面"。这种思维转换需要时间和练习。
对于简单的定义不同:
很多小伙伴们认为的"简单",往往是"操作步骤的简单"和"学习成本的简单"。比如:用筛选+复制粘贴,或写一个简单的 IF再拖拽,虽然步骤多,但每一步都直观、可预期。
新函数带来的"简单",是"逻辑表达的简单"和"模型维护的简单"。它将多步操作凝聚在一个公式里,逻辑自己包含,但理解这个"整体模型"本身需要更高的认知负荷。初期学习的困难掩盖了长期使用的便洁。再换句话说就是被困难吓倒了,已经无所谓好不好用了。
所见即所得的缺失感:
传统分步操作,每一步的中间结果都能在单元格里看到,给人以安全感和控制感。
而现阶段像REDUCE、SCAN这样的函数,它们的运算过程是内存中完成的,用户看不到迭代的中间状态。这种貌似的黑暗感让人不安,觉得难以调试和理解。
再有一点实际的就是:
目前的相对简单的职场实际工作压根不需要这些,也就是说需求感不够,需求感的不够造成的“没用感”的迎刃而出。
当然了,所有的感觉都是完全正常的感觉。因为方法没有优劣,能解决问题的方法就是好方法,能适应自己知识储备方法就是好方法。
哈哈哈,啰嗦了很多,我们今天就用一个“非常简单的案例”,慢慢的改变我们的思维吧,让我们将这些新函数用起来,将这些新观念用起来!
比如我们解决这种纵向的分类数据转换为横向的分类数据。
左表:
首行为各列标题品类,每个列标题下面为所属品类的各名称。
右表:
首列为各行标题,每个行标题右侧为所属的品类名称,且不同名称合并在一个单元格内。
总的来说,这个问题非常的简单。
为什么说简单呢?因为我们只需要分区块、借助辅助列编写几个很短的公式,得到最后的结构布局“模样”,是很容易的。
我们先来介绍一下不考虑“整理”思维、不考虑“二次调用”思维的“简单”方法。
首先在E2单元格使用TRANSPOSE函数,设置A2:C2首行列标题行的转置效果,将一行转换为一列、将横向转置为纵向:
=TRANSPOSE(A2:C2)
接下来在F2单元格再次输入TRANSPOSE函数,将A3:C6明细名称的每行依次纵向转横向:
=TRANSPOSE(A3:C6)
然后我们发现,上一步TRANSPOSE函数转换后的结果中出现很多由于数据源中包含很多空值而产生的“0”,所以我们又要想方设法去掉“0”值,显示为空。幸亏思路不难,继续使用IF函数就可以了:
=IF(TRANSPOSE(A3:C6)=0,"",TRANSPOSE(A3:C6))
如果IF第一参数TRANSPOSE结果等于0成立,我们返回第二参数固定的空值,否则我们返回TRANSPOSE原结果。
这都是最基础的知识点了。
因为上一步返回的转置结果要放在一个单元格中。所以最后又要在J2单元格输入新的TEXTJOIN函数公式:
=TEXTJOIN(",",1,F2:I2)
利用列分隔符逗号",“将F2:I2区域各值,忽略空值单元格后,合并到一个单元格中,得到第一个合并结果后,手动下拉填充公式得到所有结果。
我们还发现:
中间的IF函数辅助区域F2:I4并不是我们想要展示的,所以我们又做了一个“隐藏”区域的操作,起到了一个“美化”的作用。
至此,我们就用了一个“简单”的方法完成了左表向右表的转换。这种操作,对于很多小伙伴来说,已经算是一种很成功、很值得向周边同事展示的技能了。
但是,大家有没有发现,我们上面操作的整个流程非常的“笨重”:
比如说,我们整个过程,分别在3个不同的位置输入了3个不同的公式,E2有1个TRANSPOSE、F2有1个TRANSPOSE+IF,J2有一个TEXTJOIN,这就造成了后期修改公式的困难且容易出错。
虽然TRANSPOSE能实现数组溢出,但TEXTJOIN仍然需要手动下拉填充,逐个填写公式。这种复制粘贴公式造成了逻辑重复,计算效率低。如果数据量巨大:你可以想象一下每次更新完公式后“10个线程”的卡顿、无响应、闪退的经历。
辅助列,我们不能删除,因为后面结果是由前面辅助列而来的,牵一发而动全身。如果隐藏,又会造成表格结构的破坏。
如果我们想进一步引用结果区域,也就是二次引用、重复调用,就又要以此为数据源,建立辅助列,无法储存中间变量。
当然了,如果你对动态公式没有太大需求,以上完全可以忽略,用老方法就行。
下面我们来看看如何破解“普通公式”的弊端,由“普通公式”过渡到“动态公式”,输入一个公式就能扩展得到所有结果。
我们还是先由“普通公式”内部切入,逐步代替“普通公式”变成“动态公式”。
普通公式
首先TRANSPOSE转置A2:C2区域,横向转纵向,得到品类的纵向行标题:
=TRANSPOSE(A2:C2)
普通公式
其次再次用TRANSPOSE转置A3:C6区域,各列纵向转横向,得到每个行标题所属的名称明细:
=TRANSPOSE(A3:C6)
普通公式
继续使用TEXTJOIN利用逗号忽略空值后合并单元格内容至一个单元格:
=TEXTJOIN(”,",1,F2:I2)
思考普通公式向动态公式的转换
利用BYROW按行循环行数:
=BYROW(F2#,LAMBDA(x,TEXTJOIN(",",1,x)))
LAMBDA(x,TEXTJOIN(",",1,x))
LAMBDA定义变量x,代表每行数据,即对每行数组构造TEXTJOIN的合并逻辑。
所以将BYROW函数的循环区域F2:I4(F2#)的每行循环传递给x,进行LAMBDA指定规则的合并处理。
这样产生了第一个动态结构,返回结果直接数组溢出,无需下拉填充。
思考普通公式向动态公式的转换
因为上一步公式中的F2:I4(F2#)这个辅助区域是通过TRANSPOSE(A3:C6)而得来的,所以我们可以设置一个变量a,赋予TRANSPOSE(A3:C6)的内涵。
思考普通公式向动态公式的转换
将上面的思路通过LET这个“公式函数”内嵌进去:
=LET(a,TRANSPOSE(A3:C6),BYROW(a,LAMBDA(x,TEXTJOIN(",",1,x))))
TRANSPOSE(A3:C6)代替变量a,BYROW执行对变量a区域的行循环,传递给LAMBDA执行每行TEXTJOIN合并的计算规则。
此时,删除中间辅助区域,不会影响公式的结果,至此我们就通过调用中间变量a的模式,摆脱了辅助列的困扰。
思考普通公式向动态公式的转换
至此,我们的动态公式构造的还不是一个整体。
E列的TRANSPOS转置结果与F列的LET动态溢出结果仍分属两个单独公式,分属两列独立的列区域。
所以我们使用HSTACK函数横向拼接这两个区域即可:
=HSTACK(TRANSPOSE(A2:C2),LET(a,TRANSPOSE(A3:C6),BYROW(a,LAMBDA(x,TEXTJOIN(",",1,x)))))
至此,动态公式彻底的变成了一个整体的数组溢出结果。
如果大家还是带有“简单问题复杂化”这种观念,说明大家没有“所谓的需求”,还可能需要通过大量复杂案例慢慢体会动态公式的真谛与便利性。