Skip to content

Migración desde openpyxl

Office Oxide lee XLSX 18× más rápido que openpyxl (5,0 ms frente a 94,5 ms de media en 1.802 archivos), con la mayor tasa de éxito de cualquier biblioteca probada. Además lee .xls heredado directamente — algo que openpyxl no puede hacer en absoluto.

Cuándo migrar

Cambia si haces alguna de estas cosas:

  • Leer celdas, filas, hojas o tablas de .xlsx para ingesta / RAG / dashboards
  • Convertir hojas de cálculo a Markdown o HTML
  • Necesitar soporte de .xls sin añadir xlrd (obsoleto desde 2.0) ni invocar LibreOffice
  • Querer procesar también .docx, .pptx o DOC/PPT heredados sin más dependencias
  • Usar EditableDocument para escribir celdas en plantillas

Sigue con openpyxl si:

  • Construyes XLSX complejos desde cero con gráficos, formato condicional, estilos nombrados y tablas dinámicas (openpyxl es la opción Python puro más completa para creación integral)
  • Necesitas evaluación de fórmulas en Python puro

Instalación

pip uninstall openpyxl
pip install office-oxide

Chuleta comparativa

Abrir un libro

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:
    ...

Iterar celdas de una hoja

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)

Para un acceso más rico por celda (tipos, fórmulas, celdas combinadas), baja al módulo 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())

Leer una sola celda

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()

Escribir celdas (plantillas)

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 = primera hoja
    ed.set_cell(0, "B1", 42.5)
    ed.set_cell(0, "C1", True)
    ed.save("filled.xlsx")

sheet_index empieza en cero; cell_ref es notación A1 estándar. Para resolver nombre de hoja → índice, lee el libro una vez y llama a sheets().

Convertir a Markdown / HTML

openpyxl — no incluye nada integrado; tendrías que renderizar las filas a mano.

office_oxide

with Document.open("budget.xlsx") as doc:
    md = doc.to_markdown()    # una sección ## por hoja, tablas GFM

Leer nombres de hojas

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()])

Lectura de .xls heredado

openpyxl no puede abrir .xls. El parche histórico era xlrd, obsoleto desde 2.0 para .xls y sin mantenimiento.

office_oxide

from office_oxide import Document

with Document.open("legacy.xls") as doc:
    print(doc.plain_text())
    doc.save_as("modern.xlsx")    # migración en una línea

Rendimiento

Biblioteca Media p99 Tasa de éxito
office_oxide 5,0 ms 40 ms 97,8 %
python-calamine 13,9 ms 183 ms 96,6 %
openpyxl 94,5 ms 698 ms 96,2 %

Un pipeline de analítica típico que lee 100.000 hojas de cálculo al día: 8 horas y 18 minutos con openpyxl, 26 minutos con office_oxide.

Qué se pierde

EditableDocument.set_cell escribe valores de celda en bruto; no modifica formatos numéricos, formato condicional, gráficos ni rangos nombrados (esas partes se conservan literalmente). Para construir XLSX con estilos completos, usa openpyxl o baja a office_oxide.xlsx::create::XlsxBuilder.

Ver también