forked from AG_QGIS/Plugin_SN_Basis
Angefangen, DataGrabber anzulegen (Grundlagen gelegt, noch nicht lauffähig)
This commit is contained in:
91
modules/excel_importer.py
Normal file
91
modules/excel_importer.py
Normal file
@@ -0,0 +1,91 @@
|
||||
# sn_plan41/modules/excel_importer.py
|
||||
import os
|
||||
from typing import Optional, Iterable, Mapping, Any, List, cast
|
||||
|
||||
from openpyxl import load_workbook
|
||||
from openpyxl.workbook.workbook import Workbook
|
||||
from openpyxl.worksheet.worksheet import Worksheet
|
||||
|
||||
from sn_basis.modules.Dateipruefer import Dateipruefer
|
||||
from sn_basis.modules.Pruefmanager import Pruefmanager
|
||||
from sn_basis.modules.pruef_ergebnis import pruef_ergebnis
|
||||
|
||||
|
||||
class ExcelImporter:
|
||||
"""
|
||||
Excel-Importer für Linklisten, verwendet Dateipruefer und Pruefmanager zur Meldungsbehandlung.
|
||||
|
||||
- Der Aufrufer übergibt einen konkreten Dateipfad.
|
||||
- Vor dem Öffnen wird der Pfad mit Dateipruefer geprüft.
|
||||
- Link- und Stilprüfungen erfolgen nicht hier, sondern im DataGrabber.
|
||||
- Nach dem Ladevorgang wird die Arbeitsmappe geschlossen, damit die Datei vom OS freigegeben wird.
|
||||
"""
|
||||
|
||||
def __init__(self, filepath: str, pruefmanager: Pruefmanager):
|
||||
if not filepath:
|
||||
raise ValueError("ExcelImporter benötigt einen gültigen Dateipfad.")
|
||||
if pruefmanager is None:
|
||||
raise ValueError("ExcelImporter benötigt einen Pruefmanager.")
|
||||
self.filepath = filepath
|
||||
self.pruefmanager = pruefmanager
|
||||
|
||||
def import_xlsx(self) -> List[Mapping[str, Any]]:
|
||||
"""
|
||||
Liest die Excel-Datei und gibt eine Liste von Dicts (Zeilen) zurück.
|
||||
Bei Prüf- oder Leseproblemen wird der Pruefmanager zur Verarbeitung des pruef_ergebnis aufgerufen.
|
||||
Im Fehlerfall wird eine leere Liste zurückgegeben.
|
||||
"""
|
||||
# 1) Dateiprüfung über Dateipruefer
|
||||
datei_pruefer = Dateipruefer(pfad=self.filepath, temporaer_erlaubt=False)
|
||||
ergebnis: pruef_ergebnis = datei_pruefer.pruefe()
|
||||
ergebnis = self.pruefmanager.verarbeite(ergebnis)
|
||||
|
||||
if not ergebnis.ok:
|
||||
return []
|
||||
|
||||
workbook: Optional[Workbook] = None
|
||||
try:
|
||||
workbook = load_workbook(filename=self.filepath, data_only=True)
|
||||
|
||||
# workbook.active kann typmäßig als Optional angesehen werden; cast/prüfen, damit Pylance weiß, dass sheet ein Worksheet ist
|
||||
sheet = workbook.active
|
||||
if sheet is None:
|
||||
pe = pruef_ergebnis(ok=False, meldung=f"Kein aktives Blatt in der Arbeitsmappe: {self.filepath}", aktion="kein_arbeitsblatt", kontext=self.filepath)
|
||||
self.pruefmanager.verarbeite(pe)
|
||||
return []
|
||||
|
||||
# Typengranularität für den Linter
|
||||
sheet = cast(Worksheet, sheet)
|
||||
|
||||
# Header aus erster Zeile (als Werte)
|
||||
header_row = next(sheet.iter_rows(min_row=1, max_row=1, values_only=True), None)
|
||||
if not header_row:
|
||||
pe = pruef_ergebnis(ok=False, meldung=f"Excel-Datei enthält keine Header-Zeile: {self.filepath}", aktion="kein_header", kontext=self.filepath)
|
||||
self.pruefmanager.verarbeite(pe)
|
||||
return []
|
||||
|
||||
header = list(header_row)
|
||||
if not header or all(h is None for h in header):
|
||||
pe = pruef_ergebnis(ok=False, meldung=f"Excel-Header ist leer oder ungültig: {self.filepath}", aktion="kein_header", kontext=self.filepath)
|
||||
self.pruefmanager.verarbeite(pe)
|
||||
return []
|
||||
|
||||
ergebnis_list: List[Mapping[str, Any]] = []
|
||||
# Werte-only lesen für Performance und Einfachheit
|
||||
for row in sheet.iter_rows(min_row=2, values_only=True):
|
||||
if row is None:
|
||||
continue
|
||||
# zip stoppt bei kürzerer Länge; das ist beabsichtigt
|
||||
attributes = dict(zip(header, row))
|
||||
ergebnis_list.append(attributes)
|
||||
|
||||
return ergebnis_list
|
||||
|
||||
except Exception as exc:
|
||||
pe = pruef_ergebnis(ok=False, meldung=f"Fehler beim Lesen der Excel-Datei '{self.filepath}': {exc}", aktion="read_error", kontext=self.filepath)
|
||||
self.pruefmanager.verarbeite(pe)
|
||||
return []
|
||||
|
||||
finally:
|
||||
if workbook is not None:
|
||||
workbook.close()
|
||||
Reference in New Issue
Block a user