927437a8d8
Sistema FleetView para centralizar la flota de procesos Claude Code vivos en una sola ventana kitty + tmux (socket aislado -L fleet) con un panel TUI: - list_claude_fleet (+ tipo claude_fleet): escanea ~/.claude/sessions + goals + runtime, valida procesos vivos (anti-PID-reciclado), join por sessionId. - list_resumable_claudes (+ tipo resumable_claude): sesiones cerradas reanudables. - wrappers tmux: tmux_new_claude_window (con --resume), tmux_swap_window_into_console (preserva ancho del sidebar), tmux_map_claude_panes. - launch_kittyclaude: comando entrypoint; instala atajos alt+flechas/enter/n/0/k/r, mouse on, remain-on-exit off; fija el ancho del sidebar con hooks. - docs/capabilities/claude-fleet.md + entrada en el INDEX. Incluye ademas funciones datascience en progreso (excel/duckdb/postgres) y ajustes varios de docs e infra de otra sesion, agrupados aqui para no perderlos. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
5.4 KiB
5.4 KiB
Capability: excel
CRUD de hojas de cálculo Excel (.xlsx) desde el registry con openpyxl: escribir libros multi-hoja, actualizar una hoja sin destruir las demás (preservando columnas editadas a mano), leer a estructuras en memoria o a markdown, añadir gráficos nativos, e ingerir una hoja a DuckDB.
Es el extremo Excel del stack de datos Excel → DuckDB → Postgres → visualización: el Excel sirve como entrada (lo que produce un humano o un export) y como entregable (un libro con gráficos que viaja por email/disco, sin servidor). El round-trip humano lo cubre upsert_xlsx_sheet, que conserva las columnas que las personas rellenan a mano mientras regenera las columnas calculadas.
Funciones
| ID | Firma | Que hace |
|---|---|---|
write_xlsx_sheets_py_infra |
write_xlsx_sheets(out_path, sheets, header_bold=True, autofit=True, freeze_header=True) -> str |
Escribe (o sobrescribe) un libro .xlsx multi-hoja desde un dict {nombre_hoja: datos}. Cada hoja acepta list[list] (primera fila = headers) o {"headers": [...], "rows": [[...]]}. Cabecera en negrita, auto-ancho, freeze de cabecera. Devuelve la ruta absoluta. |
upsert_xlsx_sheet_py_infra |
upsert_xlsx_sheet(xlsx_path, sheet_name, records, columns, key_col="", preserve_cols=None, formulas=None, backup=True, ...) -> dict |
Actualiza NO destructivamente UNA hoja: reescribe solo sheet_name y conserva las demás. Antes de limpiar, lee por key_col las columnas de trabajo manual (preserve_cols) y las reescribe ganando sobre los datos nuevos. Cabecera estilizada, freeze, autofilter, fórmulas por columna, backup .bak. |
read_xlsx_py_infra |
read_xlsx(path, sheet=None, max_rows=None, header=True) -> dict |
Lee un .xlsx a memoria (NO a markdown). Devuelve {status, sheets: {nombre: {headers, rows}}}. sheet=None lee todas. Tipos de celda: fechas→ISO, int/float, bool, None, fórmulas (valor calculado, data_only=True). Espejo en lectura de write_xlsx_sheets. |
excel_to_markdown_py_core |
excel_to_markdown(path, max_rows_per_sheet=1000) -> str |
Convierte .xlsx/.xls/.xlsm a markdown, cada hoja como sección H2. Para inspección rápida / pegar en un prompt o nota. |
add_xlsx_chart_py_infra |
add_xlsx_chart(xlsx_path, sheet_name, chart_type, data_range, cats_range=None, anchor='H2', title='', x_title='', y_title='') -> dict |
Añade un gráfico nativo (bar/line/pie/scatter) a una hoja EXISTENTE, refiriendo rangos de celdas ya escritos (notación Excel 'C1:C7'). anchor = celda destino. La pieza para generar hojas Excel CON gráficos. |
excel_to_duckdb_py_infra |
excel_to_duckdb(xlsx_path, duckdb_path, table, sheet=None, mode='replace') -> dict |
Ingesta una hoja del .xlsx a una tabla DuckDB con la extensión nativa excel de DuckDB. Puente Excel→DuckDB. También etiquetada en el grupo duckdb. |
Ejemplo canónico
Escribir un libro, añadirle un gráfico y releerlo a memoria (verificado):
cd /home/enmanuel/fn_registry
python/.venv/bin/python3 - <<'PYEOF'
import sys
sys.path.insert(0, "python/functions")
from infra import write_xlsx_sheets, add_xlsx_chart, read_xlsx
xlsx = "/tmp/ventas.xlsx"
write_xlsx_sheets(xlsx, {"ventas": [
["mes", "categoria", "importe"],
["2026-01", "neumaticos", 12500.50],
["2026-02", "neumaticos", 15800.75],
["2026-03", "neumaticos", 18200.00],
]})
# Gráfico de barras del importe por mes, anclado en la celda G2
add_xlsx_chart(xlsx, "ventas", "bar", data_range="C1:C4", cats_range="A2:A4",
anchor="G2", title="Importe por mes", y_title="EUR")
rd = read_xlsx(xlsx, sheet="ventas")
print(rd["sheets"]["ventas"]["headers"], len(rd["sheets"]["ventas"]["rows"]))
PYEOF
Gotchas del grupo
- openpyxl no evalúa fórmulas.
read_xlsxcondata_only=Truedevuelve el valor cacheado por la última app que guardó el libro (Excel/LibreOffice). Un.xlsxcon fórmulas escritas por openpyxl y nunca abierto en una hoja de cálculo devuelveNoneen esas celdas. add_xlsx_chartexige libro y hoja existentes: no crea el.xlsxni escribe datos; los rangos deben apuntar a celdas ya escritas. Flujo:write_xlsx_sheets→add_xlsx_chart.- Rangos 1-indexed, notación Excel (
'C1:C7'). Sidata_rangeincluye la fila de cabecera, el nombre de la serie sale de esa celda (titles_from_data).scatterusadata_rangecomo Y ycats_rangecomo X;pieignora los títulos de eje. - Carga en memoria: openpyxl carga el libro entero; para libros muy grandes considera ingerir a DuckDB (
excel_to_duckdb) y consultar allí. upsert_xlsx_sheetes la vía para datos editados por humanos: si una persona rellena columnas a mano, pásalas enpreserve_colspara que un re-volcado no las pise.
Fronteras
- NO es una herramienta de BI ni de dashboards. Para visualización interactiva/compartida: Metabase, Evidence (sobre DuckDB) o gráficos embebidos con
add_xlsx_chartpara el caso "todo en el .xlsx". - El análisis pesado (agregaciones, joins, histórico) NO se hace en Excel: ingiere a DuckDB con
excel_to_duckdby usa el grupoduckdb. - NO cubre
.csvde entrada con encodings legacy — eso essafe_read_csv_fallback_py_core.
Relación con otros grupos
duckdb—excel_to_duckdbes el puente de entrada; el motor analítico vive allí.postgres— la salida hacia BI pasa porduckdb_to_postgres(grupoduckdb/postgres).metabase— consume los datos una vez en Postgres.