我制作了一个脚本,它打开一个 .xls 文件,在其中写入一些新值,然后保存文件。
稍后,脚本再次打开它,并希望在某些包含公式的单元格中找到答案。
如果我用 openpyxl 调用该单元格,我会得到公式(即:)"=A1*B1"
。如果我激活data_only
,我什么也得不到。
有没有办法让 Python 计算 .xls 文件?(或者我应该尝试 PyXll 吗?)
我意识到这个问题很老,但是我遇到了同样的问题并且广泛的搜索没有产生答案。
解决方案实际上非常简单,因此我将在此处发布以供后代使用。
假设您有一个用 .xlsx 修改过的 xlsx 文件openpyxl
。正如查理克拉克所说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。
实际上有一个项目采用 Excel 公式并使用 Python 评估它们: 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 执行此操作的简单方法。
公式模块对我有用。详情请参考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
我遇到了同样的问题,经过一段时间的研究,我最终使用了 pyoo ( https://pypi.org/project/pyoo/ ),它适用于 openoffice/libreoffice,因此可在所有平台上使用,并且更直接,因为可以本地通信并且不需要保存/关闭文件。我尝试了其他几个库,但发现了以下问题
不,openpyxl
永远不会有。我认为有一个 Python 库旨在为您可以使用的这种公式实现一个引擎。
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