允许目标 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.Goto
、Select
和 Selection
是不必要的。
因此你真的应该使用:
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))
我有一个工作表,我将数据从 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.Goto
、Select
和 Selection
是不必要的。
因此你真的应该使用:
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))