fix: input validierung überspringt erstes sheet, weil diese nur zur Übersicht ist
This commit is contained in:
1 parent
1e44aaab9d
commit
31cdc7747f
3 files changed
+52
-9
No files matched your search
@@ -75,15 +75,30 @@ with col1:
|
|||||||
input_path = Path(app_config.input_dir) / selected_input
|
input_path = Path(app_config.input_dir) / selected_input
|
||||||
# Validiere und parse sofort
|
# Validiere und parse sofort
|
||||||
with st.spinner("Validiere Input-Datei…"):
|
with st.spinner("Validiere Input-Datei…"):
|
||||||
val_result = validate_input_file(input_path, app_config.input_schema)
|
val_result = validate_input_file(input_path, app_config.input_schema, app_config.month_sheet_pattern)
|
||||||
|
|
||||||
if not val_result.is_valid:
|
if not val_result.is_valid:
|
||||||
|
st.markdown(
|
||||||
|
'<div style="border:2px solid #e74c3c; border-radius:8px; padding:12px; '
|
||||||
|
'background:#fdedec; margin-bottom:12px">'
|
||||||
|
'<span style="color:#b03a2e; font-weight:bold; font-size:1.1em">'
|
||||||
|
'❌ Validierung fehlgeschlagen</span></div>',
|
||||||
|
unsafe_allow_html=True,
|
||||||
|
)
|
||||||
for err in val_result.errors:
|
for err in val_result.errors:
|
||||||
st.error(err)
|
st.error(f"🔴 {err}")
|
||||||
st.session_state.input_validated = False
|
st.session_state.input_validated = False
|
||||||
else:
|
else:
|
||||||
for warn in val_result.warnings:
|
if val_result.warnings:
|
||||||
st.warning(warn)
|
st.markdown(
|
||||||
|
'<div style="border:2px solid #f39c12; border-radius:8px; padding:8px 12px; '
|
||||||
|
'background:#fef9e7; margin-bottom:8px">'
|
||||||
|
'<span style="color:#7d6608; font-weight:bold">'
|
||||||
|
'⚠️ Hinweise</span></div>',
|
||||||
|
unsafe_allow_html=True,
|
||||||
|
)
|
||||||
|
for warn in val_result.warnings:
|
||||||
|
st.warning(warn)
|
||||||
|
|
||||||
# Parse die Datei
|
# Parse die Datei
|
||||||
records = parse_input_file(
|
records = parse_input_file(
|
||||||
@@ -130,8 +145,15 @@ with col2:
|
|||||||
tpl_result = validate_template(template_path, app_config.output_mapping)
|
tpl_result = validate_template(template_path, app_config.output_mapping)
|
||||||
|
|
||||||
if not tpl_result.is_valid:
|
if not tpl_result.is_valid:
|
||||||
|
st.markdown(
|
||||||
|
'<div style="border:2px solid #e74c3c; border-radius:8px; padding:12px; '
|
||||||
|
'background:#fdedec; margin-bottom:12px">'
|
||||||
|
'<span style="color:#b03a2e; font-weight:bold; font-size:1.1em">'
|
||||||
|
'❌ Validierung fehlgeschlagen</span></div>',
|
||||||
|
unsafe_allow_html=True,
|
||||||
|
)
|
||||||
for err in tpl_result.errors:
|
for err in tpl_result.errors:
|
||||||
st.error(err)
|
st.error(f"🔴 {err}")
|
||||||
st.session_state.template_validated = False
|
st.session_state.template_validated = False
|
||||||
else:
|
else:
|
||||||
st.session_state.template_validated = True
|
st.session_state.template_validated = True
|
||||||
@@ -139,6 +161,13 @@ with col2:
|
|||||||
total = tpl_result.info.get("total_target_cells", 0)
|
total = tpl_result.info.get("total_target_cells", 0)
|
||||||
st.success(f"✅ {found}/{total} Zielfelder gefunden")
|
st.success(f"✅ {found}/{total} Zielfelder gefunden")
|
||||||
if tpl_result.warnings:
|
if tpl_result.warnings:
|
||||||
|
st.markdown(
|
||||||
|
'<div style="border:2px solid #f39c12; border-radius:8px; padding:8px 12px; '
|
||||||
|
'background:#fef9e7; margin-bottom:8px">'
|
||||||
|
'<span style="color:#7d6608; font-weight:bold">'
|
||||||
|
'⚠️ Hinweise</span></div>',
|
||||||
|
unsafe_allow_html=True,
|
||||||
|
)
|
||||||
for warn in tpl_result.warnings:
|
for warn in tpl_result.warnings:
|
||||||
st.warning(warn)
|
st.warning(warn)
|
||||||
|
|
||||||
|
|||||||
+3
-1
@@ -65,7 +65,9 @@ def parse_input_file(
|
|||||||
|
|
||||||
ws = wb[sheet_name]
|
ws = wb[sheet_name]
|
||||||
# Header ist Zeile 1, Daten ab Zeile 2
|
# Header ist Zeile 1, Daten ab Zeile 2
|
||||||
for row in ws.iter_rows(min_row=2, max_row=ws.max_row, values_only=True):
|
# min_col=1 explizit setzen für korrekte Spaltenzuordnung
|
||||||
|
schema_col_count = len(schema)
|
||||||
|
for row in ws.iter_rows(min_row=2, max_row=ws.max_row, min_col=1, max_col=schema_col_count, values_only=True):
|
||||||
name = _to_text(row[col_map.get("Name", 0)]) if len(row) > col_map.get("Name", 0) else ""
|
name = _to_text(row[col_map.get("Name", 0)]) if len(row) > col_map.get("Name", 0) else ""
|
||||||
antragsnummer = _to_text(row[col_map.get("Antragsnummer", 0)]) if len(row) > col_map.get("Antragsnummer", 0) else ""
|
antragsnummer = _to_text(row[col_map.get("Antragsnummer", 0)]) if len(row) > col_map.get("Antragsnummer", 0) else ""
|
||||||
|
|
||||||
|
|||||||
+15
-3
@@ -6,18 +6,21 @@ from typing import Optional
|
|||||||
from openpyxl import load_workbook
|
from openpyxl import load_workbook
|
||||||
from openpyxl.utils import column_index_from_string
|
from openpyxl.utils import column_index_from_string
|
||||||
|
|
||||||
|
from .config import is_month_sheet
|
||||||
from .models import FieldSchema, OutputMapping, ValidationResult
|
from .models import FieldSchema, OutputMapping, ValidationResult
|
||||||
|
|
||||||
|
|
||||||
def validate_input_file(
|
def validate_input_file(
|
||||||
filepath: Path,
|
filepath: Path,
|
||||||
schema: list[FieldSchema],
|
schema: list[FieldSchema],
|
||||||
|
month_sheet_pattern: str = "* 20??",
|
||||||
) -> ValidationResult:
|
) -> ValidationResult:
|
||||||
"""
|
"""
|
||||||
Validiert eine Input-Datei:
|
Validiert eine Input-Datei:
|
||||||
- Datei existiert
|
- Datei existiert
|
||||||
- Erwartete Spalten sind vorhanden (Header in Zeile 1)
|
- Erwartete Spalten sind vorhanden (Header in Zeile 1)
|
||||||
- Mindestens ein Daten-Sheet enthält Daten
|
- Mindestens ein Monats-Daten-Sheet enthält Daten
|
||||||
|
- Nicht-Monats-Sheets (z. B. "Alle Rollen") werden übersprungen
|
||||||
"""
|
"""
|
||||||
errors: list[str] = []
|
errors: list[str] = []
|
||||||
warnings: list[str] = []
|
warnings: list[str] = []
|
||||||
@@ -37,14 +40,23 @@ def validate_input_file(
|
|||||||
info["sheet_count"] = sheet_count
|
info["sheet_count"] = sheet_count
|
||||||
info["sheet_names"] = wb.sheetnames
|
info["sheet_names"] = wb.sheetnames
|
||||||
|
|
||||||
# Prüfe, ob mindestens ein Sheet die erwarteten Spalten hat
|
# Prüfe nur Monats-Sheets (überspringe z. B. "Alle Rollen")
|
||||||
|
schema_col_count = len(schema)
|
||||||
sheets_with_data = 0
|
sheets_with_data = 0
|
||||||
for sheet_name in wb.sheetnames:
|
for sheet_name in wb.sheetnames:
|
||||||
|
if not is_month_sheet(sheet_name, month_sheet_pattern):
|
||||||
|
continue
|
||||||
|
|
||||||
ws = wb[sheet_name]
|
ws = wb[sheet_name]
|
||||||
if ws.max_row < 2:
|
if ws.max_row < 2:
|
||||||
continue # Kein Header + Daten
|
continue # Kein Header + Daten
|
||||||
|
|
||||||
header_row = list(ws.iter_rows(min_row=1, max_row=1, values_only=True))[0]
|
# min_col=1 explizit setzen, um Verschiebungen bei
|
||||||
|
# ws.min_column > 1 zu vermeiden
|
||||||
|
header_row = list(ws.iter_rows(
|
||||||
|
min_row=1, max_row=1, min_col=1, max_col=schema_col_count,
|
||||||
|
values_only=True,
|
||||||
|
))[0]
|
||||||
missing_cols = []
|
missing_cols = []
|
||||||
for field in schema:
|
for field in schema:
|
||||||
col_idx = column_index_from_string(field.column) - 1
|
col_idx = column_index_from_string(field.column) - 1
|
||||||
|
|||||||
Reference in new issue
Block a user