"""Validierung von Input-Dateien und Templates.""" from pathlib import Path from typing import Optional from openpyxl import load_workbook from openpyxl.utils import column_index_from_string from .models import FieldSchema, OutputMapping, ValidationResult def validate_input_file( filepath: Path, schema: list[FieldSchema], ) -> ValidationResult: """ Validiert eine Input-Datei: - Datei existiert - Erwartete Spalten sind vorhanden (Header in Zeile 1) - Mindestens ein Daten-Sheet enthält Daten """ errors: list[str] = [] warnings: list[str] = [] info: dict = {} if not filepath.exists(): errors.append(f"Input-Datei nicht gefunden: {filepath}") return ValidationResult(is_valid=False, errors=errors) try: wb = load_workbook(filepath, data_only=True) except Exception as e: errors.append(f"Datei konnte nicht geöffnet werden: {e}") return ValidationResult(is_valid=False, errors=errors) sheet_count = len(wb.sheetnames) info["sheet_count"] = sheet_count info["sheet_names"] = wb.sheetnames # Prüfe, ob mindestens ein Sheet die erwarteten Spalten hat sheets_with_data = 0 for sheet_name in wb.sheetnames: ws = wb[sheet_name] if ws.max_row < 2: continue # Kein Header + Daten header_row = list(ws.iter_rows(min_row=1, max_row=1, values_only=True))[0] missing_cols = [] for field in schema: col_idx = column_index_from_string(field.column) - 1 if col_idx >= len(header_row): missing_cols.append(f"{field.column} ({field.field_name})") continue header_val = str(header_row[col_idx]).strip() if header_row[col_idx] is not None else "" if header_val != field.field_name: warnings.append( f"Sheet '{sheet_name}', Spalte {field.column}: " f"Erwartet '{field.field_name}', gefunden '{header_val}'" ) if not missing_cols: sheets_with_data += 1 # Zähle Datenzeilen data_rows = ws.max_row - 1 info[f"rows_{sheet_name}"] = data_rows info["sheets_with_data"] = sheets_with_data wb.close() if sheets_with_data == 0: errors.append("Kein Sheet mit den erwarteten Spalten gefunden.") return ValidationResult( is_valid=len(errors) == 0, errors=errors, warnings=warnings, info=info, ) def validate_template( template_path: Path, mapping: list[OutputMapping], ) -> ValidationResult: """ Validiert ein Template: - Datei existiert - Alle target_cells aus dem Mapping sind im Template vorhanden """ errors: list[str] = [] warnings: list[str] = [] info: dict = {} if not template_path.exists(): errors.append(f"Template-Datei nicht gefunden: {template_path}") return ValidationResult(is_valid=False, errors=errors) try: wb = load_workbook(template_path, data_only=True) except Exception as e: errors.append(f"Template konnte nicht geöffnet werden: {e}") return ValidationResult(is_valid=False, errors=errors) info["sheet_names"] = wb.sheetnames # Wir validieren gegen das erste Sheet (üblicherweise das Haupt-Template) if not wb.sheetnames: errors.append("Template enthält keine Sheets.") wb.close() return ValidationResult(is_valid=False, errors=errors) ws = wb[wb.sheetnames[0]] found_cells = 0 missing_cells = [] for m in mapping: try: cell = ws[m.target_cell] found_cells += 1 except (ValueError, KeyError): missing_cells.append(m.target_cell) info["found_target_cells"] = found_cells info["total_target_cells"] = len(mapping) if missing_cells: errors.append(f"Zielfelder nicht im Template gefunden: {', '.join(missing_cells)}") wb.close() return ValidationResult( is_valid=len(errors) == 0, errors=errors, warnings=warnings, info=info, )