Start der neuen Methodik zur automatischen Extraktion von Bezeichnern zu Teilenummern. Neue COnfig, schalter in drawdxf, neues Skript zum updaten

This commit is contained in:
2025-06-18 16:22:42 +02:00
parent dc1b5387a8
commit 8e653aca20
4 changed files with 214 additions and 5 deletions
+4 -1
View File
@@ -2,7 +2,7 @@
REM ~dp0 steht für das Verzeichnis, in der diese Datei liegt
pushd %~dp0\..
set PROJECT=C:\kabellaengen
set PROJECT=C:\10-Develop\kabellaengen
set PROJECT_BIN=%PROJECT%\bin
set PROJECT_CFG=%PROJECT%\cfg
set PROJECT_DOC=%PROJECT%\doc
@@ -11,6 +11,9 @@ set PROJECT_DATA=%PROJECT%\data
set PROJECT_WORK=%PROJECT%\work
set PROJECT_TEST=%PROJECT%\testdata
set SIVAS_TEILESTAMM=\\195.243.223.3\sivas\jit\programme\KSbExcelExportSivasTeilestamm.exe
set SIVAS_EXCEL_EXPORT_DIR=%PROJECT_DATA%
if not exist %PROJECT%\work mkdir %PROJECT%\work
if not exist %PROJECT%\data mkdir %PROJECT%\data
+64
View File
@@ -0,0 +1,64 @@
# Artikelnummern zu welchen Bezeichner fehlt (-> ggf. Abfrage starten!)
# Art-numbers to which no name is available (-> start query if needed!)
[Missing]
# Bezeichner jeder Verbindungsleitung (gekürzt)
# Name of every cable (shortened)
[Sivasnummern]
725000015=4G1,5mm², Steuerleitung
722001300=M12 St-0°/ M8 Bu-0° 1m
722001301=M12 St-0°/ M8 Bu-0° 2m
722001302=M12 St-0°/ M8 Bu-0° 3m
722001303=M12 St-0°/ M8 Bu-0° 5m
722001304=M12 St-0°/ M8 Bu-0° 10m
722001305=M12 St-0°/ M8 Bu-0° 15m
722001306=M12 St-0°/ M8 Bu-0° 20m
722001307=M12 St-0°/ M8 Bu-0° 25m
722001308=M12 St-0°/ M8 Bu-0° 2,5m
722001309=M12 St-0°/ M8 Bu-0° 30m
722001310=M12 St-0°/ M8 Bu-0° 35m
722001311=M12 St-0°/ M8 Bu-0° 40m
722001312=M12 St-0°/ M8 Bu-0° 50m
722001330=M12 St-0°/ M12 Bu-90° 1m
722001331=M12 St-0°/ M12 Bu-90° 2m
722001332=M12 St-0°/ M12 Bu-90° 3m
722001333=M12 St-0°/ M12 Bu-90° 5m
722001334=M12 St-0°/ M12 Bu-90° 10m
722001335=M12 St-0°/ M12 Bu-90° 15m
722001336=M12 St-0°/ M12 Bu-90° 20m
722001337=M12 St-0°/ M12 Bu-90° 25m
722001338=M12 St-0°/ M12 Bu-90° 2,5
722001339=M12 St-0°/ M12 Bu-90° 30m
722001340=M12 St-0°/ M12 Bu-90° 35m
722001341=M12 St-0°/ M12 Bu-90° 40m
722001342=M12 St-0°/ M12 Bu-90° 50m
722001352=M12 St-0°/ M12 Bu-0° 3m
722001353=M12 St-0°/ M12 Bu-0° 5m
722001354=M12 St-0°/ M12 Bu-0° 10m
722001355=M12 St-0°/ M12 Bu-0° 15m
722001356=M12 St-0°/ M12 Bu-0° 20m
722001357=M12 St-0°/ M12 Bu-0° 30m
722001358=M12 St-0°/ M12 Bu-0° 2,5m
722001359=M12 St-0°/ M12 Bu-0° 40m
726001062=Patchkabel 2xRJ45 0,25m
726001040=Patchkabel 2xRJ45 0,5m
726001041=Patchkabel 2xRJ45 1,0m
726001042=Patchkabel 2xRJ45 1,5m
726001043=Patchkabel 2xRJ45 2,0m
726001044=Patchkabel 2xRJ45 3,0m
726001045=Patchkabel 2xRJ45 5,0m
726001046=Patchkabel 2xRJ45 10m
726001047=Patchkabel 2xRJ45 15m
726001048=Patchkabel 2xRJ45 20m
726001049=Patchkabel 2xRJ45 25m
726001050=Patchkabel 2xRJ45 30m
726001051=Patchkabel 2xRJ45 35m
726001052=Patchkabel 2xRJ45 40m
726001053=Patchkabel 2xRJ45 45m
726001054=Patchkabel 2xRJ45 50m
726001055=Patchkabel 2xRJ45 55m
726001056=Patchkabel 2xRJ45 60m
726001057=Patchkabel 2xRJ45 65m
726001060=Patchkabel 2xRJ45 85m
726001061=Patchkabel 2xRJ45 95m
+10 -4
View File
@@ -10,6 +10,7 @@ from openpyxl import Workbook
import math
from collections import defaultdict
import configparser
from updateconfignames import get_sivas_teilestamm, read_bezeichner_from_csv
@dataclass
@@ -555,10 +556,10 @@ if __name__ == '__main__':
parser.add_argument('-n', '--new', action='store', help='create a new dxf file only with cables in it. Name is basename and a timestamp')
parser.add_argument('-x', '--excel', action='store', help='create a xlsx file with cables data', metavar='allCables.xls')
parser.add_argument('-o', '--origin', action='store', help='name of original .dxf file used by -d and -a', metavar='original.dxf')
parser.add_argument('-l', '--local', action='store_true', help='using only local data for naming of article numbers. If not set: fetching names from SIVAS.')
args = parser.parse_args()
config_dir = os.environ.get("PROJECT_CFG")
work_dir = os.fspath(os.environ.get('PROJECT_WORK'))
@@ -583,9 +584,14 @@ if __name__ == '__main__':
cable_cfg.read_file(f)
# Betriebsmittelkennzeichnungs-Config laden
config_BMK = configparser.ConfigParser(allow_no_value=True, delimiters=("="))
config_BMK.optionxform = lambda option: option # preserve case for letters
config_BMK.read(os.path.join(config_dir, "BMK.cfg"))
config_BMK = configparser.ConfigParser(allow_no_value=True, delimiters=("="))
config_BMK.optionxform = lambda option: option # preserve case for letters
config_BMK.read(os.path.join(config_dir, "BMK.cfg"))
names_cfg = configparser.ConfigParser()
names_cfg.optionxform = str #Keys case-sensitive
with open(os.path.join(config_dir, "bezeichner.cfg"), encoding="utf-8") as f:
names_cfg.read_file(f)
dxf_file = args.dxf
+136
View File
@@ -0,0 +1,136 @@
import argparse
import configparser
import os
import subprocess
import csv
def get_sivas_teilestamm(sivas_ids, out_dir=None, overwrite=True):
"""
Generiert für jede angegebene SIVAS-Teilenummer eine CSV-Datei, in der die Teilestamm-Informationen gespeichert sind
"""
sivas_teilestamm_exe = os.environ.get('SIVAS_TEILESTAMM')
if not os.path.isfile(sivas_teilestamm_exe):
raise FileNotFoundError(
f"Programmpfad '{sivas_teilestamm_exe}' nicht erreichbar. "
f"Bitte Zugriff und Variable SIVAS_TEILESTAMM in setenv.bat prüfen."
)
if out_dir is None:
out_dir = os.environ.get('PROJECT_DATA')
if not os.path.isdir(out_dir):
raise NotADirectoryError(
f"Ausgabeverzeichnis '{out_dir}' existiert nicht. "
f"Bitte VPN oder setenv.bat prüfen."
)
if isinstance(sivas_ids, str):
sivas_ids = list(set(sivas_ids.strip().split(",")))
ids_to_generate = []
for id in sivas_ids:
if not overwrite and os.path.isfile(os.path.join(out_dir, id + ".csv")):
continue
ids_to_generate.append(id)
if len(ids_to_generate) == 0:
print("Alle CSVs vorhanden oder keine neuen Nummern")
return
ids_to_generate_str = ",".join([f'"{id}"' for id in ids_to_generate])
os.environ["SIVAS_EXCEL_EXPORT_DIR"] = out_dir
print(f"Erstelle CSV(s) mit Teilestamminformationen...")
subprocess.run(f'{sivas_teilestamm_exe} -teilenr={ids_to_generate_str} -open_target_dir=n')
for id in ids_to_generate:
csv_path = os.path.join(out_dir, id + ".csv")
with open(csv_path, encoding="utf-8", newline="") as csv_file:
csv_data = csv.reader(csv_file, delimiter=";")
rows = list(csv_data)
if len(rows) != 2:
raise ValueError(f"SIVAS-Teilenummer '{id}' existiert nicht oder liefert keine gültige CSV.")
# Rückgabe des Bezeichners (zweite Zeile, zweite Spalte)
yield id, rows[1][1].strip()
def read_bezeichner_from_csv(teilenr):
"""
Liest den Bezeichner aus einer SIVAS-CSV für eine gegebene Teilenummer.
:param teilenr: SIVAS Teilenummer als String
:return: Bezeichner-String, falls erfolgreich. Wirft Exception bei Fehler.
"""
csv_dir = os.environ.get("PROJECT_DATA", ".")
csv_path = os.path.join(csv_dir, f"{teilenr}.csv")
if not os.path.isfile(csv_path):
raise FileNotFoundError(f"CSV für Teilenummer '{teilenr}' nicht gefunden unter {csv_path}")
with open(csv_path, encoding="utf-8", newline="") as f:
reader = csv.reader(f, delimiter=";")
rows = list(reader)
if len(rows) != 2:
raise ValueError(f"Ungültiges Format oder keine Daten in CSV für '{teilenr}'")
bezeichner = rows[1][1].strip()
return bezeichner
def update_bezeichner(names_config):
if "Missing" not in names_config or not names_config["Missing"]:
print("Keine fehlenden Einträge in [Missing]. Keine Abfrage angestoßen.")
return
missing_ids = list(names_config["Missing"].keys())
print(f"Starte SIVAS-Abfrage für {len(missing_ids)} fehlende Teilenummer(n)...")
try:
get_sivas_teilestamm(missing_ids)
except Exception as e:
print(f"Fehler bei der SIVAS-Abfrage: {e}")
return
updated = 0
for id in missing_ids:
try:
bezeichner = read_bezeichner_from_csv(id)
if "Sivasnummern" not in names_config:
names_config["Sivasnummern"] = {}
names_config["Sivasnummern"][id] = bezeichner
updated += 1
except Exception as e:
print(f"WARNUNG: Bezeichner für {id} konnte nicht gelesen werden: {e}")
for id in missing_ids:
names_config["Missing"].pop(id, None)
if "Missing" in names_config and not names_config["Missing"]:
names_config.remove_section("Missing")
with open(config_path, "w", encoding="utf-8") as f:
names_config.write(f)
print(f"{updated} Bezeichner erfolgreich ergänzt und Konfiguration aktualisiert.")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Aktualisiert fehlende Bezeichner in bezeichner.cfg anhand von SIVAS-Teilestamm.")
parser.add_argument("-c", "--config", type=str, default=os.path.join(os.environ.get("PROJECT_CFG", "."), "bezeichner.cfg"), help="Pfad zur bezeichner.cfg")
args = parser.parse_args()
config_path = args.config
if not os.path.isfile(config_path):
raise FileNotFoundError(f"Config-Datei nicht gefunden: {config_path}")
config = configparser.ConfigParser()
config.optionxform = str # Groß-/Kleinschreibung erhalten
config.read(config_path, encoding="utf-8")
update_bezeichner(config)