ParamManagerScripts/backend/script_groups/S7_DB_Utils/x6.py

163 lines
6.6 KiB
Python

# --- x6_refactored.py ---
import json
from typing import List, Dict, Any
import openpyxl
from openpyxl.utils import get_column_letter
import sys
import os
import glob
script_root = os.path.dirname(
os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
)
sys.path.append(script_root)
from backend.script_utils import load_configuration
# Importar funciones comunes desde x3
from x3 import flatten_db_structure, format_address_for_display
from x4 import format_data_type_for_source
def find_working_directory():
configs = load_configuration()
working_directory = configs.get("working_directory")
if not working_directory:
print("No working directory specified in the configuration file.")
sys.exit(1)
return working_directory
def generate_excel_table(db_info: Dict[str, Any], excel_filename: str):
"""
Genera un archivo Excel con documentación del DB usando flatten_db_structure.
"""
workbook = openpyxl.Workbook()
sheet = workbook.active
db_name_safe = db_info['name'].replace('"', '').replace(' ', '_').replace('/','_')
sheet.title = f"DB_{db_name_safe}"[:31] # Sheet names tienen límite de longitud
# Definir encabezados
headers = ["Address", "Name", "Type", "Size (Bytes)", "Bit Size", "Initial Value", "Actual Value", "Comment"]
for col_num, header in enumerate(headers, 1):
cell = sheet.cell(row=1, column=col_num, value=header)
cell.font = openpyxl.styles.Font(bold=True)
# Usar flatten_db_structure importado de x3
flat_vars = flatten_db_structure(db_info)
# Poblar filas con los datos
for row_num, var in enumerate(flat_vars, 2):
# Columna 1: Address
address = var.get("address_display", format_address_for_display(var["byte_offset"], var.get("bit_size", 0)))
sheet.cell(row=row_num, column=1, value=address)
# Columna 2: Name
sheet.cell(row=row_num, column=2, value=var["full_path"])
# Columna 3: Type
data_type = format_data_type_for_source(var)
sheet.cell(row=row_num, column=3, value=data_type)
# Columna 4: Size (Bytes)
sheet.cell(row=row_num, column=4, value=var.get("size_in_bytes", 0))
# Columna 5: Bit Size
sheet.cell(row=row_num, column=5, value=var.get("bit_size", 0) if var.get("bit_size", 0) > 0 else None)
# Columna 6: Initial Value
sheet.cell(row=row_num, column=6, value=var.get("initial_value", ""))
# Columna 7: Actual Value
sheet.cell(row=row_num, column=7, value=var.get("current_value", ""))
# Columna 8: Comment
sheet.cell(row=row_num, column=8, value=var.get("comment", ""))
# Crear una segunda hoja para el bloque BEGIN
begin_sheet = workbook.create_sheet(title="BEGIN_Values")
begin_headers = ["Address", "Path", "Value"]
for col_num, header in enumerate(begin_headers, 1):
cell = begin_sheet.cell(row=1, column=col_num, value=header)
cell.font = openpyxl.styles.Font(bold=True)
# Filtrar solo variables con valores actuales para la hoja BEGIN
vars_with_values = [var for var in flat_vars if var.get("current_value") is not None]
# Poblar la hoja BEGIN
for row_num, var in enumerate(vars_with_values, 2):
# Columna 1: Address
begin_sheet.cell(row=row_num, column=1, value=var.get("address_display"))
# Columna 2: Path
begin_sheet.cell(row=row_num, column=2, value=var["full_path"])
# Columna 3: Value
value_str = str(var["current_value"])
if value_str.lower() == "true": value_str = "TRUE"
elif value_str.lower() == "false": value_str = "FALSE"
begin_sheet.cell(row=row_num, column=3, value=value_str)
# Auto-ajustar columnas para mejor legibilidad
for sheet in workbook.worksheets:
for col_idx, column_cells in enumerate(sheet.columns, 1):
max_length = 0
column = get_column_letter(col_idx)
for cell in column_cells:
try:
if len(str(cell.value)) > max_length:
max_length = len(str(cell.value))
except:
pass
adjusted_width = min(max_length + 2, 100) # Limitar a 100 para anchos extremos
sheet.column_dimensions[column].width = adjusted_width
try:
workbook.save(excel_filename)
print(f"Excel documentation generated: {excel_filename}")
except Exception as e:
print(f"Error writing Excel file {excel_filename}: {e}")
def main():
working_dir = find_working_directory()
print(f"Using working directory: {working_dir}")
input_json_dir = os.path.join(working_dir, "json")
documentation_dir = os.path.join(working_dir, "documentation")
os.makedirs(documentation_dir, exist_ok=True)
print(f"Los archivos Excel de documentación se guardarán en: {documentation_dir}")
json_files_to_process = glob.glob(os.path.join(input_json_dir, "*.json"))
if not json_files_to_process:
print(f"No se encontraron archivos .json en {input_json_dir}")
return
print(f"Archivos JSON encontrados para procesar: {len(json_files_to_process)}")
for json_input_filepath in json_files_to_process:
current_json_filename = os.path.basename(json_input_filepath)
print(f"\n--- Procesando archivo JSON para Excel: {current_json_filename} ---")
try:
with open(json_input_filepath, 'r', encoding='utf-8') as f:
data_from_json = json.load(f)
print(f"Archivo JSON '{current_json_filename}' cargado correctamente.")
except Exception as e:
print(f"Error al cargar/leer {current_json_filename}: {e}")
continue
if data_from_json.get("dbs"):
for db_to_document in data_from_json["dbs"]:
excel_output_filename = os.path.join(documentation_dir, f"{current_json_filename}_{db_to_document['name'].replace('"', '')}.xlsx")
print(f"Generando documentación Excel para DB: '{db_to_document['name']}' (desde {current_json_filename}) -> {excel_output_filename}")
try:
generate_excel_table(db_to_document, excel_output_filename)
except Exception as e_excel:
print(f"Error al generar Excel para DB '{db_to_document['name']}': {e_excel}")
else:
print(f"No se encontraron DBs en el archivo JSON '{current_json_filename}' para generar documentación Excel.")
print("\n--- Proceso de generación de documentación Excel completado ---")
if __name__ == "__main__":
main()