【问题标题】:Set xlsx to recalculate formulae on open设置 xlsx 以在打开时重新计算公式
【发布时间】:2020-08-10 18:39:42
【问题描述】:

我正在生成 xlsx 文件,并且希望在此过程中不必计算所有公式的值。 也就是说,对于带有<f> 的单元格,我想将<v> 设置为0(或省略它),并让Excel 在打开时填写这些值。

一个建议是在启动时运行Calculate 的宏,但一直无法找到完整的指南,说明如何使用已签名的宏执行此操作以避免提示用户。您可以在 xlsx 中的某处设置一个标志会好得多。

编辑:我不是在寻找涉及使用 Office 程序进行更改的答案。我正在寻找文件格式的详细信息。

【问题讨论】:

  • 如果没有宏,您将无法完成您所追求的那种动态行为。 Excel 公式/单元格总是相同的(是静态的),如果您想考虑可变行为,您将不得不依赖宏(或其他类型的应用程序)。
  • @varocarbas 您能否提供完整的答案,详细说明如何实现这一目标?
  • 当然。但是如果你想把宏放在同一个文件中,你必须把它转换成 xlsm;如果目标计算机中的 Excel 安全设置告诉您,还会出现提示(“您要启用宏吗?”)。你还想要吗?
  • <v><f> 是什么意思?您使用什么过程来“生成” xlsx 文件?
  • @LS_dev 用 7zip 打开一个 xlsx,自己看看。我正在以编程方式直接创建文件格式。

标签: openxml xlsx


【解决方案1】:

Python 模块XlsxWriterxl/workbook.xml 文件中将公式<v> 的值设置为0(除非实际值已知),并将<calcPr>fullCalcOnLoad 属性设置为true:

<calcPr fullCalcOnLoad="1"/>

这适用于我测试过的所有 Excel 和 OpenOffice、LibreOffice、Google Docs 和 Gnumeric 版本。

不适用于无法重新计算公式值的非电子表格应用程序,例如文件查看器。

【讨论】:

  • 对 Python 的引用几乎让我无法理解这个答案的价值。我通过使用 PHP preg_replace 将现有标记 Calcpr 设置为 fullCalcOnLoad="1" 解决了这个问题
  • 使用 Excel Online 和 LibreOffice 对此进行了测试,但仅适用于前者。
【解决方案2】:

如果计算模式设置为自动,Excel 总是(重新)计算打开的工作簿。

所以,只需生成计算模式设置为“自动”的文件。

xl/workbook.xml 中,将以下节点添加到工作簿节点:

<calcPr calcMode="auto"/>

同时检查Description of how Excel determines the current mode of calculation

您可以按照建议使用宏,但是您将创建一个不太安全且兼容性较差的工作簿,而不会避免用户交互来强制计算。

如果您选择使用 VBA,您可以在Workbook_Open 事件中Application.Calculate

【讨论】:

  • 按照链接的说明,以自动和手动模式保存的文件是相同的。以防万一,我更改了自动模式文件中计算单元格的值,打开时它们没有重新计算。
  • “我更改了自动模式文件中计算单元格的值”?您必须生成计算模式设置为自动的工作簿。是工作簿属性,而不是单元格!
  • 我将单元格的值更改为不是公式的结果。
  • 这似乎是 xls 文件的属性,而不是 xlsx。
  • xls 文件不是 Office Open XML。不是msdn.microsoft.com/en-us/library/…吗?
【解决方案3】:

在您的 XML 内容中,只需在每个具有公式的单元格中省略 &lt;v&gt; 实体,这将迫使 Excel 女士实现公式,无论 Excel 选项是什么。

代替:

  <c r="B2" s="1">
    <f>SUM(A1:C1)</f>
    <v>6</v>
  </c>

有:

  <c r="B2" s="1">
    <f>SUM(A1:C1)</f>
  </c>

如果您必须在已经给定的 XML 内容中实现公式,那么您可以轻松编写一个小型解析器来搜索每个 &lt;c&gt; 实体。如果&lt;c&gt; 实体有&lt;f&gt; 实体,则删除其&lt;v&gt; 实体。

【讨论】:

  • 这在我看来是个好主意。但是我测试过,如果计算模式没有设置为自动,打开工作簿时B2显示为空。
  • 此外,Google 文档过去常常拒绝没有设置 &lt;v&gt; 值的 Excel 文件。因此,一般情况下最好设置一些值,即使它是 0。
【解决方案4】:

在通过 openxml 导出 xlsx'es 时遇到同样的问题(使用最快的 SAX + 模板文件方法,没有 zip 流倒带)。

尽管计算选项=自动,打开文件时不会重新计算。 此外,无需通过“立即计算”和“计算工作表”按钮重新计算。 仅在选择单元格并按 Enter 时;(

原始公式:SUM(A3:A999)

解决方案:

  1. 创建内部隐藏工作表
  2. 将结束行号(在我的情况下为 999)放入隐藏工作表中的任何单元格(在我的情况下为 P1)
  3. 通过 INDIRECT 运算符引用单元格中的行号

最终公式:SUM(A3:INDIRECT("A"&Internal!P1))

请参考附件中的 gifs

before.gif

after.gif

附言

理论上,在 P1 中,您可以通过类似 =LOOKUP(2;1/(Sheet1!A:A"");ROW(Sheet1!A:A)) 的方式实现动态行数计算,但我的客户是对硬编码行号解决方案感到满意

【讨论】:

  • 这“有效”只是因为您将公式设为易失性(间接强制单元格被视为易失性)。因此,只要工作簿中任何事情发生更改,就会重新计算您的公式。请注意,更简单的解决方案是将您的公式更改为 SUM(A3:A999)+0*RAND() 这也会使公式不稳定,但不需要隐藏表。
猜你喜欢
  • 2012-07-31
  • 1970-01-01
  • 2020-02-24
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
  • 1970-01-01
  • 2021-06-05
  • 1970-01-01
相关资源
最近更新 更多