有没有办法在没有VBA的情况下串联两个数组?

Ima*_*889 2 arrays excel concatenation excel-formula

我正在尝试创建一个公式,该公式返回两个不同长度的数组的串联。我需要将此串联用于另一个公式的一部分,如果可能的话,我希望避免使用“帮助”行。

参见下面的示例数据。

在此处输入图片说明

目的是使输出为{10;11;12;13;20;21;22}。当然,可以很容易地将其硬编码到公式中,但是这些值是动态的,因此不是一种选择。

我尝试了以下方法:

{A1:A4;B1:B3}
Run Code Online (Sandbox Code Playgroud)

但这显然不是有效的Excel语法。

有解决方案吗?

小智 20

如果您只需要连接两个数组并且您有最新版本的 Excel,我相信这是保持数组原始顺序的最短答案。

该答案循环遍历s数组(这是两个目标数组的组合长度),并使用 if 语句来确定是输出数组a 的元素还是数组b 的元素。

要将此公式复制并粘贴到工作簿中,您只需将A2#B2#的值更改为您想要连接的两个数组。

多线版本

=LET(
    a, A2#,
    b, B2#,
    s, SEQUENCE(ROWS(a) + ROWS(b)),
    IF(s > ROWS(a), 
        INDEX(b, s - ROWS(a)), 
        INDEX(a, s)
    ))
Run Code Online (Sandbox Code Playgroud)

缩小版:

=LET(a,A2#,b,B2#,s,SEQUENCE(ROWS(a)+ROWS(b)),IF(s>ROWS(a),INDEX(b,s-ROWS(a)),INDEX(a,s)))
Run Code Online (Sandbox Code Playgroud)


Ima*_*889 5

Excel无法按照您描述的方式直接串联数组(即,简单地将它们背靠背组合在一起)。但是,有一个(复杂的)解决方案,无需使用辅助函数即可解决此问题。

本质上,您需要做的是将转换{10;11;12;13}{10;11;12;13;0;0;0}并转换{20;21;22}{0;0;0;0;20;21;22}。得到该结果后,可以将长度为7的两个数组加在一起以获得所需的结果。

那么如何将零添加到数组的开头或结尾?

答案是MMULT巧妙地使用矩阵乘法(Excel内置函数)。

我不会解释所有数学原理,为什么会这样,因为我认为编程太离题了,但最终以下矩阵乘法方程式为您提供了理想的结果:

[1 0 0 0]   [10]   [10]
[0 1 0 0] * [11] = [11]
[0 0 1 0]   [12]   [12]
[0 0 0 1]   [13]   [13]
[0 0 0 0]          [ 0]
[0 0 0 0]          [ 0]
[0 0 0 0]          [ 0]
Run Code Online (Sandbox Code Playgroud)

或者在Excel中,您可以键入以下内容来获得结果:(我添加了换行符以提高可读性。)

= MMULT({1,0,0,0;
         0,1,0,0;
         0,0,1,0;
         0,0,0,1;
         0,0,0,0;
         0,0,0,0;
         0,0,0,0},A1:A4)
Run Code Online (Sandbox Code Playgroud)

如果您在单元格中突出显示此公式并按F9键,则应注意它将为您提供所需的结果{10;11;12;13;0;0;0}

同样,以下公式将为您提供所需的结果{0;0;0;0;20;21;22}

= MMULT({0,0,0;
         0,0,0;
         0,0,0;
         0,0,0;
         1,0,0;
         0,1,0;
         0,0,1},B1:B3)
Run Code Online (Sandbox Code Playgroud)

将这两个值加在一起将得到所需的最终结果{10;11;12;13;20;21;22}


注意

在这一点上,这可能足以满足您的需求。但是,对于大型数组,将这些1和0的矩阵硬编码到公式中可能太麻烦了。如果是这种情况,请继续阅读以了解如何自动生成这些1和0的矩阵,而不是对其进行硬编码。


我们如何自动生成上面显示的1和0的大型矩阵?

同样,由于我认为讨论将变得太长且太离题了,因此在这里没有解释很多“为什么”,下面是一个公式,该公式生成上面的1和0的第一个矩阵:

= (ROW(INDIRECT(ADDRESS(1,1)&":"&ADDRESS(ROWS(A1:A4)+ROWS(B1:B3),1)))
  =COLUMN(INDIRECT(ADDRESS(1,1)&":"&ADDRESS(1,ROWS(A1:A4)))))+0
Run Code Online (Sandbox Code Playgroud)

1和0的第二矩阵的公式略有不同:

= (ROW(INDIRECT(ADDRESS(1,1)&":"&ADDRESS(ROWS(A1:A4)+ROWS(B1:B3),1)))
  =(COLUMN(INDIRECT(ADDRESS(1,1)&":"&ADDRESS(1,ROWS(B1:B3))))+ROWS(A1:A4)))+0
Run Code Online (Sandbox Code Playgroud)

最终公式

连接两个(垂直)数组的最终公式如下:(添加了多个换行符以提高可读性)

= MMULT(
    (ROW(INDIRECT(ADDRESS(1,1)&":"&ADDRESS(ROWS(A1:A4)+ROWS(B1:B3),1)))
    =COLUMN(INDIRECT(ADDRESS(1,1)&":"&ADDRESS(1,ROWS(A1:A4)))))+0,
    A1:A4)
 +MMULT(
    (ROW(INDIRECT(ADDRESS(1,1)&":"&ADDRESS(ROWS(A1:A4)+ROWS(B1:B3),1)))
    =(COLUMN(INDIRECT(ADDRESS(1,1)&":"&ADDRESS(1,ROWS(B1:B3))))+ROWS(A1:A4)))+0,
    B1:B3)
Run Code Online (Sandbox Code Playgroud)

最后的笔记/思想

使用此公式的优点是它允许在不使用VBA的情况下串联数组。缺点是这种用于连接数组的方法仅适用于数字,不适用于文本。(这是因为MMULT需要数字。)

  • 没有易失性公式:`= MMULT((ROW($ A $ 1:INDEX($ A:$ A,ROWS($ A $ 1:$ A $ 4)+ ROWS($ B $ 1:$ B $ 3)))= COLUMN( $ A $ 1:INDEX($ 1:$ 1,ROWS($ A $ 1:$ A $ 4))))+ 0,$ A $ 1:$ A $ 4)+ MMULT((ROW($ A $ 1:INDEX($ A:$ A,ROWS($ A $ 1:$ A $ 4)+ ROWS($ B $ 1:$ B $ 3)))=(列($ A $ 1:INDEX($ 1:$ 1,ROWS($ B $ 1:$ B $ 3)) ))+ ROWS($ A $ 1:$ A $ 4))+ 0,$ B $ 1:$ B $ 3)` (3认同)
  • INDEX 对完整的列/行没有任何损害,因为它只设置要查看的范围,实际上并不将整个范围加载到内存中。它不使用比“$A$7”更多的内存 (3认同)

Ima*_*889 5

就其价值而言,这是一个连接两个任意两个垂直数组的解决方案(没有数据必须是数字的限制)。

这是数组公式:(例如组合A1:A4C7:C9

= INDEX(CHOOSE({1,2},A1:A4,C7:C9),
  N(IF({1},ROW(INDEX($A:$A,1):INDEX($A:$A,ROWS(A1:A4)+ROWS(C7:C9)))-IF(
  ROW(INDEX($A:$A,1):INDEX($A:$A,ROWS(A1:A4)+ROWS(C7:C9)))<=ROWS(A1:A4),0,ROWS(A1:A4)))),
  N(IF({1},2-(ROW(INDEX($A:$A,1):INDEX($A:$A,ROWS(A1:A4)+ROWS(C7:C9)))<=ROWS(A1:A4)))))
Run Code Online (Sandbox Code Playgroud)

这是组合两个水平数组的数组公式(例如A1:D1C3:E3

= INDEX(CHOOSE({1;2},A1:D1,C3:E3),
  N(IF({1},2-(COLUMN(INDEX($1:$1,1):INDEX($1:$1,COLUMNS(A1:D1)+COLUMNS(C3:E3)))
  <=COLUMNS(A1:D1)))),N(IF({1},COLUMN(INDEX($1:$1,1):INDEX($1:$1,COLUMNS(A1:D1)+
  COLUMNS(C3:E3)))-IF(COLUMN(INDEX($1:$1,1):INDEX($1:$1,COLUMNS(A1:D1)+COLUMNS(C3:E3)))
  <=COLUMNS(A1:D1),0,COLUMNS(A1:D1)))))
Run Code Online (Sandbox Code Playgroud)


小智 5

如果您有动态数组版本的 Excel、Excel 365 或 2019 年之后的版本,则答案要短得多。如果一列被命名Foo而另一列被命名Bar,则您的公式将是:

=SMALL((Foo,Bar),SEQUENCE(ROWS(Foo)+ROWS(Bar)))

这里,SEQUENCE返回一个数组,其序列为 1 到 Foo 和 Bar 的总行数。SMALL为序列中的每个值返回适当的值。然后 Excel 将结果“溢出”到公式下方所需的行数中。

  • 如果数组包含从小到大排序的数字,则此方法有效,因为 SMALL 返回数组中第 N 个最小的数字。 (2认同)

Rob*_*ert 5

感谢该线程之前的贡献者,我了解到附加数组数据的解决方案在于使用相等长度的数组。

该解决方案适用于文本和数字,但我使用了文本。

在下面的示例中,我加入了 3 个命名范围(分别命名为 Range1、Range2 和 Range3)。我还确保每个范围中的项目顺序保持不变,尽管这可能不是必要的。

我使用了Excel 365的LET函数来方便阅读。该范围只是溢出到输入公式的空白列中。

=LET(
TotRows,ROWS(Range1)+ROWS(Range2)+ROWS(Range3),
A,INDEX(Range1,SEQUENCE(TotRows)),
B,INDEX(Range2,SEQUENCE(TotRows,,-ROWS(Range1)+1,1)),
C,INDEX(Range3,SEQUENCE(TotRows,,-ROWS(Range1)-ROWS(Range2)+1,1)),
X,IFERROR(IFERROR(A,B),C),
X)
Run Code Online (Sandbox Code Playgroud)

更多范围可以轻松添加为 D、E、F 等。然后只需在末尾包装更多 IFERROR() 函数即可。我返回 X,但您当然可以将其包装到 UNIQUE() 中以提取唯一列表,或者您可以对其进行 SORT() 等。

当您稍微修改它以组合溢出范围时,事情会变得更加有趣和动态(即,命名范围被对溢出范围的引用替换(有关示例和使用的公式,请参阅随附的屏幕截图)

我的输入和结果如下所示:数据和公式输出的屏幕截图

祝你好运。