允许目标 table 扩展的动态数组公式

Dynamic array formula that allows for target table expansion

我有一个工作表,我将数据从 Table1 复制到 Table2。

将数据复制粘贴到位于 Table1 下方的 Table2 后,我 select Table2 第一列中的第一个单元格,然后按 Ctrl+ Shift+向下 to select 向下到最后使用的单元格。最后,我应用了一个串联数组公式,为表 1 中相关单元格的值添加了一个后缀。我已经将这些 Table2 步骤记录为一个宏。

为了演示,表 1 如下所示:

Table1

   |  A      B   C   D   E
---+-----------------------
 1 | Name    V1  V3  V3  V4
---+-----------------------
 2 | Wood    10  10  10  10
 3 | wood    28  28  28  28
 4 | tree    30  45  60  68
 5 | plastic 50  50  50  50
 6 | tree    50  50  50  50
 7 | iron    64  75  75  80

这是我在表 2 的 A 列中使用的公式:

{=concatenate(A2:A7," - A")}

这是将其应用于表 2 后的结果:

Table2

   |  A               B    C    D    E
---+-----------------------------------
25 | Wood - A        25   25   25   25
26 | wood - A        50   50   50   50
27 | tree - A        50   50   100  100
28 | plastic - A     100  100  100  100
29 | tree - A        100  100  100  100
30 | iron - A        100  100  100  100


现在,当我向 Table1 添加新条目时,例如在单元格 A8 & A9 中:

Table1a

   |  A      B   C   D   E
---+-----------------------
 1 | Name    V1  V3  V3  V4
---+-----------------------
 2 | Wood    10  10  10  10
 3 | wood    28  28  28  28
 4 | tree    30  45  60  68
 5 | plastic 50  50  50  50
 6 | tree    50  50  50  50
 7 | iron    64  75  75  80
 8 | table   20  25  0   30
 9 | plastic 54  35  21  0 

在 运行 录制的宏之后,没有使用新的范围 A2:A9,而是使用以前录制的范围 (A2:A7),导致 #N/A 错误如表2a所示:

Table2a

   |  A               B    C    D    E
---+-----------------------------------
25 | Wood - A        25   25   25   25
26 | wood - A        50   50   50   50
27 | tree - A        50   50   100  100
28 | plastic - A     100  100  100  100
29 | tree - A        100  100  100  100
30 | iron - A        100  100  100  100
31 | #N/A            #N/A #N/A #N/A #N/A
32 | #N/A            #N/A #N/A #N/A #N/A

这是因为在数组公式中,范围不是动态的,而是固定的

所以,我想要一个公式,当在 Table1 中添加或删除新条目时自动调整范围。类似于我在记录的宏中的内容,在应用数组公式之前 selects Table2 A 列中的所有单元格:

Application.Goto Reference:="R25C1"
Range("A25", Range("A25").End(xlDown)).Select

我在想类似下面的内容,我在其中提供了 Table1 的起始单元格,并自动计算出到最后一个包含数据的单元格的范围:

Selection.FormulaArray = "=concatenate(Range("A2",Range("A2").End(xldown)).Select,""- A"")"

我想要一个可以应用于所有单元格的公式解决方案。我不想为此定义变量等。

答案很简单:

Selection.FormulaArray = "=concatenate(A2:" & Range("A2").End(xlDown).Address & ","" - A"")"

请注意,您必须将原始数组公式中的每个单引号 " 转换为双引号 "".

解决方案的技巧是计算范围最后一个单元格的地址,并用此地址替换A6。这必须在 外部 字符串中完成,并使用字符串连接运算符 &.

添加到字符串中

然而,Application.GotoSelectSelection 是不必要的。

因此你真的应该使用:

Range("A25", Range("A25").End(xlDown)).FormulaArray _
= "=concatenate(A2:" & Range("A2").End(xlDown).Address & ","" - A"")"

使用 With 的另一种编码方式是:

With Range("A25", Range("A25").End(xlDown))
  .FormulaArray = "=concatenate(A2:" & Range("A2").End(xlDown).Address & ","" - A"")"
End With

最后,一个 "proper" VBA 解决方案(你明确表示你不想要的那个):

With Range("A2").End(xlDown)
  Range("A25", .Offset(25 - 2)).FormulaArray = "=concatenate(A2:" & .Address & ","" - A"")"
End With

请注意,使用最后一个解决方案,不再需要手动 pre-copy 将数据从 Table1 转移到 Table2。


附录:

刚刚意识到您要求的是 "pure" 公式 解决方案。如果这就是您所追求的,那么这个公式有效:

{=CONCATENATE(A2:INDEX(A1:A24,MATCH("*",A1:A24,-1))," - A")}

只要记住在转换它以用于 VBA 时将所有单引号双引号。结果 VBA 看起来像这样:

Selection.FormulaArray = "=CONCATENATE(A2:INDEX(A1:A24,MATCH(""*"",A1:A24,-1)),"" - A"")"

X-Solution(参见What is the XY problem?

还刚刚意识到,如果您只使用普通公式而不是数组公式,则实际上并不需要复杂的动态公式。

只需表 2 的 select 列 A 并在单元格 A25 中输入以下公式。按 Ctrl+Enter 将其作为普通公式输入到所有 selected 单元格中。

=CONCATENATE(A2," - A")

VBA 代码是:

Selection.Formula = "=CONCATENATE(A2,"" - A"")"

当您在表 1 中添加或删除行时,此公式将自动调整。

当然,我建议使用 "proper" 全自动 VBA 代码,不需要手动 pre-copying:

Range("A25", Range("A2").End(xlDown).Offset(25 - 2)).Formula = "=CONCATENATE(A2,"" - A"")"

最后:

查看您之前的问题和本次提供的数据后,B-E 列的解决方案同样简单。所有这些列都使用相同的公式,使用 Ctrl+Enter.

输入单元格 B25

正规公式:

=IF(B2<25,25,IF(B2<50,50,100))

等价于VBA:

Selection.Formula = "=IF(B2<25,25,IF(B2<50,50,100))"

"Proper" fully-auto VBA:

With Range("A2").End(xlDown)
  Range("B25", .Offset(25 - 2, 4)).Formula = "=IF(B2<25,25,IF(B2<50,50,100))"
End With

请注意,我简化了公式,直接使用数字代替数字作为字符串,然后使用 VALUE() 将它们转换为数字。

您需要根据 A 列中的文本值动态扩展公式中的范围。

=concatenate(A2:index(a:a, match("zzz", a:a)), " - A")

为了使数字条目同质化,他们应该使用相同的匹配公式来确定终止行。对于 B 列,

b2:index(b:b, match("zzz", a:a))