不打开Excel表格如何计算(使用openpyxl或xlwt)

17

我编写了一个脚本,打开一个 .xls 文件,在其中写入一些新的数值,然后保存该文件。

稍后,脚本再次打开该文件,并想要在某些包含公式的单元格中找到答案。

如果使用 openpyxl 调用该单元格,会得到公式(例如:"=A1*B1")。 而如果激活 data_only,则什么也不会得到。

有没有办法让 Python 计算 .xls 文件?(或者应该尝试 PyXll?)

6个回答

8
我知道这个问题很旧了,但是我遇到了同样的问题,广泛地搜索没有找到答案。
事实上,解决方法非常简单,所以我在此发布它以供后人参考。
假设您有一个已用openpyxl修改过的xlsx文件。如Charlie Clark所提到的,openpyxl不会计算公式,但是如果您在excel中打开该文件,则公式将自动计算。因此,您所需要做的就是打开文件,然后使用excel保存它。
要做到这一点,您可以使用win32com模块。
import win32com.client as win32

excel = win32.gencache.EnsureDispatch('Excel.Application')
workbook = excel.Workbooks.Open(r'absolute/path/to/your/file')
# this must be the absolute path (r'C:/abc/def/ghi')
workbook.Save()
workbook.Close()
excel.Quit()

就是这样。我看到了使用Pycel或Koala的建议,但如果你只需要告诉Excel打开和保存文件,那似乎有点过度杀伤力。

当然,这个解决方案仅适用于Windows。


3
问题的核心,正如主题所述,是不要使用Excel打开文件。建议使用Pycel或Koala并非“过度解决”,它们是必需的以满足要求。你的解决方案不仅特定于Windows,而且需要Excel。有些人使用Windows,但没有Excel。尽管你的解决方案最终被提问者采用了(请参见2014年我回答的第二条评论),如果你可以使用Excel,那么它肯定是一个合理的选择。 - John Y

8

实际上有一个项目可以使用Python来评估Excel公式:Pycel。Pycel使用Excel本身(通过COM)来提取公式,因此在您的情况下,您可以跳过该部分。该项目可能有一些有用的东西,但我不能保证其成熟度或完整性。它实际上并不是为普通大众开发的

还有一个名为Koala的新项目,它建立在Pycel和OpenPyXL的基础之上。

如果您无法使用Excel,但是可以在Python代码中计算公式的结果,则另一种方法是将值和公式都写入单元格中(这样当您读取文件时,只需提取值,而不必担心公式)。截至本文撰写时,我还没有找到在OpenPyXL中实现它的方法,但XlsxWriter可以实现。来自文档
XlsxWriter不计算公式的值,而是将0作为公式结果存储。然后,在XLSX文件中设置全局标志,表示在打开文件时应重新计算所有公式和函数。这是Excel文档中推荐的方法,在电子表格应用程序中通常效果良好。但是,没有计算公式的工具(如Excel Viewer或某些移动应用程序)仅显示0结果。

如果需要,也可以使用选项值参数指定公式的计算结果。这在与不计算公式值的非Excel应用程序一起使用时偶尔是必要的。计算出的值添加到参数列表末尾:

worksheet.write_formula('A1', '=2+2', num_format, 4)

使用此方法时,当读取值时,可以使用OpenPyXL的data_only选项。(对于其他人阅读此答案:如果您使用xlrd,则只有值可用。)

最后,如果您Excel,则可能最简单可靠的方法是自动打开并在Excel中重新保存文件(以便它会为您计算和编写公式的值)。xlwings是从Windows或Mac轻松完成此操作的方法。


谢谢,我会查看Pycel,它看起来有点像我现在的解决方案。 - Frtschaal
当前的解决方案:使用openpyxl生成文件,然后在Excel中使用win32com简要打开文件,保存并关闭工作簿。虽然不太美观,但它能够正常工作。我还在研究“spreadscript”,一种计算引擎。不幸的是,您的第二个建议行不通,因为Excel表格非常复杂。 - Frtschaal
值得一提的是,当前版本的 Pycel 已经不需要 Excel 来解析 xlsx 文件了。尽管对于2010年以后的格式仍然适用独立的解析方式。 - Mr. Girgitt
如果您选择使用打开-保存-关闭的方法,请记住需要将计算设置为自动,否则需要显式触发计算。 - MJB

7

这个公式模块对我很有用。详细信息请参见https://pypi.org/project/formulas/

from openpyxl import load_workbook
import formulas

#The variable spreadsheet provides the full path with filename to the excel spreadsheet with unevaluated formulae
fpath = path.basename(spreadsheet) 
dirname = path.dirname(spreadsheet)
xl_model = formulas.ExcelModel().loads(fpath).finish()
xl_model.calculate()
xl_model.write(dirpath=dirname)
#Use openpyxl to open the updated excel spreadsheet now
wb = load_workbook(filename=spreadsheet,data_only=True)
ws = wb.active

1
这将创建一个新文件,其中公式被替换为值。可能有用,但感觉有点丑陋。 - embe
2
好的,保留公式的机会在那里,他只是写了一个简单的例子。 - Alex R

3
我遇到了同样的问题,经过一段时间的研究后,我最终使用了pyoo (https://pypi.org/project/pyoo/),它适用于openoffice/libreoffice,因此在所有平台上都可用,并且更加直观,因为它可以本地通信,不需要保存/关闭文件。我尝试了几个其他库,但发现存在以下问题:
  • xlswings:仅在安装了Excel和Windows/MacOS的情况下才能工作,因此我无法评估
  • Koala:似乎已经损坏,在networkx 2.4更新后。
  • openpyxl:正如其他人指出的那样,它无法计算公式,因此我正在考虑将其与pycel结合使用以获取值。最终我没有尝试,因为我找到了pyoo。由于pycel也依赖于networkx库,因此现在可能无法使用Openpyxl+pycel。

1
不会的,在openpyxl中也永远不会有。我认为有一个Python库声称可以实现这些公式的引擎,你可以使用它。

那将是理想的,你知道那个库的名称吗? - Frtschaal
根据以下特性请求,有一个名为PyCel的库。由于我从未使用过,因此无法发表更多意见。 - Charlie Clark
看起来很有前途,我会深入研究的!谢谢!我还发现了一个名为“spreadscript”的东西,它只在Linux上运行,但也很有前途。 - Frtschaal

1

xlcalculator可以完成这个任务。https://github.com/bradbase/xlcalculator

from xlcalculator import ModelCompiler
from xlcalculator import Model
from xlcalculator import Evaluator

filename = r'use_case_01.xlsm'
compiler = ModelCompiler()
new_model = compiler.read_and_parse_archive(filename)
evaluator = Evaluator(new_model)

# First!A2
# value is 0.1
#
# Fourth!A2
# formula is =SUM(First!A2+1)

val1 = evaluator.evaluate('Fourth!A2')
print("value 'evaluated' for Fourth!A2:", val1)

evaluator.set_cell_value('First!A2', 88)
# now First!A2 value is 88
val2 = evaluator.evaluate('Fourth!A2')
print("New value for Fourth!A2 is", val2)

这将产生以下输出;
file_name use_case_01.xlsm ignore_sheets []
value 'evaluated' for Fourth!A2: 1.1
New value for Fourth!A2 is 89

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接