#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ merkmalstamm.py - Liest Merkmalnummer -> Bezeichnung aus cfg/Merkmalsstamm_in_Sivas.xlsx. Bewusst ohne openpyxl (reine Standard-Library: zipfile + xml.etree) - export.lsp/export:python-exe loest den Interpreter fuer EXPORTSIVAS ueber Config/DXFM_PYTHON/Projekt-venv/PATH auf und garantiert dabei keine zusaetzliche pip-Abhaengigkeit; ein .xlsx ist im Kern ein ZIP aus XML- Dateien, das reicht hier ohne Zusatzpaket. """ import os import re import zipfile from functools import lru_cache from xml.etree import ElementTree as ET _NS = {"main": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"} def merkmalstamm_pfad(): """Pfad zu Merkmalsstamm_in_Sivas.xlsx: DXFM_CFG env var, sonst /cfg.""" dxfm_cfg = os.environ.get("DXFM_CFG") if dxfm_cfg: return os.path.join(dxfm_cfg, "Merkmalsstamm_in_Sivas.xlsx") basis = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) return os.path.join(basis, "cfg", "Merkmalsstamm_in_Sivas.xlsx") def _spalte_zu_zahl(spalte): zahl = 0 for zeichen in spalte: zahl = zahl * 26 + (ord(zeichen) - ord("A") + 1) return zahl def _spalte_aus_zellref(ref): treffer = re.match(r"([A-Z]+)\d+", ref) return treffer.group(1) if treffer else "A" @lru_cache(maxsize=None) def lade_merkmalstamm(pfad=None): """Liest Sheet 1 (Spalte A=Merkmal-Nr., Spalte C=Bezeichnung) und liefert ein Dict Merkmalnummer (str) -> Bezeichnung (str, von Excel- Zeilenumbruch-Artefakten wie "_x000D_" bereinigt). Bei fehlender/kaputter Datei: leeres Dict - Aufrufer faellt dann auf die reine Merkmalnummer zurueck (siehe bezeichnung_fuer).""" if pfad is None: pfad = merkmalstamm_pfad() if not os.path.exists(pfad): return {} try: with zipfile.ZipFile(pfad) as z: shared = [] if "xl/sharedStrings.xml" in z.namelist(): baum = ET.fromstring(z.read("xl/sharedStrings.xml")) for si in baum.findall("main:si", _NS): texte = si.findall(".//main:t", _NS) shared.append("".join(t.text or "" for t in texte)) sheet = ET.fromstring(z.read("xl/worksheets/sheet1.xml")) mapping = {} for row in sheet.findall(".//main:sheetData/main:row", _NS): zellen = {} for c in row.findall("main:c", _NS): spalte = _spalte_zu_zahl(_spalte_aus_zellref(c.get("r", "A1"))) v = c.find("main:v", _NS) wert = v.text if v is not None else None if c.get("t") == "s" and wert is not None: wert = shared[int(wert)] zellen[spalte] = wert nummer = zellen.get(1) bezeichnung = zellen.get(3) if nummer and str(nummer).strip().isdigit() and bezeichnung: bezeichnung = bezeichnung.replace("_x000D_", " ") bezeichnung = re.sub(r"\s+", " ", bezeichnung).strip() mapping[str(nummer).strip()] = bezeichnung return mapping except (KeyError, zipfile.BadZipFile, ET.ParseError): return {} def bezeichnung_fuer(nummer, mapping=None): """Bezeichnung zu einer Merkmalnummer, Fallback: die Nummer selbst (z.B. bei fehlendem Eintrag im Merkmalstamm).""" if mapping is None: mapping = lade_merkmalstamm() return mapping.get(str(nummer), str(nummer))