OpenpyXL - 如何 return 任何给定工作簿的单元格的计算和公式组件

OpenpyXL - How to return BOTH the calculated and formula components of a cell for any given workbook

在工作中我们使用Excel文档对样本进行分析,工作簿中的一项工作sheet是'Top Sheet',其中整理了数据的所有重要部分变成一个不错的 table 报告。我写了一个详尽的 python 脚本,它使用 OpenPyXL 提取所有必要的数据,这样我就可以从多个文件中提取这些数据。所有这些都需要在打开工作簿时实施 data_only=True 标志。

但是 - 我现在需要从工作簿的另一部分提取数据,另一个 sheet(不是顶部 sheet),实际上在 [=32= 的公式中引用了它].我通过本质上让脚本打开工作簿两次来笨拙地实现这一点 - 一次拉出所有顶部 sheet 数据,一次拉出公式(实际上是一系列单元格引用)。

wb_value = load_workbook(os.path.join(root, fname), data_only=True)

wb_formula = load_workbook(os.path.join(root, fname))

在 OpenPyXL 中有什么方法可以 return 数据和公式而无需重新打开?这实际上使执行提取循环所需的时间加倍,正如我上面提到的,这是一个更大结构的一部分,该结构循环遍历整个目录以查找 suitable .xlsx 文件。

非常感谢任何帮助。

PS。我读过 Charlie Clark 对问题 23350581 的回答,所以我对有一个简单的解决方案并不乐观,但希望有人能想出一个解决方法。

PPS。我无法对要提取的单元格引用进行硬编码,因为随着时间的推移,它们已经发生变化,并且有人已经对 Excel 进行硬编码以跟踪位置(多年)。

干杯

修改openpyxl的代码即可。请注意,我在 openpyxl 2.2.5 上进行了这些更改,这不是最新版本。因此,您的行号可能会有所不同。

这是一个快速的猴子补丁,很可能不是最好的方法,但它应该能让你继续。

请注意,如果您修改公式(如查理克拉克在他的回答中所说),这些更改不会使 openpyxl 重新计算值。这只会导致 load_workbook 检索单元格的值和公式,而不需要调用它两次。


\openpyxl\cell\cell.py:

第 84 行:

'formula'添加到__slots__:

 __slots__ =  (
        'column',
        'row',
        'coordinate',
        '_value',
        'formula',      
        'data_type',
        'parent',
        'xf_index',
        '_hyperlink_rel',
        '_comment')


第 111 行: 更改 Cell__init__ 以接受具有默认参数 None:

formula arg
def __init__(self, worksheet, column, row, value=None, formula=None, fontId=0,
                 fillId=0, borderId=0, alignmentId=0, protectionId=0, numFmtId=0,
                 pivotButton=None, quotePrefix=None, xfId=None):

并在__init__正文中初始化:

self.formula = formula


\openpyxl\reader\worksheet.py

第 111 行:

我们不再关心 data_only,所以将行从 if formula is not None and not self.data_only: 更改为 if formula is not None:

第 113 - 116 行:

更改以下行
if formula.text:
    value = "=" + formula.text
else:
    value = "="

if formula.text:
    _formula = "=" + formula.text
else:
    _formula = "="

您应该看到这些行下面的几行

else:
    cell._value=value
    cell.data_type=data_type

在这些行的正下方添加:

try:
    cell.formula = _formula
except UnboundLocalError:
    pass



就是这样!让我们测试一下:

我创建了一个新的 xlsx 文件。单元格 A1 有公式 =1+1 而单元格 A2 没有公式,只有 2.

的普通值
wb = load_workbook('test.xlsx')
sheet = wb.get_sheet_by_name('Sheet1')

cell = sheet.cell(row=1, column=1)
print(cell.value)
print(cell.formula)

>> 2
>> =1+1

cell = sheet.cell(row=2, column=1)
print(cell.value)
print(cell.formula)

>> 2
>> None

请注意,无论传递给 open_workbookdata_only 的值如何,这都会起作用。