# -*- 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,)