![](/img/trans.png)
[英]Python - openpyxl - Use openpyxl to get number of rows that contain a specific value
[英]How to use Python to read Excel files that contain extended fonts? (openpyxl error: Max value is 14)
作为 Python 的学习项目,我试图读取目录中的所有 Excel 文件并提取所有工作表的名称。
我一直在尝试几个可用的 Python 模块来执行此操作(在本例中为pandas
),但我遇到了一个问题,其中大部分取决于openpyxl
。
这是我当前的代码:
import os
import pandas
directory_root = 'D:\\testFiles'
# Dict to hold all files, stats
all_files = {}
for _current_path, _dirs_in_path, _files_in_path in os.walk(directory_root):
# Add all files to this `all_files`
for _file in _files_in_path:
# Extract filesystem stats from the file
_stats = os.stat(os.path.join(_current_path, _file))
# Add the full file path and its stats to the `all_files` dict.
all_files[os.path.join(_current_path, _file)] = _stats
# Loop through all found files to extract the sheet names
for _file in all_files:
# Open the workbook
xls = pandas.ExcelFile(_file)
# Loop through all sheets in the workbook
for _sheet in xls.sheet_names():
print(_sheet)
这会在调用pandas.ExcelFile()
时从openpyxl
引发错误: ValueError: Max value is 14
。
根据我在网上可以找到的信息,这是因为该文件包含 14 以上的字体系列。如何在忽略任何现有格式的情况下读取 Excel (xlsx) 文件?
我能找到的唯一可能的解决方案是修改原始文件并删除格式,但这不是一个选项,因为我不想以任何方式修改文件。
还有另一种没有格式限制的方法吗?
通过在 windows 或 grep 中的简单解压缩|查找,很容易检测到家庭值何时超出范围。 因此,您可以根据这些值过滤掉文件。 在这里,我们在 bad boy 示例中看到它们是可以接受的 2 和不可接受的 34
但是,由于所有平台(包括 win 10)都有 TAR,因此最简单的方法是首先将 file.xlsx 扩展为一组并在本机操作系统(或 python)中使用按文件查找,然后确保您确切知道需要调整哪个文件。
所以我们现在知道它是 styles.xml(这并不奇怪,因为字体值应该在那里)
此时我们可以使用字符串替换来更改该条目说
<family val="3"/>
如果这对您的目的更有用。
然后重新打包调整后的 xlsx(注意:最好只使用工具“更新”一个 style.xls 文件以维护 zip 的相对顺序),它的行为应该与具有标准的 standard.xlsx 相同1-14 fonts,假设作者没有引入其他错误。
问题是您的文件不符合 Open Office 规范。 仅允许使用某些字体系列。 一旦openpyxl
遇到不符合规范的字体,它就会抛出这个错误,因为OpenPyxl 只允许符合规范的 excel 文件。
一些 Excel 阅读器可能对此没有问题,并且对不符合 OpenOffice 规范的文件更灵活,但 openpyxl 仅实现 Apache Open Office 规范。
正在解析的 xml 将包含有关字体的信息,如下所示:
<font>
<b/>
<sz val="11"/>
<color rgb="FF000000"/>
<name val="Century Gothic"/>
<family val="34"/>
</font>
如果家庭值超过 14,openpyxl 会抛出这个ValueError
。 Open Office 中有一个底层描述符来控制它。
当其他读者(例如 Microsoft Office 365 Excel)遇到这种情况时,它会在将文件加载为兼容字体(默认为 Calibri)时更改字体系列。
作为一种解决方法,如果您不想更改该值(如 Microsoft Excel 所做的那样),您可以对描述符进行猴子补丁以允许更大的最大字体系列。
# IMPORTANT, you must do this before importing openpyxl
from unittest import mock
# Set max font family value to 100
p = mock.patch('openpyxl.styles.fonts.Font.family.max', new=100)
p.start()
import openpyxl
openpyxl.open('my-bugged-worksheet.xlsx') # this works now!
这可以使用此 excel 工作簿进行复制。 在补丁之前,这将无法加载。 补丁后,它加载没有错误。
这是为我解决此错误的原因。 我编辑了lib\site-packages\openpyxl\descriptors\base.py
并在 class Max 的第86
行之后添加了一个打印语句,如下所示:
def __set__(self, instance, value):
if ((self.allow_none and value is not None)
or not self.allow_none):
value = _convert(self.expected_type, value)
if value > self.max:
print(f"value is {value}")
raise ValueError('Max value is {0}'.format(self.max))
super(Max, self).__set__(instance, value)
这打印出34
的值,明显高于最大值 14。
我所做的只是注释掉raise
错误的行。
将代码更改为:
def __set__(self, instance, value):
if ((self.allow_none and value is not None)
or not self.allow_none):
value = _convert(self.expected_type, value)
if value > self.max:
self.max = value
# print(f"value is {value}")
# raise ValueError('Max value is {0}'.format(self.max))
super(Max, self).__set__(instance, value)
这为我解决了这个问题。
或者,如果您需要分发文件并且必须使用原始库代码,那么请尝试第一个答案。
# IMPORTANT, you must do this before importing openpyxl
from unittest import mock
# Set max font family value to 100
p = mock.patch('openpyxl.styles.fonts.Font.family.max', new=100)
p.start()
import openpyxl
openpyxl.open('my-bugged-worksheet.xlsx') # this works now!
在导入 openpyxl 之前。
如果我是对的,您想从目录中的文件中获取所有 xlsx 工作表名称,以便您可以执行以下操作:
import pandas as pd
import os
dirpth = './Target Folder/'
for dirpath, dirnames, filenames in os.walk(dirpth):
file_names = filenames
file_names = [dirpth+file_names[i] for i in range(len(file_names))]
data = []
sheet_names = []
for names in file_names:
df = pd.ExcelFile(names,engine = 'openpyxl')
data_sheet = []
sheet_temp = []
for name in df.sheet_names:
data_sheet.append(df.parse(nama,index_col = [0]))
sheet_temp.append(name)
data.append(data_sheet)
sheet_names.append(sheet_temp)
这样,您将自动从每个工作表中获取每个 excel 文件的数据,但是如果您在同一文件夹中具有不同扩展名的文件(例如在同一文件夹中您有.csv 文件),则会出现错误。 因此,您需要先过滤所有文件名,或者您可以使用try except
语句跳过非 excel 文件。 如果您的.py 文件与您的文件夹目标路径不同,只需更改 dirpath,例如: 'D:/changeYour Folder Path/Example/Target/'
注意:需要安装openpyxl
这个问题可以通过完全清理 xlsx styles来解决,这是我的代码如何使用pandas
通过openpyxl
https://stackoverflow.com/a/71526058/1731460
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.