我有一个使用多种功能的工作簿。
在一张特定的表格上有大量的计算,这些函数很少需要更新。而在其他工作表上,有一些功能需要在我使用工作簿时进行更新。
工作簿现在速度大大降低,我认为这是因为这张工作表包含工作簿中使用的 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,"!*")
据我了解,OP 要求使用非 VBA 解决方案来进行选择性重新计算,即暂停重新计算整个工作表或单元格范围,直到结果变得相关。虽然这将是一个很好的功能,但我可以看到它为什么会出现问题。电子表格的连贯性存在风险,混合新旧数据,并可能在取消暂停时触发无休止的循环计算。手动计算的现有功能(OP 已知)是提供此类功能的最安全方式。这样,所有数据要么包含旧值,要么包含新值(不允许灰色区域)。
除此之外,OP 有三个选项:
通过引发错误来暂时禁用单元格,即删除名为selectivecalc的命名范围(值为true)并更改这样的函数=if(selectivecalc,原始单元格函数)
将“暂停”数据移动到另一个工作簿并链接回原始数据。虽然此工作簿处于打开状态,但更改应该是自动的。当它关闭时,它应该被暂停。我认为!我不确定当两个工作簿相互链接时会发生什么,或者当您在只打开一个工作簿的情况下点击全部刷新时会发生什么。
尝试优化现有函数的计算,考虑到 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 单元格触发了本地重新计算。您已经可以通过仅比较此字符串的第一个字符来加快速度:
单个单元格更改可能会立即触发其中一些 COUNTIF。如果您能想出一种方法将其简化为二进制比较和求和(而不是文本),那么您就会飞起来。
此外,“另存为”>“另存为类型”>“Excel 二进制工作簿 *.xlsb”可能会有所帮助,至少可以减少保存和加载时间。
我不是 100% 确定这会起作用并且很难测试,但是如果链接到同一页面上的布尔单元格,您可以尝试将您的函数包装在一个附加中。我想知道计算是否只会在您更改布尔单元格时更新?
例如我测试了这个:
复制了 10,000 个单元格并在命名表中使用了简单的数字,这一切都运行得太快了,我无法确定当我更改链接页面上的单元格时是否存在差异。我想知道这个公式是否只会在 C1 单元格更改为 1 时评估它的大部分。再次很难确定。
我还认为这个讨论可能会为您提供某种形式的解决方案: Excel function that evaluate a string as if it is an formula?
但无法解决它,你可能有一些运气。这个想法是使用评估指向您的公式字符串,然后可以使用响应 2 中概述的技巧将其设置为易失性或非易失性。