Creación, edición y análisis de XLSX
| Tarea | Enfoque |
|---|---|
| Crear o editar con fórmulas/formato | openpyxl — ver advertencias abajo |
| Datos masivos de entrada o salida | pandas (read_excel, to_excel) |
| Vistazo rápido a una hoja | markitdown archivo.xlsx — ## NombreHoja por hoja; también lee .xlsm. Sin coordenadas de celda, así que no planees ediciones a partir de él |
| Leer un modelo (fórmulas y valores) | dos pases de load_workbook — ver advertencias |
openpyxl,pandasymarkitdownestán preinstalados — no ejecutespip installprimero; escribe el script e importa directamente. Solo si una importación falla (o el comandomarkitdownno se encuentra):pip installel paquete faltante.
Las rutas de los scripts a continuación son relativas al directorio de esta habilidad.
Requisitos para cada salida
- Fuente profesional (Arial, Times New Roman) en todo el documento, a menos que el usuario indique lo contrario.
- Cero errores de fórmula. Nunca entregues mientras
recalc.pyreporteerrors_found. Si crees que un error existía antes de tu intervención, demuéstralo: carga el archivo original condata_only=Truey revisa esa celda. Un error que introdujiste se ve exactamente igual que uno heredado. - Usa fórmulas, nunca resultados codificados. Escribe
sheet['B10'] = '=SUM(B2:B9)', no el total calculado en Python. La hoja debe recalcularse cuando sus entradas cambien. - Sigue las especificaciones del usuario al pie de la letra. Nombres exactos de pestañas, encabezados de columna exactos y la fórmula que indicó. Un rediseño que calcule algo diferente falla, por más elegante que sea.
- Documenta cada suposición y número codificado donde el lector pueda verlo: un comentario de celda, o una celda adyacente al final de una tabla. Cita una fuente real cuando exista (
Fuente: Informe 10-K de la empresa, Año Fiscal 2024, Página 45, Nota de Ingresos, [URL SEC EDGAR]); cuando el número provino del usuario, dilo claramente. - Un libro de trabajo que crees para que alguien lo complete necesita una leyenda corta que indique qué celdas editar, y una fila de ejemplo con valores realistas que muestre el formato esperado. Nunca agregues esa fila a un archivo que te pidieron editar.
- Editar un archivo existente: respeta sus convenciones exactamente. Estas anulan cualquier directriz aquí. Encuentra primero sus celdas de entrada designadas — un color de fuente, relleno o sombreado distinto las marca — escribe solo allí, y deja intacta cada fórmula existente.
Recalcular (obligatorio siempre que el archivo contenga fórmulas)
openpyxl escribe fórmulas como cadenas sin valores almacenados en caché. Hasta que recalculas, cada celda de fórmula se lee como None para cualquier cosa que lea valores en caché — pandas, load_workbook(data_only=True) y la mayoría de los previsualizadores.
python scripts/recalc.py salida.xlsx [tiempo_limite_segundos] # predeterminado 30
LibreOffice calcula cada fórmula, el archivo se reescribe en el mismo lugar y obtienes JSON: status (success | errors_found), total_formulas, total_errors y un error_summary que nombra hasta 100 celdas por tipo de error (locations_truncated indica cuántas omitió — confía en total_errors, no en la longitud de la lista). Corrige lo que nombra y ejecútalo de nuevo. JSON con una clave error en lugar de status significa que no se recalculó nada, y solo ese caso sale con código distinto de cero — errors_found sale con 0, así que nunca trates una salida limpia como un libro de trabajo limpio.
Un recálculo exitoso demuestra que tus fórmulas se evalúan, no que sean correctas. Un rango desplazado por uno o una referencia a la fila incorrecta produce un archivo limpio y sin errores pero con números incorrectos. Escribe 2–3 fórmulas primero y verifica que obtengan los valores esperados, antes de construir una cuadrícula completa.
Un libro de trabajo que enlaza a otro archivo pierde esos enlaces si lo vuelves a guardar con openpyxl y luego recalculas. Una fórmula así se lee como ='[1]Returns Analysis'!$B$2 — el [1] es un índice en la lista de referencias externas del libro, que nombra un archivo separado en el disco, no una hoja. Ese archivo rara vez está presente aquí, así que el valor en caché de la celda es lo único que mantiene sus datos. openpyxl elimina ese valor al guardar; luego LibreOffice tiene que resolver la referencia realmente, falla, escribe #NAME? y elimina todos los enlaces. recalc.py se niega a ejecutarse en ese estado — copia los valores de esas celdas desde el original antes de guardar sobre ellas (--force anula y acepta la pérdida).
Elegir fórmulas que sobrevivan a la verificación
LibreOffice implementa menos funciones que Excel, y una que no puede evaluar se convierte en un literal #NAME? integrado en el archivo que entregas.
- Prefiere funciones de la era de Excel 2007 —
SUMIFS,INDEX,MATCH,IFERROR,SUMPRODUCT— que no necesitan prefijo. - Seis funciones posteriores a 2007 funcionan, pero solo con un prefijo
_xlfn., porque openpyxl escribe tu fórmula en XML textualmente y Excel almacena los nombres posteriores a 2007 con prefijo (su interfaz oculta el prefijo):_xlfn.TEXTJOIN,_xlfn.CONCAT,_xlfn.IFS,_xlfn.SWITCH,_xlfn.MAXIFS,_xlfn.MINIFS. Escritas sin prefijo, cada una produce#NAME?. - Nunca uses
XLOOKUP,XMATCH,SORT,FILTER,UNIQUEoSEQUENCE. El runtime de LibreOffice no puede evaluarlas bajo ningún prefijo. Las versiones más nuevas sí las evalúan, pero son funciones de matriz derramada y un archivo escrito por openpyxl no tiene metadatos de derrame, por lo que solo la celda superior izquierda del rango recibe un valor — yrecalc.pyreportatotal_errors: 0sobre el resultado truncado. UsaINDEX/MATCHpara búsquedas, y ordena, filtra y elimina duplicados en Python antes de escribir las celdas. - Una fórmula que LibreOffice no pudo analizar se escribe de vuelta en minúsculas — una pista rápida junto a un
#NAME?.
Advertencias de openpyxl
- Leer un modelo requiere dos cargas.
data_only=Trueproduce valores en caché sin las fórmulas; el valor predeterminado produce cadenas de fórmula sin valores. Un solo pase no puede darte ambos. data_only=Truees destructivo si guardas. Ese libro de trabajo ya no tiene fórmulas, por lo que guardar reemplaza cada una con un literal — permanentemente.data_only=Trueen un archivo que openpyxl acaba de escribir devuelveNoneen todas partes — ejecutarecalc.pyprimero. (Una fórmula cuyo resultado es""también se lee comoNone).- Celdas combinadas: escribe solo el ancla superior izquierda. Cada otra celda en el rango es un
MergedCellcuyo.valuees de solo lectura. .xlsmpierde sus macros a menos que paseskeep_vba=Trueaload_workbook.- Un nombre de hoja que contenga un espacio debe estar entre comillas en una referencia entre hojas:
='Inputs de Supuestos'!$B$5. Sin comillas, se evalúa como#VALUE!.
Modelos financieros
A menos que el usuario indique lo contrario, o el archivo existente ya haga algo diferente.
Color: texto azul (0,0,255) para entradas codificadas y palancas de escenario · negro para fórmulas · verde (0,128,0) para enlaces a otra hoja · rojo (255,0,0) para enlaces a otro archivo · relleno amarillo (255,255,0) para supuestos clave y celdas que el usuario debe completar.
Números: moneda $#,##0, con la unidad nombrada en el encabezado (Ingresos ($mm)) · ceros se muestran como -, incluso en porcentajes ($#,##0;($#,##0);-) · negativos entre paréntesis · porcentajes 0.0%, almacenados como fracciones (0.15 muestra 15.0%; almacenar 15 muestra 1500.0%) · múltiplos de valoración 0.0x · años como texto ("2024", nunca 2,024).
Estructura: cada supuesto en su propia celda etiquetada, referenciado por las fórmulas que lo usan (=B5*(1+$B$6), nunca =B5*1.05) · fórmulas consistentes en cada período de proyección, ya que una celda editada solitaria en medio de una fila es el error silencioso más común · protege denominadores que pueden ser cero.
Dependencias
openpyxl, pandas, markitdown (pip, preinstalados — instala solo si una importación falla o el comando no se encuentra) · LibreOffice (soffice, configurado automáticamente para entornos aislados mediante scripts/office/soffice.py)