Skip to content

Миграция с openpyxl

Office Oxide читает XLSX в 18 раз быстрее openpyxl (5,0 мс против 94,5 мс в среднем на 1 802 файлах), с самой высокой долей успешных разборов среди протестированных библиотек. Он также читает устаревший .xls напрямую — чего openpyxl не умеет вообще.

Когда мигрировать

Переходите, если вы делаете что-либо из этого:

  • Читаете ячейки, строки, листы или таблицы из .xlsx для ingestion / RAG / дашбордов
  • Конвертируете таблицы в Markdown или HTML
  • Нужна поддержка .xls без добавления xlrd (устарел с версии 2.0) или запуска LibreOffice
  • Хотите обрабатывать также .docx, .pptx или устаревшие DOC/PPT без дополнительных зависимостей
  • Используете EditableDocument для записи ячеек в шаблонах

Останьтесь на openpyxl, если:

  • Вы собираете сложные XLSX с нуля, с графиками, условным форматированием, именованными стилями и сводными таблицами (openpyxl — самый богатый вариант на чистом Python для полнофункционального создания)
  • Вам нужна оценка формул на чистом Python

Установка

pip uninstall openpyxl
pip install office-oxide

Сравнительная шпаргалка

Открытие рабочей книги

openpyxl

from openpyxl import load_workbook

wb = load_workbook("budget.xlsx", data_only=True)

office_oxide

from office_oxide import Document

with Document.open("budget.xlsx") as doc:
    ...

Итерация по ячейкам листа

openpyxl

from openpyxl import load_workbook

wb = load_workbook("budget.xlsx", data_only=True)
for sheet in wb.worksheets:
    for row in sheet.iter_rows(values_only=True):
        print(row)

office_oxide

from office_oxide import Document

with Document.open("budget.xlsx") as doc:
    ir = doc.to_ir()

for section in ir["sections"]:
    print(f"# {section.get('title')}")
    for el in section["elements"]:
        if el["kind"] == "Table":
            for row in el["rows"]:
                print(row)

Для более богатого доступа по ячейкам (типы, формулы, объединённые ячейки) спускайтесь в модуль XLSX:

with Document.open("budget.xlsx") as doc:
    xlsx = doc.as_xlsx()
    for sheet in xlsx.sheets():
        for cell in sheet.cells():
            print(cell.address(), cell.value(), cell.value_type())

Чтение одной ячейки

openpyxl

wb = load_workbook("budget.xlsx", data_only=True)
sheet = wb["Q4"]
val = sheet["B5"].value

office_oxide

with Document.open("budget.xlsx") as doc:
    val = doc.as_xlsx().sheet("Q4").cell("B5").value()

Запись ячеек (шаблонизация)

openpyxl

from openpyxl import load_workbook

wb = load_workbook("template.xlsx")
ws = wb["Summary"]
ws["A1"] = "Total"
ws["B1"] = 42.5
ws["C1"] = True
wb.save("filled.xlsx")

office_oxide

from office_oxide import EditableDocument

with EditableDocument.open("template.xlsx") as ed:
    ed.set_cell(0, "A1", "Total")    # sheet 0 = первый лист
    ed.set_cell(0, "B1", 42.5)
    ed.set_cell(0, "C1", True)
    ed.save("filled.xlsx")

sheet_index отсчитывается с нуля; cell_ref — стандартная нотация A1. Чтобы получить индекс листа по имени, один раз прочитайте рабочую книгу и вызовите sheets().

Конвертация в Markdown / HTML

openpyxl — нет встроенной; строки пришлось бы рендерить самому.

office_oxide

with Document.open("budget.xlsx") as doc:
    md = doc.to_markdown()    # один раздел ## на лист, GFM-таблицы

Чтение имён листов

openpyxl

wb = load_workbook("budget.xlsx")
print(wb.sheetnames)

office_oxide

with Document.open("budget.xlsx") as doc:
    print([s.name() for s in doc.as_xlsx().sheets()])

Чтение устаревшего .xls

openpyxl не умеет открывать .xls. Исторический обходной путь — xlrd, с версии 2.0 поддержка .xls признана устаревшей, пакет больше не сопровождается.

office_oxide

from office_oxide import Document

with Document.open("legacy.xls") as doc:
    print(doc.plain_text())
    doc.save_as("modern.xlsx")    # миграция в одну строку

Производительность

Библиотека Среднее p99 Доля успеха
office_oxide 5,0 мс 40 мс 97,8%
python-calamine 13,9 мс 183 мс 96,6%
openpyxl 94,5 мс 698 мс 96,2%

Типичный аналитический конвейер, читающий 100 000 таблиц в день: 8 часов 18 минут на openpyxl, 26 минут на office_oxide.

Что теряется

EditableDocument.set_cell пишет сырые значения ячеек; он не меняет числовые форматы, условное форматирование, графики или именованные диапазоны (эти части сохраняются дословно). Для сборки XLSX с полной стилизацией используйте openpyxl или спускайтесь в office_oxide.xlsx::create::XlsxBuilder.

См. также