erste Fassung eines SKripts zur Extraktion der Texte aus einer .dxf Datei erstellt

This commit is contained in:
2025-12-02 22:20:26 +01:00
parent 17902ec8dc
commit f7f8aca5f1
5 changed files with 315 additions and 1 deletions
+272
View File
@@ -0,0 +1,272 @@
import argparse
import os
import re
import sys
from pathlib import Path
from configparser import ConfigParser
from fnmatch import fnmatch
import ezdxf
from openpyxl import Workbook
"""
Dieses Programm:
- liest eine DXF Datei und sammelt alle TEXT und MTEXT Objekte
- schreibt diese in die erste Spalte einer Excel-Datei
- speichert die Excel-Datei im PROJECT_WORK Verzeichnis
"""
def check_environment_var(env_str: str) -> Path:
"""Prüft ob eine Umgebungsvariable gesetzt ist und gibt den Pfad zurück."""
out_path = os.environ.get(env_str)
if out_path:
return Path(out_path)
else:
print(f"Umgebungsvariable {env_str} ist nicht gesetzt oder leer.")
sys.exit(1)
def load_ignore_patterns(cfg_path: Path) -> tuple[list[str], list[str]]:
"""
Liest die ignore_pattern aus der translator.cfg Datei.
Unterstützt sowohl Wildcard-Muster (*,?) als auch reguläre Ausdrücke.
Args:
cfg_path: Pfad zum Konfigurationsverzeichnis (PROJECT_CFG)
Returns:
Tuple mit (Wildcard-Mustern, Regex-Mustern)
"""
config_file = cfg_path / "translator.cfg"
if not config_file.exists():
print(f"FEHLER: Konfigurationsdatei nicht gefunden: {config_file}")
print(f"Bitte erstellen Sie die Datei 'translator.cfg' im Verzeichnis: {cfg_path}")
sys.exit(1)
config = ConfigParser()
try:
config.read(config_file, encoding='utf-8')
except Exception as e:
print(f"Fehler beim Lesen der Konfigurationsdatei: {e}")
sys.exit(1)
wildcard_patterns = []
regex_patterns = []
# Lade Wildcard-Muster
if config.has_section('ignore_pattern_wildcard'):
for key in config['ignore_pattern_wildcard']:
pattern = config['ignore_pattern_wildcard'][key].strip()
if pattern and not pattern.startswith('#'):
wildcard_patterns.append(pattern)
# Lade Regex-Muster
if config.has_section('ignore_pattern_regex'):
for key in config['ignore_pattern_regex']:
pattern = config['ignore_pattern_regex'][key].strip()
if pattern and not pattern.startswith('#'):
regex_patterns.append(pattern)
print(f"Geladene Wildcard-Muster: {len(wildcard_patterns)}")
for pattern in wildcard_patterns:
print(f" - {pattern}")
print(f"Geladene Regex-Muster: {len(regex_patterns)}")
for pattern in regex_patterns:
print(f" - {pattern}")
return wildcard_patterns, regex_patterns
def should_ignore_text(text: str, wildcard_patterns: list[str], regex_patterns: list[str]) -> bool:
"""
Prüft ob ein Text ignoriert werden soll basierend auf den Mustern.
Args:
text: Zu prüfender Text
wildcard_patterns: Liste der Wildcard-Muster (*,?)
regex_patterns: Liste der regulären Ausdrücke
Returns:
True wenn Text ignoriert werden soll, False sonst
"""
# Prüfe Wildcard-Muster
for pattern in wildcard_patterns:
if fnmatch(text, pattern):
return True
# Prüfe Regex-Muster
for pattern in regex_patterns:
try:
if re.search(pattern, text):
return True
except re.error:
# Falls ungültiger Regex, ignoriere dieses Muster
print(f"WARNUNG: Ungültiger regulärer Ausdruck: {pattern}")
continue
return False
def extract_text_from_dxf(filename: Path, wildcard_patterns: list[str], regex_patterns: list[str]) -> list[str]:
"""
Extrahiert alle TEXT und MTEXT Objekte aus einer DXF Datei.
Verwendet ein Set, um Duplikate zu vermeiden.
Args:
filename: Pfad zur DXF Datei
wildcard_patterns: Liste der Wildcard-Muster zum Filtern
regex_patterns: Liste der Regex-Muster zum Filtern
Returns:
Alphabetisch sortierte Liste mit allen gefundenen Texten (nach Filterung, ohne Duplikate)
"""
texts_set = set() # Set für eindeutige Texte
ignored_count = 0
total_count = 0
try:
doc = ezdxf.readfile(filename)
msp = doc.modelspace()
# Sammle alle TEXT Objekte
for entity in msp.query('TEXT'):
if entity.dxf.text:
total_count += 1
text = entity.dxf.text
if should_ignore_text(text, wildcard_patterns, regex_patterns):
ignored_count += 1
else:
texts_set.add(text)
# Sammle alle MTEXT Objekte
for entity in msp.query('MTEXT'):
if entity.text:
total_count += 1
text = entity.text
if should_ignore_text(text, wildcard_patterns, regex_patterns):
ignored_count += 1
else:
texts_set.add(text)
# Konvertiere Set zu sortierter Liste
texts = sorted(texts_set)
print(f"Anzahl gefundener TEXT/MTEXT Objekte: {total_count}")
print(f"Ignorierte Texte (nach Filter): {ignored_count}")
print(f"Duplikate entfernt: {total_count - ignored_count - len(texts)}")
print(f"Eindeutige Texte für Export: {len(texts)}")
except Exception as e:
print(f"Fehler beim Lesen der DXF Datei: {e}")
sys.exit(1)
return texts
def write_texts_to_excel(texts: list[str], output_path: Path):
"""
Schreibt die Texte in die erste Spalte einer Excel-Datei.
Args:
texts: Liste der zu schreibenden Texte
output_path: Pfad zur Ausgabe-Excel-Datei
"""
wb = Workbook()
ws = wb.active
ws.title = "Texte"
# Kopfzeile
ws['A1'] = "Text"
# Texte in die erste Spalte schreiben
for idx, text in enumerate(texts, start=2):
ws[f'A{idx}'] = text
# Spaltenbreite anpassen
ws.column_dimensions['A'].width = 50
try:
wb.save(output_path)
print(f"Excel-Datei erfolgreich erstellt: {output_path}")
except Exception as e:
print(f"Fehler beim Schreiben der Excel-Datei: {e}")
sys.exit(1)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Extrahiert TEXT und MTEXT Objekte aus einer DXF Datei und schreibt sie in eine Excel-Datei',
prog='translate'
)
parser.add_argument(
'-f', '--filename',
action='store',
required=True,
help='DXF Datei die verarbeitet werden soll',
metavar='myfile.dxf'
)
parser.add_argument(
'-e', '--extract',
action='store_true',
required=True,
help='Hole alle Texte aus der .dxf in eine Excel Datei'
)
parser.add_argument(
'-o', '--outname',
action='store',
help='Name der Ausgabedatei (ohne Pfad, mit oder ohne .xlsx Endung)',
metavar='output.xlsx'
)
args = parser.parse_args()
# Prüfe Umgebungsvariablen
work_dir = check_environment_var('PROJECT_WORK')
cfg_dir = check_environment_var('PROJECT_CFG')
# Lade Ignore-Muster aus Konfigurationsdatei
wildcard_patterns, regex_patterns = load_ignore_patterns(cfg_dir)
# Prüfe ob Datei eine DXF Datei ist
input_filename = args.filename
if not input_filename.lower().endswith(('.dxf', '.dwg')):
print("Nur verfügbar für .dxf oder .dwg Dateien")
sys.exit(1)
# Versuche zuerst Datei im Work-Ordner zu finden
filename = work_dir / input_filename
if not filename.exists():
# Falls nicht gefunden, prüfe ob es ein vollständiger Pfad ist
filename = Path(input_filename)
if not filename.exists():
print(f"Datei nicht gefunden: {input_filename}")
print(f" Geprüft in Work-Ordner: {work_dir / input_filename}")
print(f" Geprüft als vollständiger Pfad: {filename}")
sys.exit(1)
# Extrahiere Texte aus DXF
if args.extract:
print(f"Lese DXF Datei: {filename}")
texts = extract_text_from_dxf(filename, wildcard_patterns, regex_patterns)
# Erstelle Output-Dateinamen
if args.outname:
# Verwende benutzerdefinierten Namen
output_filename = args.outname
# Füge .xlsx Endung hinzu falls nicht vorhanden
if not output_filename.endswith('.xlsx'):
output_filename += '.xlsx'
else:
# Standardname basierend auf Eingabedatei
output_filename = filename.stem + "_texts.xlsx"
output_path = work_dir / output_filename
# Schreibe Texte in Excel
write_texts_to_excel(texts, output_path)
print("Verarbeitung erfolgreich abgeschlossen.")