有没有办法在没有 VBA 的情况下在 Excel 中连接两个数组? [复制]

Posted

技术标签:

【中文标题】有没有办法在没有 VBA 的情况下在 Excel 中连接两个数组? [复制]【英文标题】:Is there a way to concatenate two arrays in Excel without VBA? [duplicate] 【发布时间】:2018-02-21 07:41:57 【问题描述】:

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

请参阅下面的示例数据。

目标是让输出为10;11;12;13;20;21;22。当然,这可以很容易地硬编码到公式中,但这些值是动态的,所以这不是一个选项。

我尝试了以下方法:

A1:A4;B1:B3

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

有解决办法吗?

【问题讨论】:

您尝试的方式(使用 和 ; 分隔行)完全符合您在 Google 表格中的期望 @OrenPinsky 不知道,谢谢分享!! 我不知道这个问题怎么可能被标记为重复。 1) 它比标记的问题大 4 年。 2)它们是两个完全不同的问题。这个问题询问如何为另一个公式的中间步骤连接两个数组。标记的问题询问如何从两个单独的列表中获取唯一的值列表。 【参考方案1】:

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

此答案循环遍历 s 数组(这是您的两个目标数组的组合长度),并使用 if 语句确定是否输出数组 a's 元素或数组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)
    ))

缩小版:

=LET(a,A2#,b,B2#,s,SEQUENCE(ROWS(a)+ROWS(b)),IF(s>ROWS(a),INDEX(b,s-ROWS(a)),INDEX(a,s)))

【讨论】:

【参考方案2】:

上面罗伯特的回答让我朝着正确的方向前进,但我需要能够合并具有多列的数组。

    =LET(
    TotRows,ROWS(Range1)+ROWS(Range2),
    A,TRANSPOSE(INDEX(Range1,SEQUENCE(1,TotRows),SEQUENCE(COLUMNS(Range1)))),
    B,TRANSPOSE(INDEX(Range2,SEQUENCE(1,TotRows,-ROWS(Range1)+1,1),SEQUENCE(COLUMNS(Range2)))),
    X,IFERROR(A,B),
    X)

这使我可以返回命名范围中的所有列。

剩下的唯一问题是第二个命名范围可能不返回任何行。如果第二个命名范围内没有任何行,我在 TotRows 定义中添加了一个检查以不添加其他行。

=LET(
TotRows,ROWS(Range1)+IF(COUNT(Range2)=0,0,ROWS(Range2)),
A,TRANSPOSE(INDEX(Range1,SEQUENCE(1,TotRows),SEQUENCE(COLUMNS(Range1)))),
B,TRANSPOSE(INDEX(Range2,SEQUENCE(1,TotRows,-ROWS(Range1)+1,1),SEQUENCE(COLUMNS(Range2)))),
X,IFERROR(A,B),
X)

【讨论】:

【参考方案3】:

在对 Excel 完全出乎意料的行为进行了大量实验后,我最终使用了一个非常简单的公式:

=IF(ROW()<=COUNTA(A:A),INDEX(A:A,ROW()),INDEX(B:B,ROW()-COUNTA(A:A)))

当然,counta(a:a) 可以分配给命名区域/单元格,这样公式会变得更快。

还请注意,无论有什么(数字、文本、日期...),它都会追加数组,因为这是一个简单的 Index() 用法!

如果您选择不同大小的数组,请将Index()...es 包含在IfError(...,0) 语句中! (ELSE 会出现一个奇怪的错误,即使 Excel 不应该计算 IF( ..., ..., ...) 语句中的错误部分)

将公式扩展为

=IF(ROW()<=COUNTA(H:I),INDEX(H:I,ROW(),COLUMN(A1:B1)),INDEX(K:L,ROW()-COUNTA(H:I),COLUMN(A1:B1)) )

追加多列数组...

【讨论】:

【参考方案4】:

SEQUENCE() 函数可用作连接数组的循环计数器。让数组为 range1range2 - 它们可以包含任何内容。

公式如下:

=IF(SEQUENCE(COUNTA(range1)+COUNTA(range2))<=COUNTA(range1),range1,INDEX(range2,SEQUENCE(COUNTA(range1)+COUNTA(range2))-COUNTA(range1)))

这假设range1 堆叠在顶部。如果range1 有5 个元素,range2 有6 个元素,那么SEQUENCE() 部分是SEQUENCE(11) = 1, 2, ..., 10, 11。这设置了连接数组的长度,您可以使用SEQUENCE() 的条目作为IF 表达式中的计数器:如果计数器range1 元素,否则选择range2元素。

SEQUENCE() 数组将range1range2 映射到用FALSE 填充的11 元素数组,因此IF 表达式的第二部分使用INDEX 将6 个位置移回填充-range2 的输出版本。

这些公式也适用:

=IF(SEQUENCE(COUNTA(range1)+COUNTA(range2))<=COUNTA(range1),INDEX(range1,SEQUENCE(COUNTA(range1))),INDEX(range2,SEQUENCE(COUNTA(range1)+COUNTA(range2))-COUNTA(range1)))

=IF(SEQUENCE(COUNTA(range1)+COUNTA(range2))<=COUNTA(range1),INDEX(range1,SEQUENCE(COUNTA(range1)+COUNTA(range2))),INDEX(range2,SEQUENCE(COUNTA(range1)+COUNTA(range2))-COUNTA(range1)))

示例:

【讨论】:

我在找这个!我有 2 个数组,开头字母后跟数字,这个解决方案帮助了我【参考方案5】:

用任何分隔符连接两个向量,例如“#”。 可以使用 Office 365 TextJoin() 一步完成。假设结果是单元格 A1 中的字符串: 10#11#12#13#20#21#22

然后使用以下公式创建单个字符串数组。选中连续7个单元格后记得点击CTRL-SHFT-Enter获取大括号显示数组:

=TRIM(MID(
  SUBSTITUTE(A1,"#",REPT(" ",99)),       
 (ROW(OFFSET($AB$1,,,LEN(A1)-LEN(SUBSTITUTE(A1,"#",""))+1))-1)*99+
((ROW(OFFSET($AB$1,,,LEN(A1)-LEN(SUBSTITUTE(A1,"#",""))+1)))=1),
  99))

还可以通过转换为公式中的数字来对数组求和:

=SUM(1*TRIM(MID(SUBSTITUTE(A1,"#",REPT(" ",99)),(ROW(OFFSET($AB$1,,,LEN(A1)-LEN(SUBSTITUTE(A1,"#",""))+1))-1)*99+((ROW(OFFSET($AB$1,,,LEN(A1)-LEN(SUBSTITUTE(A1,"#",""))+1)))=1),99)))= 109

【讨论】:

【参考方案6】:

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

此解决方案适用于文本和数字,但我使用的是文本。

在下面的示例中,我加入了 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)

更多的范围可以很容易地添加为 D、E、F 等.. 然后在最后包装更多的 IFERROR() 函数。我返回 X,但你当然可以将它包装到 UNIQUE() 中以提取唯一列表,或者你可以 SORT() 它等等。

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

我的输入和上面的结果如下:Screenshots of Data and Output with Formula

祝你好运。

【讨论】:

【参考方案7】:

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

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

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

【讨论】:

这适用于数组包含从小到大排序的数字,因为 SMALL 返回数组中第 N 个最小的数字。【参考方案8】:

对于两个垂直的单列列表/数组,试试这个:

https://drive.google.com/file/d/1x1SX4VGM7rQPMkJMVAtvDzpmYG2XHZWx/view?usp=sharing

(在 Excel 中打开,而不是在 Google 表格中打开)

我使用了 LET 函数,因为它被认为是最佳实践,并且更容易看到发生了什么。

使用的其他动态数组函数有:SORT、UNIQUE、FILTER、SEQUENCE、CHOOSE 和 INDEX

希望这会有所帮助,

ST

公式如下:

注意: List1List2是命名范围; K3# 和 M3# 是溢出的数组(见最后 2 个公式)

全部唯一:

=SORT(UNIQUE(LET(
RightList,FILTER(List2, NOT(ISBLANK(List2))),
LeftList,FILTER(List1, NOT(ISBLANK(List1))),
BothListCount,SEQUENCE(ROWS(LeftList)+ROWS(RightList),1,1),
INDEX(CHOOSE(1,2,LeftList,RightList),
N(IF(1,BothListCount IF(BothListCount<=ROWS(LeftList),0,ROWS(LeftList)))),
N(IF(1,2-(BothListCount<=ROWS(LeftList)))))
)))

在两个列表中:

=SORT(UNIQUE(FILTER(List1,COUNTIF(List2,List1)>0)))

不在两个列表中

=SORT(UNIQUE(LET(
RightList, M3#,
LeftList,K3#,
BothListCount,SEQUENCE(ROWS(LeftList)+ROWS(RightList),1,1),
INDEX(CHOOSE(1,2,LeftList,RightList),
N(IF(1,BothListCount-IF(BothListCount<=ROWS(LeftList),0,ROWS(LeftList)))),
N(IF(1,2-(BothListCount<=ROWS(LeftList)))))
)))

在列表 1 中,但不在列表 2 中 - 在上面的公式中也称为 K3#

=SORT(UNIQUE(FILTER(List1,(COUNTIF(List2,List1)=0)*NOT(ISBLANK(List1)))))

在列表 2 中,但不在列表 1 中 - 在上面的公式中也称为 M3#

=SORT(UNIQUE(FILTER(List2,(COUNTIF(List1,List2)=0)*NOT(ISBLANK(List2)))))

【讨论】:

【参考方案9】:

要在 MMULT 中为数值数组实现 1 和 0 的矩阵(如 @ImaginaryHuman072889 所述),请使用以下代码:

= --(((ROW()&lt;=TRANSPOSE(ROW()))*(ROW()&lt;10))*(TRANSPOSE(ROW($1:$11))&lt;=ROW($1:$11)))

他们的解决方案很好,但这将在访问矩阵功能时使用更少的代码,而无需使用 ADDRESS 或 INDIRECT 函数。两个简单的步骤:

    调整 (ROW() 调整行范围“11”以对应两个数组合并后将存在的总行数。

【讨论】:

【参考方案10】:

对于数值数组:

=SMALL((A1:A4,B1:B4),ROW(INDIRECT("1:"&COUNT(A1:A4)+COUNT(B1:B4))))

=SMALL((A1:A4,B1:B4),ROW(INDEX(A:A,1):INDEX(A:A,COUNT(A1:A4)+COUNT(B1:B4))))

【讨论】:

你能解释一下这些公式是如何解决这个问题的吗? 该公式给出了组合范围 (A1:A4,B1:B4) 的所有值的集合,从最小的 (Nr = 1) 到最大的 (Nr = COUNT(A1:A4) )+COUNT(B1:B4) = 成员数量)。这种通过方括号 (arr1,arr2,...) 组合数组的方式可能仅适用于函数 SMALL() 和 LARGE()。公式的任何方式都有效,而且很简单)) @4udoudo 有趣的公式,但没有回答问题。问题是如何连接两个数组。您的答案连接两个数组并对它们进行排序 对不起,但是在开始任务中写着“目标是让输出为 10;11;12;13;20;21;22”并且没有提到排序。使用我提出的公式,目标就达到了。 @4udoudo 问题指出所需的输出应该是A1:A4;B1:B3。这不是公式的输出。示例输入数据已排序的事实只是一个巧合。顺便说一句,我认为你的公式很聪明,只是说它没有回答问题。【参考方案11】:

TLDR 和自我指导 - Here's the example workbook。

是的,有一种方法可以在 pre-office 2016 中加入数组。我知道上面的 ImaginaryHuman 已经回答了这个问题,但我有另一种方法,它返回一个数组,并且更容易阅读(恕我直言)。我将分解公式的演变,以便您找到适合您的用例的公式。我以粗体突出显示了用例,以便您可以快速找到您的用例。我知道这很冗长,但我是那种喜欢知道解决方案如何运作的人,所以我会尽量给你同样的礼貌。

公式依赖于嵌套的IF 语句和INDEX/CHOOSE 结构。它适用于范围、命名范围,甚至表格列。我的所有示例都显示了四个范围,因此三个 IF 语句,但如果您关心那么多嵌套的 IF 语句,这可以串成(我认为)64 个范围。

对于这些示例,数据范围为 A3:B6A9:B11A14:B19A22:B32。生成的数组公式放在E3:E26 范围内,并以Ctrl+Shift+Enter 结尾,使其成为数组公式。您的数据可以随心所欲 - 您不受这些范围的限制 - 只需适当地替换您的范围。

如果您的数据在连续范围内

=IF(ROW()-ROW(E3)<ROWS(A3:A6),INDEX(A3:B6,ROW()-ROW(E3)+1,COLUMN()-COLUMN(E3)+1),
IF(ROW()-ROW(E3)<ROWS(A3:A6)+ROWS(A9:A11),INDEX(A9:B11,ROW()-ROW(E3)-ROWS(A9:A11),COLUMN()-COLUMN(E3)+1),
IF(ROW()-ROW(E3)<ROWS(A3:A6)+ROWS(A9:A11)+ROWS(A14:A19),INDEX(A14:B19,ROW()-ROW(E3)-ROWS(A3:A6)-ROWS(A9:A11)+1,COLUMN()-COLUMN(E3)+1),
INDEX(A22:B32,ROW()-ROW(E3)-ROWS(A3:A6)-ROWS(A9:A11)-ROWS(A14:A19)+1,COLUMN()-COLUMN(E3)+1))))

它是如何工作的:

    IF 语句通过从单元格E3 的输出范围顶部减去当前行并将其与@987654336 的第一个输入范围中的单元格数进行比较,确保我们在第一个范围内@。 INDEX 语句从A3:B6 的第一个输入范围中选择一个项目,给定从单元格E3 计算的行和列偏移量。 如果该行不在第一个范围内,则继续执行下一个IF 语句,该语句重复该过程,但将数组的当前行与前两个范围的长度进行比较。对任何进一步嵌套的 IF 语句重复该过程。

如果您的数据不在连续范围内,您需要一列显示数据最初来自哪个范围,或两者兼有:

=IF(ROW()-ROW(E3)<ROWS(A3:A6),INDEX(CHOOSE(1,2,3,1,A3:A6,B3:B6),ROW()-ROW(E3)+1,COLUMN()-COLUMN(E3)+1),
IF(ROW()-ROW(E3)<ROWS(A3:A6)+ROWS(A9:A11),INDEX(CHOOSE(1,2,3,2,A9:A11,B9:B11),ROW()-ROW(E3)-ROWS(A3:A6)+1,COLUMN()-COLUMN(E3)+1),
IF(ROW()-ROW(E3)<ROWS(A3:A6)+ROWS(A9:A11)+ROWS(A14:A19),INDEX(CHOOSE(1,2,3,3,A14:A19,B14:B19),ROW()-ROW(E3)-ROWS(A3:A6)-ROWS(A9:A11)+1,COLUMN()-COLUMN(E3)+1),
INDEX(CHOOSE(1,2,3,4,A22:A32,B22:B32),ROW()-ROW(E3)-ROWS(A3:A6)-ROWS(A9:A11)-ROWS(A14:A19)+1,COLUMN()-COLUMN(E3)+1))))

它是如何工作的:

    IFINDEX 语句的所有原则与上述相同。 添加了CHOOSE 语句,它允许您选择不连续的数据列或静态数组,其中包含您想要的每个范围的任何标识符。在这种情况下,我选择了数字 (1,2,3,4)。 CHOOSE 语句可以包含任意数量的列 - 只需将第一个参数更改为 1,2,3,4 即可获得四列,并将第四列添加为最后一个参数。对任何后续列执行相同操作(即 1,2,3,4,5 并将第五列添加为最后一个参数。

如果您有水平数据而不是垂直数据,您可以使用TRANSPOSE 使前面的示例工作。只需将 TRANSPOSE 函数嵌套在 CHOOSE 函数中,如下所示:

CHOOSE(1,2,3,1,TRANSPOSE(A3:C3),TRANSPOSE(A4:C4)

您可以使用命名范围或表格显着清理公式。此示例建立在前一个示例的基础上,允许数据不在连续范围内,并提供了一个标识符列,显示数据的来源:

=IF(ROW()-ROW(E3)<ROWS(Table1),INDEX(CHOOSE(1,2,3,1,Table1[Column1],Table1[Column2]),ROW()-ROW(E3)+1,COLUMN()-COLUMN(E3)+1),
IF(ROW()-ROW(E3)<ROWS(Table1)+ROWS(Table2),INDEX(CHOOSE(1,2,3,2,Table2[Column1],Table2[Column2]),ROW()-ROW(E3)-ROWS(Table1)+1,COLUMN()-COLUMN(E3)+1),
IF(ROW()-ROW(E3)<ROWS(Table1)+ROWS(Table2)+ROWS(Table3),INDEX(CHOOSE(1,2,3,3,Table3[Column1],Table3[Column2]),ROW()-ROW(E3)-ROWS(Table1)-ROWS(Table2)+1,COLUMN()-COLUMN(E3)+1),
INDEX(CHOOSE(1,2,3,4,Table4[Column1],Table4[Column2]),ROW()-ROW(E3)-ROWS(Table1)-ROWS(Table2)-ROWS(Table3)+1,COLUMN()-COLUMN(E3)+1))))

如果这还不够,您可以通过创建一些命名值来进行更多内务处理以提高可读性。可以做的第一件事是定义我们从哪一行开始从每个表中获取数据。对于此示例,我将它们命名为 Table2_ULTable3_ULTable4_UL。他们在名称管理器中的代码公式如下所示:

    Table2_UL: =ROWS(Table1) Table3_UL: =Table2_UL+ROWS(Table2) Table4_UL: =Table3_UL+ROWS(Table3)

如您所见,每个都建立在最后一个之上,因此其输出是动态的。我们现在有了一个更易读的公式:

=IF(ROW()-ROW(E3)<Table2_UL,INDEX(CHOOSE(1,2,3,1,Table1[Column1],Table1[Column2]),ROW()-ROW(E3)+1,COLUMN()-COLUMN(E3)+1),
IF(ROW()-ROW(E3)<Table3_UL,INDEX(CHOOSE(1,2,3,2,Table2[Column1],Table2[Column2]),ROW()-ROW(E3)-Table2_UL+1,COLUMN()-COLUMN(E3)+1),
IF(ROW()-ROW(E3)<Table4_UL,INDEX(CHOOSE(1,2,3,3,Table3[Column1],Table3[Column2]),ROW()-ROW(E3)-Table3_UL+1,COLUMN()-COLUMN(E3)+1),
INDEX(CHOOSE(1,2,3,4,Table4[Column1],Table4[Column2]),ROW()-ROW(E3)-Table4_UL+1,COLUMN()-COLUMN(E3)+1))))

但这对我来说还不够。我想摆脱所有对ROW()COLUMN() 的讨厌引用。我们可以通过在名称管理器中定义另外两个值来跟踪我们当前的行和列来做到这一点:

    Output_CC: =COLUMN()-COLUMN(Sheet1!E3)+1 Output_CR: =ROW()-ROW(Sheet1!E3)+1

最后,我们有了接近人类可读的东西:

=IF(Output_CR-1<Table2_UL,INDEX(CHOOSE(1,2,3,1,Table1[Column1],Table1[Column2]),Output_CR,Output_CC),
IF(Output_CR-1<Table3_UL,INDEX(CHOOSE(1,2,3,2,Table2[Column1],Table2[Column2]),Output_CR-Table2_UL,Output_CC),
IF(Output_CR-1<Table4_UL,INDEX(CHOOSE(1,2,3,3,Table3[Column1],Table3[Column2]),Output_CR-Table3_UL,Output_CC),
INDEX(CHOOSE(1,2,3,4,Table4[Column1],Table4[Column2]),Output_CR-Table4_UL,Output_CC))))

如果我们真的想一路走下去,我们也可以将 CHOOSE 语句转换为命名值。只需对名称管理器中的每个输入表执行以下操作,确保为每个输入表指定一个唯一名称:

Table1_IN:=CHOOSE(1,2,3,1,Table1[Column1],Table1[Column2])

现在我们可以很容易地阅读公式:

=IF(Output_CR-1<Table2_UL,INDEX(Table1_IN,Output_CR,Output_CC),
IF(Output_CR-1<Table3_UL,INDEX(Table2_IN,Output_CR-Table2_UL,Output_CC),
IF(Output_CR-1<Table4_UL,INDEX(Table3_IN,Output_CR-Table3_UL,Output_CC),
INDEX(Table4_IN,Output_CR-Table4_UL,Output_CC))))

同样,这还不够,因为您无法打开过滤器并对数组 A-Z 进行排序。您收到错误“您无法更改数组的一部分”。不过,有一个解决方法!它需要一个帮助列并复制您的输出。它可以复制到普通的旧范围或表格中。要允许您对数据进行排序和过滤,请在数组输出左侧创建一个辅助列,在本例中,从 D3 开始。如果您的数据不需要排序(如所有文本列),请创建静态编号(1、2、3、4 等)。在此示例中,列 G 包含要排名的数字。如果确实需要排名,请在D3中输入以下公式并向下拖动:

=RANK.EQ(G3,G$3:G$26,0)+COUNTIF(G$3:G3,G3)-1

如果您需要升序排名,请将最后一个参数更改为 1。如果您的数据被排名,那么您现在有一个乱序排名,或者如果没有排名,则它旁边有一个静态数字的不可排序数组。现在我们将数据复制到一个范围或表格中。在I 列中,从I3 开始,创建与数据集一样长的静态编号(即1、2、3、4)。现在在单元格J3 的右侧输入引用源数组中数据的VLOOKUP

=VLOOKUP($I3,$D$3:$G$26,COLUMNS($I$3:J3),FALSE)

向下拖动公式,然后向右拖动。您现在可以像正常范围一样对数据进行排序和过滤。

【讨论】:

【参考方案12】:

对于它的价值,这是一个连接两个任意两个垂直数组的解决方案(不限制数据必须是数字)。

这里是数组公式:(例如结合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)))))

这里是组合两个水平数组的数组公式(例如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)))))

【讨论】:

请注意,如果您在 CHOOSE 中使用数组索引,它就会出现,例如CHOOSE( 1,2, ...) 它将返回的值截断为最多 255 个字符,至少对于文本值是这样。具有讽刺意味的是,如果您使用标量索引,例如CHOOSE(2, ...),貌似没有字数限制。在 Office 365 上测试。【参考方案13】:

Excel 无法以您描述的方式直接连接数组(即简单地将它们背靠背组合。)但是,对于这个问题有一个(复杂的)解决方案,而不使用辅助函数。

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

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

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

我不会解释为什么这是结果的所有数学,因为我认为它与编程太离题了,但最终下面的矩阵乘法方程会给你想要的结果:

[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]

或者在 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)

如果您在单元格中突出显示此公式并按 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)

将这两个值相加将得到所需的最终结果,即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

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

最终公式

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

= 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)

最后的笔记/想法

使用这个公式的好处是它允许在不使用 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))) =(COLUMN($A$1:INDEX($1:$1,ROWS($B$1:$B$3))))+ROWS($A$1:$A$4))+0, $B$1:$B$3) 谢谢斯科特。我一直想知道是否有办法使用INDIRECT(ADDRESS(...。但我通常避免在公式中检查整个行/列(例如A:A),因为在我看来,考虑到电子表格实际上包含超过一百万行,这会减慢速度。使用你的方法比INDIRECT更有效吗? INDEX 对完整的列/行没有任何损害,因为它只设置要查看的范围,实际上并没有将整个范围加载到内存中。它使用的内存不超过$A$7 感谢 Scott,这对将来的使用很有帮助,因为我经常发现自己在使用 INDIRECT(ADDRESS(...

以上是关于有没有办法在没有 VBA 的情况下在 Excel 中连接两个数组? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何在仍可以更改工作表中的值的情况下在vba excel中执行Do Event计时器?

OBIEE 11 - 如何在没有提示的情况下在 excel 中导出多页仪表板

如何在不使用 VBA 的情况下在 Excel 中转换 HEX 和 DEC 之间的大数字?

有没有办法像 c# 一样在 Excel 的 VBA 中注释一行的一部分

在不使用 VBA 的情况下突出显示 Excel 中的活动行/列?

有没有办法让 Excel VBA 宏提示输入文件? [复制]