Openpyxl: 'ValueError: Максимальное значение равно 14' при использовании load_workbook
Я попытался открыть файл Excel, в который мне нужно вставить кадры данных на определенные листы, оставив другие листы в покое. Скрипт работает отлично, когда я тестировал его на других файлах Excel. Когда я использую его на том, что мне действительно нужно, я получаю сообщение об ошибке.
Вот сценарий:
from openpyxl import load_workbook
book = load_workbook(self.directory)
Self.directory ссылается на мое местоположение файла. Как вы можете видеть в трассировке, она завершается с ошибкой уже в этой строке при попытке выполнить load_workbook() и выдает следующее сообщение об ошибке:
ValueError: максимальное значение 14
Вот соответствующая трассировка (я оставил каталоги, начиная с папки виртуальной среды "virtual"):
"""
book = load_workbook(self.directory)
virtual\lib\site-packages\openpyxl\reader\excel.py", line 217, in load_workbook
shared_strings = read_string_table(archive.read(strings_path))
virtual\lib\site-packages\openpyxl\reader\strings.py", line 22, in read_string_table
text = Text.from_tree(node).content
virtual\lib\site-packages\openpyxl\descriptors\serialisable.py", line 84, in from_tree
obj = desc.expected_type.from_tree(el)
virtual\lib\site-packages\openpyxl\descriptors\serialisable.py", line 84, in from_tree
obj = desc.expected_type.from_tree(el)
virtual\lib\site-packages\openpyxl\styles\fonts.py", line 110, in from_tree
return super(Font, cls).from_tree(node)
virtual\lib\site-packages\openpyxl\descriptors\serialisable.py", line 100, in from_tree
return cls(**attrib)
virtual\lib\site-packages\openpyxl\cell\text.py", line 114, in __init__
self.family = family
virtual\lib\site-packages\openpyxl\descriptors\nested.py", line 36, in __set__ 6, in __set__
super(Nested, self).__set__(instance, value)
virtual\lib\site-packages\openpyxl\descriptors\base.py", line 110, in __set__ , in __set__
super(Min, self).__set__(instance, value)
virtual\lib\site-packages\openpyxl\descriptors\base.py", line 89, in __set__ in __set__
raise ValueError('Max value is {0}'.format(self.max))
ValueError: Max value is 14
"""
Я понял, что файл Excel, который я использовал, превысил предел self.max.
Я попытался самостоятельно просмотреть сценарии openpyxl, но мне не удалось выяснить, что относится к self.max или как я могу изменить свой файл Excel, чтобы загрузить книгу.
Кто-нибудь может указать мне правильное направление?
Заранее спасибо!
11 ответов
Для использования Pandas - как полностью очистить стили XLSX
который исправит все ошибки стиля, такие как
'ValueError: Max value is 14'
1. Добавьте свой собственный движок XLSX для панд в один из ваших файлов init .py, который загружается автоматически .
from openpyxl.reader.excel import ExcelReader
from openpyxl.xml import constants as openpyxl_xml_constants
from pandas import ExcelFile
from pandas.io.excel._openpyxl import OpenpyxlReader
class OpenpyxlReaderWOFormatting(OpenpyxlReader):
"""OpenpyxlReader without reading formatting
- this will decrease number of errors and speedup process
error example https://stackoverflow.com/q/66499849/1731460 """
def load_workbook(self, filepath_or_buffer):
"""Same as original but with custom archive reader"""
reader = ExcelReader(filepath_or_buffer, read_only=True, data_only=True, keep_links=False)
reader.archive.read = self.read_exclude_styles(reader.archive)
reader.read()
return reader.wb
def read_exclude_styles(self, archive):
"""skips addings styles to xlsx workbook , like they were absent
see logic in openpyxl.styles.stylesheet.apply_stylesheet """
orig_read = archive.read
def new_read(name, pwd=None):
if name == openpyxl_xml_constants.ARC_STYLE:
raise KeyError
else:
return orig_read(name, pwd=pwd)
return new_read
ExcelFile._engines['openpyxl_wo_formatting'] = OpenpyxlReaderWOFormatting
print('Monkey patching pandas XLS engines. See OpenpyxlReaderWOFormatting')
2. Используйте его, укажите engine='openpyxl_wo_formatting' при чтении файла XLSX.
import pandas as pd
df = pd.read_excel(filepath, engine='openpyxl_wo_formatting')
Вот что исправило эту ошибку для меня. Я отредактировал lib\site-packages\openpyxl\descriptors\base.py и добавил оператор печати после строки 86 в классе Max следующим образом:
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 (это значение семейства шрифтов).
Затем я сохранил копию своей электронной таблицы Excel с расширением.zip, извлек все файлы XML и затем использовал grep для поиска val="34". Это привело меня к трем ячейкам, в которых каким-то образом было font-family=34. Я изменил шрифт на другой в Excel, сохранил электронную таблицу, затем изменил ее на исходный шрифт (Arial) и сохранил.
После всего этого ошибка исчезла.
Мне пришлось удалить все форматирование на листе, с которым я работал.
В Libreoffice; выбрать все, "очистить прямое форматирование"
Вместо исправления
__set__
метод, вы можете исправить максимальное значение конкретного дескриптора.
# 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!
Если вы исправите
descriptors\base.py
вы будете разрешать потенциально неверные значения для всех дескрипторов. Этот подход является более хирургическим, поскольку он исправляет только дескриптор семейства шрифтов, вызывающий ошибку.
Это файл Excel, созданный WPS, но не MS office.
- вы можете использовать xlwings, чтобы открыть его.
- вы можете сохранить в файл CSV вручную и прочитать.
Проблема решена, если вы подавите / закомментируете исключение, как показано ниже в openpyxl:
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=self.max
#raise ValueError('Max value is {0}'.format(self.max))
super(Max, self).__set__(instance, value)
Это устранило проблему, и теперь я могу использовать
pd.read_excel(io.BytesIO(obj['Body'].read()), engine='openpyxl', sheet_name=[0], header=None)
Я смог обойти ошибку после удаления 15-го + маленьких "полей для комментариев" на листе.
Эта ошибка появится, если в книге более 14 файлов. Итак, попробуйте вставить содержимое Excel в новый файл, а затем попробуйте загрузить его. Это решило мою проблему. Надеюсь, это решит и вашу.
Количество комментариев в штучной упаковке не решило мою проблему. Мне пришлось удалить некоторые листы, пока я не получил менее 14 листов, чтобы открыть / прочитать документ.
У меня была такая же проблема — неподдерживаемый шрифт в файле.
Я просто открыл файл в MS Excel, сбросил шрифты на базовый Arial и сохранил новый файл. И Openpyxl принял новый файл.
Просто закомментируйте строку кода в openpyxl, которая вызывает ошибку.