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_workbook
的 data_only
的值如何,这都会起作用。
在工作中我们使用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_workbook
的 data_only
的值如何,这都会起作用。