205 lines
7.3 KiB
Python
205 lines
7.3 KiB
Python
import os
|
|
import curses
|
|
import pandas as pd
|
|
import numpy as np
|
|
from colorama import init, Fore, Style
|
|
|
|
from helpers import CabColumna, ListaCabColumnas
|
|
|
|
# Inicializa colorama
|
|
init(autoreset=True)
|
|
|
|
def limpiar_pantalla():
|
|
os.system('cls' if os.name == 'nt' else 'clear')
|
|
|
|
def seleccionar_archivo_curses(stdscr):
|
|
curses.curs_set(0) # Ocultar cursor
|
|
archivos = [f for f in os.listdir() if f.lower().endswith(('.xls', '.xlsx'))]
|
|
if not archivos:
|
|
stdscr.addstr(0, 0, "No se encontraron archivos .xls o .xlsx en el directorio actual.")
|
|
stdscr.getch()
|
|
return None
|
|
|
|
seleccion = 0
|
|
|
|
while True:
|
|
stdscr.clear()
|
|
stdscr.addstr(0, 0, "Selecciona un archivo Excel (.xls, .xlsx):\n\n")
|
|
|
|
for idx, archivo in enumerate(archivos):
|
|
if idx == seleccion:
|
|
stdscr.addstr(idx + 2, 0, f"> {archivo}", curses.A_REVERSE)
|
|
else:
|
|
stdscr.addstr(idx + 2, 0, f" {archivo}")
|
|
|
|
stdscr.addstr(len(archivos) + 3, 0, "Usa ↑↓ para moverte, Enter para seleccionar, q para salir.")
|
|
|
|
tecla = stdscr.getch()
|
|
|
|
if tecla == curses.KEY_UP and seleccion > 0:
|
|
seleccion -= 1
|
|
elif tecla == curses.KEY_DOWN and seleccion < len(archivos) - 1:
|
|
seleccion += 1
|
|
elif tecla == ord('q'):
|
|
return None
|
|
elif tecla == 10: # Enter
|
|
return os.path.abspath(archivos[seleccion])
|
|
|
|
def seleccionar_archivo():
|
|
return curses.wrapper(seleccionar_archivo_curses)
|
|
|
|
memoria_combinaciones = {}
|
|
def elegir_combinacion(strtemp):
|
|
combinaciones = []
|
|
|
|
if len(strtemp) == 3:
|
|
combinaciones = [
|
|
(' '.join(strtemp[:1]), ' '.join(strtemp[1:])),
|
|
(' '.join(strtemp[:2]), strtemp[2])
|
|
]
|
|
elif len(strtemp) == 4:
|
|
combinaciones = [
|
|
(' '.join(strtemp[:1]), ' '.join(strtemp[1:])),
|
|
(' '.join(strtemp[:2]), ' '.join(strtemp[2:])),
|
|
(' '.join(strtemp[:3]), strtemp[3])
|
|
]
|
|
else:
|
|
return strtemp
|
|
|
|
claves_posibles = [parte1 for parte1, parte2 in combinaciones]
|
|
|
|
for i, clave in enumerate(claves_posibles):
|
|
if clave in memoria_combinaciones:
|
|
return (clave, memoria_combinaciones[clave])
|
|
|
|
# Mostrar menú al usuario
|
|
print("\nSe detectaron múltiples líneas. Elige cómo dividirlas:")
|
|
for i, (parte1, parte2) in enumerate(combinaciones):
|
|
print(f"{i+1}) Parte 1: \"{parte1}\" | Parte 2: \"{parte2}\"")
|
|
|
|
while True:
|
|
opcion = input("Introduce el número de la opción deseada: ").strip()
|
|
if opcion.isdigit() and 1 <= int(opcion) <= len(combinaciones):
|
|
seleccion = combinaciones[int(opcion) - 1]
|
|
clave_general = seleccion[0] # Solo recordamos la parte 1
|
|
memoria_combinaciones[clave_general] = seleccion[1] # Guardamos parte 2 asociada
|
|
return seleccion
|
|
else:
|
|
print("Opción inválida. Intenta de nuevo.")
|
|
|
|
def parsear_documento(archivo):
|
|
print("\n>>> Parsear documento")
|
|
print(f"Parseando archivo: {archivo} ...")
|
|
|
|
df = pd.read_excel(archivo, engine='openpyxl', header=None)
|
|
df = df.replace(r'^\s*$', np.nan, regex=True)
|
|
df = df.dropna(how='all').dropna(axis=1,how='all')
|
|
|
|
lista_cab_columnas=ListaCabColumnas()
|
|
lista_cab_columnas.importar('cabs.json')
|
|
|
|
cabeceras = []
|
|
ministerio = ''
|
|
for cabecera in lista_cab_columnas.lista:
|
|
if cabecera.nombre_cabecera!="": #
|
|
cabecera.indice=df.columns[df.apply(lambda col: col.astype(str).str.contains(cabecera.nombre_cabecera)).any()].tolist()[0]
|
|
cabeceras.extend(list(map(str, cabecera.campos)))
|
|
df_parseado=pd.DataFrame(columns=cabeceras)
|
|
|
|
for index, row in df.iterrows():
|
|
valor_celda = row.iloc[0]
|
|
if isinstance(valor_celda, str) and lista_cab_columnas.lista[0].nombre_cabecera not in valor_celda:
|
|
row=row.dropna()
|
|
ministerio = ' '.join(row.astype(str))
|
|
elif isinstance(valor_celda, str) and lista_cab_columnas.lista[0].nombre_cabecera in valor_celda:
|
|
continue
|
|
else:
|
|
fila_index = len(df_parseado)
|
|
for cabecera in lista_cab_columnas.lista:
|
|
if cabecera.nombre_cabecera!="": #
|
|
if len(cabecera.campos)>1:
|
|
strtemp = row[cabecera.indice].split('\n')
|
|
if len(strtemp) in (3, 4):
|
|
strtemp = elegir_combinacion(strtemp)
|
|
else:
|
|
strtemp = [' '.join(strtemp[:-1]), strtemp[-1]]
|
|
|
|
for i, campo in enumerate(cabecera.campos):
|
|
valor = strtemp[i] if i < len(strtemp) else ""
|
|
df_parseado.at[fila_index, campo] = valor
|
|
else:
|
|
df_parseado.at[fila_index,cabecera.campos[0]] = str(row[cabecera.indice]).replace('\n',' ')
|
|
else:
|
|
df_parseado.at[fila_index,cabecera.campos[0]] = ministerio
|
|
input("\nPresiona Enter para continuar...")
|
|
return df_parseado
|
|
|
|
def exportar_a_excel(documento_parseado):
|
|
print("\n>>> Exportar a Excel")
|
|
try:
|
|
documento_parseado.to_excel('DestinosParseados.xlsx', index=False)
|
|
print("Documento exportado a Excel.")
|
|
except Exception as e:
|
|
print(f"Error al exportar: {e}")
|
|
input("\nPresiona Enter para continuar...")
|
|
|
|
def mostrar_menu(archivo, documento_parseado):
|
|
print("=== Menú Principal ===\n")
|
|
|
|
print("1) Seleccionar archivo")
|
|
|
|
if archivo:
|
|
print(f"2) Parsear documento {Fore.GREEN}{os.path.basename(archivo)}{Fore.RESET}")
|
|
else:
|
|
print(Fore.LIGHTBLACK_EX + "2) Parsear documento [desactivado]")
|
|
|
|
if archivo and documento_parseado is not None and not documento_parseado.empty:
|
|
print("3) Exportar a Excel")
|
|
else:
|
|
print(Fore.LIGHTBLACK_EX + "3) Exportar a Excel [desactivado]")
|
|
|
|
print("0) Salir")
|
|
|
|
def main():
|
|
archivo = None
|
|
archivoParser = None
|
|
documento_parseado = None
|
|
while True:
|
|
limpiar_pantalla()
|
|
mostrar_menu(archivo, documento_parseado)
|
|
opcion = input("\nSeleccione una opción: ").strip()
|
|
|
|
if opcion == "1":
|
|
archivo = seleccionar_archivo()
|
|
if archivo:
|
|
print(f"\nArchivo seleccionado: {archivo}")
|
|
else:
|
|
print("\nNo se seleccionó ningún archivo.")
|
|
documento_parseado = None
|
|
|
|
elif opcion == "2":
|
|
if not archivo:
|
|
print(Fore.RED + "Opción desactivada: debes seleccionar un archivo primero.")
|
|
else:
|
|
documento_parseado = parsear_documento(archivo)
|
|
|
|
elif opcion == "3":
|
|
if not archivo:
|
|
print(Fore.RED + "Opción desactivada: primero selecciona un archivo.")
|
|
elif documento_parseado is None or documento_parseado.empty:
|
|
print(Fore.RED + "Opción desactivada: debes parsear el archivo antes de exportar.")
|
|
else:
|
|
exportar_a_excel(documento_parseado)
|
|
|
|
elif opcion == "0":
|
|
print("\nSaliendo del programa...")
|
|
break
|
|
|
|
else:
|
|
print(Fore.RED + "Opción no válida.")
|
|
input("\nPresiona Enter para continuar...")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|