import pandas as pd import os import re import logging import PyLibrary.funciones_comunes as fc from openpyxl.utils.escape import unescape from openpyxl import load_workbook from openpyxl.styles import Font from openpyxl.comments import Comment def update_from_master(tipo_PLC, codigo_columna_maestra, archivo_maestro, archivo_to_update, target_lang_code): if not os.path.exists(archivo_maestro): print("El archivo maestro no existe.") return # Configurar el logger logger = fc.configurar_logger() logger.info(" .... ") logger.info( f"Iniciando actualización en {archivo_to_update} desde el archivo maestro. Para {target_lang_code} " ) df_maestro = fc.read_dataframe_with_cleanup_retries(archivo_maestro) df_to_update = fc.read_dataframe_with_cleanup_retries(archivo_to_update) col_clave = codigo_columna_maestra # Diccionario para almacenar las celdas con errores en el archivo maestro celdas_con_errores = {} # Iterar sobre las filas del archivo de actualización para actualizarlas for index, fila in df_to_update.iterrows(): valor_original = fila[col_clave] clave = fc.compactar_celda_clave(tipo_PLC, valor_original) logger.info( f'Fila {index} : Clave: {clave}' ) if not pd.isnull(clave) and clave in df_maestro[col_clave].values: # Obtenemos los valores indice_maestro = df_maestro.index[df_maestro[col_clave] == clave].tolist()[0] valor_traducido_compacto = df_maestro.loc[indice_maestro, target_lang_code] # Descompactamos valor_traducido = fc.decompactar_celda_traducida(tipo_PLC, celda_original=valor_original, celda_traducida=valor_traducido_compacto ) if ( not pd.isnull(valor_traducido) and fila[target_lang_code] != valor_traducido ): # Verificamos si la traducción es válida okToSave, Error = fc.verificar_celda_traducida(tipo_PLC, clave, valor_traducido_compacto ) if okToSave: logger.info("Actualizado.") df_to_update.at[index, target_lang_code] = valor_traducido else: df_to_update.at[index, target_lang_code] = valor_original logger.error( f'No actualizado porque: {Error}' ) # Almacenar la celda con error para marcarla en rojo más tarde en el archivo maestro celdas_con_errores[indice_maestro] = Error # Guardar el archivo actualizado nombre, extension = os.path.splitext(archivo_to_update) nuevo_nombre = f"{nombre}_import{extension}" fc.save_dataframe_with_retries(df_to_update, output_path=nuevo_nombre) # Marcar celdas con errores en rojo en el archivo maestro marcar_celdas_con_errores(archivo_maestro, celdas_con_errores, target_lang_code) print( f"Se han actualizado las filas en {archivo_to_update} desde el archivo maestro. " f"Se han marcado {len(celdas_con_errores)} celdas con errores en el archivo maestro." ) logger.info( f"Se han actualizado las filas en {archivo_to_update} desde el archivo maestro. " f"Se han marcado {len(celdas_con_errores)} celdas con errores en el archivo maestro." ) logger.info(" .... ") def marcar_celdas_con_errores(archivo_maestro, celdas_con_errores, target_lang_code): """ Marca las celdas con errores en rojo en el archivo maestro Excel. :param archivo_maestro: Ruta del archivo maestro Excel. :param celdas_con_errores: Diccionario con las celdas a marcar {indice_maestro: mensaje_error}. :param target_lang_code: Código del idioma objetivo. """ workbook = load_workbook(archivo_maestro) sheet = workbook.active # Encontrar la columna del idioma objetivo for col in range(1, sheet.max_column + 1): if sheet.cell(row=1, column=col).value == target_lang_code: target_col = col break else: print(f"No se encontró la columna para el idioma {target_lang_code}") return # Marcar celdas con errores for indice_maestro, mensaje_error in celdas_con_errores.items(): row = indice_maestro + 2 # +2 porque Excel empieza en 1 y tiene encabezados cell = sheet.cell(row=row, column=target_col) cell.font = Font(color="FF0000") # Texto en rojo # Añadir un comentario con el mensaje de error comment = Comment(mensaje_error, "Sistema de Traducción") cell.comment = comment workbook.save(archivo_maestro) print(f"Se han marcado {len(celdas_con_errores)} celdas con errores en rojo en el archivo maestro {archivo_maestro}") def run(tipo_PLC, codigo_columna_maestra, seleccion_idioma): archivo_maestro = f".\\data\\1_hmi_master_translates_{tipo_PLC}.xlsx" archivo_to_update = fc.select_file("xlsx") if archivo_to_update: if seleccion_idioma not in fc.IDIOMAS: print("Selección inválida.") else: _, target_lang_code = fc.IDIOMAS[seleccion_idioma] update_from_master(tipo_PLC, codigo_columna_maestra, archivo_maestro, archivo_to_update, target_lang_code) if __name__ == "__main__": tipo_PLC = "siemens" codigo_columna_maestra = "it-IT" fc.mostrar_idiomas() seleccion_idioma = int(input("Introduce el número del idioma de destino: ")) run(tipo_PLC, codigo_columna_maestra, seleccion_idioma)