在 Excel 中,您可以在单元格中编写函数并规定只能手动计算

在 Excel 中,您可以在单元格中编写函数并规定只能手动计算

我有一个使用多个函数的工作簿。

在某个特定工作表上,计算量非常大,但这些函数很少需要更新。而在其他工作表上,当我使用工作簿时,有些函数需要更新。

工作簿现在速度变得非常慢,我认为这是因为这张工作表包含了工作簿中使用的 90% 的函数。

我是否可以在单元格中编写一个函数,以便 Excel 知道仅当我手动触发计算时才需要重新计算它?

我知道我可以在 VBA 中轻松地做到这一点,但在这种情况下,有一种情况阻止我使用 VBA。

示例函数:

=IF('Prd Clt Ind'!B11574<>'Dev Clt Ind'!B11574,"! P " &'Prd Clt Ind'!B11574 & " D " & 'Dev Clt Ind'!B11574, 'Dev Clt Ind'!B11574)

=COUNTIF(A11574:AN11574,"!*")

答案1

据我了解,原作者要求使用非 VBA 解决方案进行选择性重新计算,即暂停重新计算整个工作表或单元格范围,直到结果变得相关。虽然这是一个不错的功能,但我明白它为什么会有问题。电子表格的一致性存在风险,混合新旧数据,并可能在取消暂停时触发无休止的循环计算。现有的手动计算功能(原作者知道)是提供此类功能的最安全方法。这样,所有数据要么包含旧值,要么所有内容都有新值(不允许灰色区域)。

除此之外,OP还有三个选择:

  1. 通过引发错误来暂时禁用单元格,即删除名为 selectedcalc 的命名范围(值为 true)并更改如下函数 =if(selectivecalc, original cell function)

  2. 将“暂停”的数据移动到另一个工作簿并链接回原始工作簿。当此工作簿打开时,更改应该是自动的。当它关闭时,它应该暂停。我想!我不确定当两个工作簿相互链接时会发生什么,或者当您只打开一个工作簿时点击全部刷新时会发生什么。

  3. 尝试优化现有函数的计算,同时考虑 Excel 自动重新计算的工作原理及其触发时间。本文的其余部分专门介绍此优化。

@Scott 的一些评论暗示了这一点。Excel 为每个单元格构建一个依赖关系树,并且仅在其父节点更改/重新计算时才重新计算单元格。例如,假设 A1 = 1、B1 = A1*100 和 C1 = LOG(SQRT(SIN(-4)*PI()^3))。虽然 C1 是 CPU 密集型的,但它仅依赖于自身,并且只有在用户编辑时才会重新计算。B1 依赖于 A1,如果 A1 发生变化,它将自动计算。现在,如果 C1 = LOG(SQRT(SIN(-4)*PI()^3))*RAND(),就会出现问题,因为 C1 会在每次其他单元格更改时重新计算,因为 RAND() 是不稳定的。在这种情况下,明智的做法是保持 C1 原样,并定义 D1 = C1 * RAND()。CPU 密集型的 C1 不会重新计算,但会将其常量值提供给 D1 进行不稳定的重新计算。

现在具体到您的情况,您的 IF 函数本身并不太慢,包含文本比较,并且仅依赖于其他两个单元格(称为 IND 单元格)。这两个单元格中的任何一个发生更改都会触发重新计算此本地 IF 和文本比较。输出是 TEXT,这不是很好,期待。

我假设的 countif 公式正在计算第一个 IF 公式的 TRUE 情况的数量。它必须进行 40 次文本通配符比较 - 即使这 40 个单元格中只有一个单元格的 IND 单元格触发了本地重新计算。您可以通过仅比较此字符串的第一个字符来加快速度:

=SUM((LEFT(A11574:AN11574)="!")+0)      ...type in cell, press CTRL+SHIFT+ENTER (array formula)

可能有几个 COUNTIF 是由单个单元格更改同时触发的。如果您能想出一种方法将其简化为二进制比较和求和(而不是文本),那么您将飞起来。

此外,“另存为”>“保存类型”>“Excel 二进制工作簿 *.xlsb”可能会有所帮助,至少可以减少保存和加载时间。

答案2

我不能 100% 确定这会起作用,而且很难测试,但您可以尝试将您的函数包装在附加 if 中,并将其链接到同一页面上的布尔单元格。我想知道计算是否只会在您更改布尔单元格时更新?

例如我测试了这个:

=IF($C$1 = 1, IF(INDIRECT("'Prd Clt Ind'!B" & ROW())<>INDIRECT("'Dev Clt Ind'!B" & ROW()),"! P " &INDIRECT("'Prd Clt Ind'!B" & ROW()) & " D " & INDIRECT("'Dev Clt Ind'!B" & ROW()), INDIRECT("'Dev Clt Ind'!B" & ROW())),"")

复制了 10,000 个单元格,并在命名工作表中使用简单的数字,一切都运行得太快了,以至于我无法确定在更改链接页面上的单元格时是否存在差异。我想知道这个公式是否只会在 C1 单元格更改为 1 时才计算大部分内容。同样很难确定。

我还认为这次讨论可能会为您提供某种形式的解决方案: Excel 函数是否可以像公式一样对字符串进行求值?

但无法解决,你可能运气不错。想法是使用评估指向公式的字符串,然后可以使用响应 2 中概述的技巧将其变为易变的或非易变的。

相关内容