GND_Skript_Test/vorschlag_ersetzen.py
2025-10-10 09:46:41 +02:00

196 lines
7.1 KiB
Python

# -*- coding: utf-8 -*-
# LibreOffice Calc Makro: Interaktive Termersetzung mit Logging
import os
import re
try:
import uno
from com.sun.star.awt import XActionListener
UNO_AVAILABLE = True
except ImportError:
UNO_AVAILABLE = False
# Log-Datei definieren
BASE_DIR = os.path.expanduser("~/.config/libreoffice/4/user/Scripts/python/")
LOG_FILE = os.path.join(BASE_DIR, "vorschlag_ersetzen_log.txt")
def log(msg):
try:
with open(LOG_FILE, "a", encoding="utf-8") as f:
f.write(msg + "\n")
except Exception:
pass
def interactive_term_replace():
"""Makro zum interaktiven Ersetzen von Termen mit Logging."""
if not UNO_AVAILABLE:
log("Fehler: UNO-Bindings nicht verfügbar. Bitte LibreOffice-Python verwenden.")
return
try:
doc = XSCRIPTCONTEXT.getDocument()
controller = doc.getCurrentController()
if controller is None:
log("Fehler: Kein aktiver Controller gefunden.")
return
sheet = controller.ActiveSheet
if sheet is None:
log("Fehler: Kein aktives Sheet gefunden.")
return
# Aktive Zelle abrufen
try:
cell = controller.getActiveCell()
except Exception as e:
log(f"Fehler: Konnte aktive Zelle nicht abrufen: {e}")
return
if cell is None:
log("Fehler: Keine Zelle ausgewählt.")
return
cell_text = str(cell.String).strip()
if not cell_text:
log("Info: Ausgewählte Zelle ist leer.")
return
# Term-Liste erzeugen
clauses = [c.strip() for c in re.split(r",", cell_text) if c.strip()]
terms = []
for cl in clauses:
parts = [p.strip() for p in re.split(r"\s+", cl) if p.strip()]
terms.extend(parts)
if not terms:
log("Info: Keine Terme in der Zelle gefunden.")
return
# Norm_Vorschlag Spalte finden
header_row = None
norm_sug_col = None
for r in range(5):
for c in range(sheet.Columns.Count):
try:
val = str(sheet.getCellByPosition(c, r).String).strip()
except Exception:
val = ""
if val == "Norm_Vorschlag":
norm_sug_col = c
if val.lower() == "objektbeschreibung":
header_row = r
if header_row is not None and norm_sug_col is not None:
break
if header_row is not None and norm_sug_col is not None:
break
if norm_sug_col is None:
log("Fehler: Spalte 'Norm_Vorschlag' nicht gefunden.")
return
# Vorschläge auslesen
row = cell.RangeAddress.StartRow
sugg_str = str(sheet.getCellByPosition(norm_sug_col, row).String).strip()
all_suggestions = [s.strip() for s in sugg_str.split("|") if s.strip()]
if not all_suggestions:
log(f"Info: Keine Vorschläge in Zeile {row+1}.")
return
# Dialog erstellen (wie vorher)
toolkit = XSCRIPTCONTEXT.getDesktop().getCurrentFrame().getContainerWindow().getToolkit()
dialog_model = ctx.ServiceManager.createInstance("com.sun.star.awt.UnoControlDialogModel")
dialog_model.PositionX = 100
dialog_model.PositionY = 100
dialog_model.Width = 300
dialog_model.Height = 250
dialog_model.Title = "Term ersetzen"
# ListBox: Terme
term_list_model = dialog_model.createInstance("com.sun.star.awt.UnoControlListBoxModel")
term_list_model.Name = "term_list"
term_list_model.PositionX = 10
term_list_model.PositionY = 10
term_list_model.Width = 280
term_list_model.Height = 80
term_list_model.StringItemList = tuple(terms)
term_list_model.MultiSelection = False
dialog_model.insertByName("term_list", term_list_model)
# ListBox: Vorschläge
sugg_list_model = dialog_model.createInstance("com.sun.star.awt.UnoControlListBoxModel")
sugg_list_model.Name = "sugg_list"
sugg_list_model.PositionX = 10
sugg_list_model.PositionY = 100
sugg_list_model.Width = 280
sugg_list_model.Height = 80
sugg_list_model.StringItemList = tuple(all_suggestions)
sugg_list_model.MultiSelection = False
dialog_model.insertByName("sugg_list", sugg_list_model)
# Checkbox für "Alle Terme ersetzen"
cb_model = dialog_model.createInstance("com.sun.star.awt.UnoControlCheckBoxModel")
cb_model.Name = "replace_all"
cb_model.PositionX = 10
cb_model.PositionY = 190
cb_model.Width = 200
cb_model.Height = 15
cb_model.Label = "Alle Terme ersetzen"
dialog_model.insertByName("replace_all", cb_model)
# OK-Button
ok_model = dialog_model.createInstance("com.sun.star.awt.UnoControlButtonModel")
ok_model.Name = "ok_button"
ok_model.PositionX = 200
ok_model.PositionY = 190
ok_model.Width = 80
ok_model.Height = 25
ok_model.Label = "OK"
dialog_model.insertByName("ok_button", ok_model)
# Dialog erstellen
dialog = ctx.ServiceManager.createInstance("com.sun.star.awt.UnoControlDialog")
dialog.setModel(dialog_model)
dialog.setVisible(False)
dialog.createPeer(toolkit, None)
# ActionListener für OK
class OkListener(XActionListener):
def __init__(self, dialog, cell, terms):
self.dialog = dialog
self.cell = cell
self.terms = terms
def actionPerformed(self, event):
try:
list_box = self.dialog.getControl("term_list")
sugg_box = self.dialog.getControl("sugg_list")
cb = self.dialog.getControl("replace_all")
selected_sugg_idx = sugg_box.getSelectedItemPos()
if selected_sugg_idx < 0:
self.dialog.endExecute()
return
selected_sugg = sugg_box.getItem(selected_sugg_idx)
replace_all = cb.State == 1
if replace_all:
self.cell.String = " ".join([selected_sugg for t in self.terms])
else:
term_idx = list_box.getSelectedItemPos()
if term_idx >= 0:
self.terms[term_idx] = selected_sugg
self.cell.String = " ".join(self.terms)
except Exception as e:
log(f"Fehler während Dialogaktion: {e}")
finally:
self.dialog.endExecute()
def disposing(self, event):
pass
listener = OkListener(dialog, cell, terms)
ok_btn = dialog.getControl("ok_button")
ok_btn.addActionListener(listener)
dialog.execute()
except Exception as e:
log(f"Unbekannter Fehler: {e}")
# Export für LibreOffice
g_exportedScripts = (interactive_term_replace,)