从单个单元格中获取整个数组,该单元格是包含相同数组公式的单元格集合的一部分?
Posted
技术标签:
【中文标题】从单个单元格中获取整个数组,该单元格是包含相同数组公式的单元格集合的一部分?【英文标题】:Obtain entire array from a single cell that is part of a collection of cells containing the same array formula? 【发布时间】:2015-09-28 14:28:21 【问题描述】:如果我用一个例子来解释这可能是最好的......
假设我们在工作表单元格A1:C1
中包含值[1,2,3]
。
我想取每个数字的平方,但我使用单元格公式执行此操作,因此在单元格 A2
中我有 =A1:C1^2
。这是一个数组公式。但是,如果我只在单元格A2
中按ctrl+alt+enter
,我会看到数组的第一个元素平方(i.e. A1^2 = 1^2 = 1)
。
如果我选择所有A2:C2
并点击ctrl+alt+enter
,它会将整个数组公式扩展到三个单元格,我们会看到[1,4,9]
的结果。
我想要的是只需将数组公式放在单元格A2
中并编写 VBA 即可访问整个数组以进行整个操作(即A1:C1^2
)。
我不想在 VBA 中再次执行该函数,因为当我们在单元格 A2
中执行 =A1:C1^2
时,数组必须已经存储在内存中,所以我怎样才能从单个单元格中获取整个数组结果更大数组的一部分?
注意:这只是一个示例,我计划对未知大小的大型数组执行此操作。
【问题讨论】:
那么您想将整个数组存储在一个单元格中然后能够访问它吗?这不是数组公式的工作方式。在您的示例中——实际上只有值 1 存储在A2
中(=SUM(A2)
返回 1,而不是 14——即使您将总和作为数组公式输入)。您可以将值组合成带有一些分隔符的字符串,然后使用 VBA 拆分字符串并提取值,尽管这很少比动态计算值更有效。
您是说希望 VBA 自动填充整个“数组”的公式吗?也就是说,您要开始在 A2 中输入一个公式,然后选择 A1:C1,然后输入您的运算结果为“=A1:C1^2”;然后按 ctrl-shift-enter 使其成为数组公式;那么你想让 VBA 自动填充到 B2 和 C2 中吗?
我认为 =(A1:C1)^2 会返回一个数组,Excel 然后知道这是一个数组,并根据所选区域的大小,输出结果数组的元素.本质上,这是我要问的一个更基本的问题 - 当您告诉 Excel 执行单元格公式时,它是否会计算整个公式,然后根据用户提供的区域确定要打印出多少元素?或者,它只是根据所选区域逐个元素地计算数组吗?
@as9422 好问题。由于数组通常是在循环中计算的,我怀疑 Excel 只计算所需的数组。其他任何事情都是低效的。
@JohnColeman 我是这么认为的 - 听到有点令人沮丧,但我有一半的预期是不可能完全按照我的要求执行。谢谢你的帮助!编辑:虽然 - 你知道是否可以告诉 VBA 不执行同一工作簿中其他人正在调用的函数?这可能是我的问题的一种解决方法(这一切都表明我不想在刷新时执行相同的函数两次)。
【参考方案1】:
Excel 单元格只能包含标量值,因此如果不使用 VBA 中的 EVALUATE 来执行 A2 中的公式,您想要做的事情是不可能的。 而且你需要小心你如何使用 EVALUATE:它有许多特殊的怪癖。
(见我的blog post on EVALUATE)
【讨论】:
Excel 是否只计算数组公式中被选定区域覆盖的部分? 不,AFAIK Excel 计算所有值,因此如果您将公式包装在 SUM 等聚合函数中,它可以聚合所有值。但是单个单元格只有一个位置来保存其他公式可以读取的值。因此,存储公式结果的 Excel 部分会丢弃任何其他值。【参考方案2】:Excel 计算整个数组并显示它所能做的。这是基于用户在数组确认之前选择的单元格。
查尔斯的回答是正确的。如果不使用 Evaluate() 重新计算数组,就无法获取数组,如下所示:
MsgBox Join(Evaluate([a2].Formula))
VBA 确实具有范围对象的 HasArray
属性,在您的示例中,[a2] 是数组公式中的唯一单元格,HasArray
属性将返回 True。
不幸的是,没有对应的GetArray
属性,这正是您所追求的。
我的看法是 Excel 的工作表计算引擎确实将数组保存在内存中,但这是一个单独的结构,形成范围和单元格,VBA 无法访问它。
【讨论】:
我不确定 Excel 会计算整个数组。我使用=rand()
完全填充了 A:J 列,并将它们作为值粘贴到位。然后在 K1 中输入公式=EXP(SIN(COS(SQRT(ABS(TAN(A:J))))))
。计算整个数组将涉及超过 6000 万次函数调用(但 K1 中的值是在几分之一秒内计算出来的
我确信 Excel 进行了优化。你的是一个边缘情况......整个列的一个单元格输出。将确认范围扩大到两个单元格,例如 [K2:K2] 是否需要更长的时间?
我不知道——我删除了那个工作簿,午休时间也快结束了。鉴于 Excel 的闭源性质,这一切都有些投机性。 OP 的问题正是涉及这种“边缘案例”。
有点。一个单元格输出是。多个全栏参考号。由于您无法对其进行测试,因此我可以证明它的速度要慢得多。在许多情况下,如果计算引擎维护数组,它可以极大地提高效率。我的经验让我“猜测”大部分时间它确实如此,除非它认为它太贵了。
我不知道——我只是重复了实验,并用公式=EXP(SIN(COS(SQRT(ABS(TAN(A1:J1048575^2))))))
填充了 K1:T10 范围内的所有 100 个单元格(它停止了整列不足 1 行并投入一个正方形只是为了很好的衡量)并且这 100 个单元格在不到一秒的时间内被填满,尽管计算整个数组需要数十亿次浮点运算。有趣的是,尝试将 =MAX(EXP(SIN(COS(SQRT(ABS(TAN(A1:J1048575^2)))))))
评估为 K1 中的数组公式会给我一个“Excel 资源不足”的错误消息。以上是关于从单个单元格中获取整个数组,该单元格是包含相同数组公式的单元格集合的一部分?的主要内容,如果未能解决你的问题,请参考以下文章
如何在 ag-grid 中的单元格中使用和添加图标以指示该单元格是可编辑的
从 RowDataBound 事件的 gridview 从单元格中获取值