Сообщить об ошибке.

Обработка больших файлов XLSX модулем openpyxl в Python

Иногда требуется открыть или записать файлы электронных таблиц XLSX очень большого размера. При чтении или записи таких файлов openpyxl может не справиться с такой нагрузкой. Специально для таких случаев, модуль openpyxl предоставляет два оптимизированных режима работы, которые позволяют считывать и записывать неограниченные объемы данных при (почти) постоянном потреблении памяти.

Содержание:


Режим только для чтения.

В отличие от обычного режима работы, рабочая книга XLSX открытая в режиме только для чтения будет использовать отложенную загрузку, что очень важно для экономии оперативной памяти. При этом, будет использоваться класс ReadOnlyWorksheet, который доступен только в этом режиме.

Важно. Рабочая книга, в таком режиме должна быть явно закрыта с помощью метода Workbook.close().

from openpyxl import load_workbook
# открываем файл только для чтения
wb = load_workbook(filename='big_data.xlsx', read_only=True)
# открываем лист по его имени
ws = wb['Sheet']

for row in ws.rows:
    for cell in row:
        print(cell.value)

# закрываем книгу после прочтения
wb.close()

Ложный объем данных рабочего листа.

Включение режима только для чтения, еще зависит от приложений и библиотек, которые создали файл XLSX, предоставляющий правильную информацию о рабочих листах, в частности об объеме используемой его части. Некоторые приложения устанавливают это неправильно. Можно проверить кажущиеся размеры рабочего листа, используя метод ws.calculate_dimension(). Если вызов этого метода возвращает заранее неверный диапазон, скажем, A1: A1, то простой сброс атрибутов ws.max_row и ws.max_column должен позволить работать с этим файлом в обычном режиме.

Режим только для записи.

Режим только для записи может экспортировать неограниченное количество данных, даже больше, чем может обрабатывать Excel, при этом будет сохраняться использование памяти менее 10 МБ.

В режиме только для записи, снова обычный класс Worksheet будет заменен более быстрой альтернативой WriteOnlyWorksheet. Если нужно сохранить ну совсем очень большие объемы данных, то необходимо дополнительно установить модуль lxml (чтобы процесс сохранения шел быстрее).

>>> from openpyxl import Workbook
# создаем книгу только для записи
>>> wb = Workbook(write_only=True)
>>> ws = wb.create_sheet()
# заполним 1000 строк х 100 столбцов
>>> for i in range(1, 1000):
...     ws.append([f'{i*j}' for j in range(1, 100)])
# сохраним файл
>>> wb.save('big_data.xlsx')

Если требуется записывать ячейки со стилями и/или комментариями, то дополнительно нужно будет импортировать подмодули:

  • openpyxl.cell.WriteOnlyCell(),
  • openpyxl.styles.Font
  • openpyxl.comments.Comment.

Пример:

>>> from openpyxl import Workbook
# создаем книгу только для записи
>>> wb = Workbook(write_only = True)
# импортируем дополнительные подмодули
>>> from openpyxl.cell import WriteOnlyCell
>>> from openpyxl.comments import Comment
>>> from openpyxl.styles import Font
# начинаем работать с листом книги
>>> ws = wb.create_sheet()
>>> cell = WriteOnlyCell(ws, value="Привет, мир!")
>>> cell.font = Font(name='Courier', size=36)
>>> cell.comment = Comment(text="Комментарий", author="Имя автора")
>>> ws.append([cell, 3.14, None])
>>> wb.save('write_only.xlsx')

Код выше создаст рабочую книгу только для записи с одним листом и добавит строку из 3 ячеек: одну текстовую ячейку с пользовательским шрифтом и комментарием, число с плавающей запятой и пустую ячейку (которая все равно не будет записана в итоговый файл).

Предупреждения:

  • В отличие от обычной рабочей книги, созданная рабочая книга в режиме только для записи не содержит активных рабочих листов. Рабочий лист должен быть специально создан с помощью метода .create_sheet().
  • В такую рабочую книгу, строки можно добавлять только с помощью метода .append(). Невозможно записывать (или читать) ячейки в произвольных местах с помощью методов .cell() или .iter_rows().
  • Книгу, созданную в режиме только для записи можно сохранить только один раз. После этого каждая попытка сохранить книгу или вызвать метод .append() к существующему листу вызовет исключение WorkbookAlreadySaved.
  • Все, что появляется в файле перед фактическими данными ячейки, должно быть создано до добавления этих данных в ячейки. Например, изменение свойства .freeze_panes(), позволяющий зафиксировать шапку, должен быть установлен ​​до добавления данных в ячейки.