Wie kann ich ein Listenfeld mit einem Makro auslesen und dadurch ein Wort an einer anderen Stelle ändern?

Hallo zusammen,

ich habe im Writer ein Listenfeld erstellt, mit drei Optionen.

Ich würde gerne, wenn Option A im Listenfeld ausgewählt ist den Text an Stelle 1 und Stelle 2 in das Wort von Option A ändern. Wenn Option B und C jeweils in die entsprechende andere Bezeichnung.

Leider bin ich ganz neu was Libre Office angeht und finde auch nichts so richtig im Internet.

Ich hoffe ihr könnt mir weiterhelfen.

Vielen Dank.
VG Melvin

Das kann ich mir nur mit Makros vorstellen:

  1. Von dem Listenfeld den aktuellen Wert (CurrentValue) auslesen.
  2. Für die Textstellen einen gleichlautenden Platzhalter (Einfügen → Feldbefehl → weitere Feldbefehle → Funktionen → Platzhalter) erstellen.
  3. Die Platzhalter mit dem Wert des Listefeldes befüllen.

Wie bewandert bist Du mit Makros?

Also bisschen aus Word und Excel. In Libre jedoch garnicht.

In Libre fehlt mir auch die Dokumentation über die ganzen Formeln bzw. Befehle, in denen beschrieben ist wie diese funktionieren in den Makros.

Ich habe meinen Vorschlag gerade einmal ausprobiert. Da ich hauptsächlich mit Datenbanken unterwegs bin und auf ähnliche Art und Weise Vorlagen fülle habe ich nicht bedacht, dass zwar das Einfügen gelingt, aber anschließend eben die Platzhalter nicht mehr da sind. Das Verfahren geht also nur mit einem unberührten, neuen Dokument:
ListboxPlatzhalter.odt (16.0 KB)
Da müssen wohl einmal Leute ran, die mehr mit Writer unterwegs sind. Vermutlich müsste das mit Variablen statt Platzhaltern laufen.

Robert’s Faden aufnehmend:
ListboxPlatzhalter.odt (15.9 KB)

2 Likes

Hallo
Vorab: Ich möchte hier nicht als Besserwisser wahrgenommen werden… ( @Villeroy @Wanderer etcpp. können das genausogut wie ich nach python portieren ) …es geht mir eigentlich nur darum zu zeigen daß:

  1. python existiert und aus LO benutzt werden kann
  2. python keine »Raketenwissenschaft« ist
  3. zb. hier ein direkter Vergleich IMHO hilfreich ist, um andere Leute zu ermutigen auch mal in python zu programmieren.

zum Thema, hier ist der bereits leicht abgewandelte Code aus @Villeroy’s ListboxPlatzhalter.odt

SUB ListwertUebertragen(oEvent AS OBJECT)	
	oListbox = oEvent.Source.Model
	oDoc = oListbox.Parent  
	stEinfueg = oListbox.Tag	'Information in den Zusatzinformationen der Listbox
	stName = oListbox.SelectedValue
	oTextFieldMasters = ThisComponent.getTextFieldMasters()
	oMaster = oTextFieldMasters.getByName("com.sun.star.text.fieldmaster.User."& stEinfueg)
	oMaster.Content = stName
END SUB

und hier ein mögliches Equivalent in python:

def uebertrage_Auswahl(event):
    doc = (box := event.Source.Model).Parent.Parent.Parent
    fields = doc.TextFieldMasters
    fields[ "com.sun.star.text.fieldmaster"
            f".User.{box.Tag}"
           ].Content = box.SelectedValue
  1. ich wusste bisher nicht, daß Basic intern so »optimiert« daß bereits einmal …Parent ausreicht, um das Dokument-objekt zu erhalten
    Ich Depp … »oDoc« wird ja gar nicht mehr verwendet in Zeile 6 steht ja »thisComponent« ergo Basic optimiert da nix weg sondern möchte das genauso wie …→, python braucht an der Stelle explizit dreimal .Parent bis zu Dokument.
  2. in der zweiten Zeile benutze ich den sogenannten := Walrusoperator für eine seperate Zuweisung innerhalb der klammern. ( seit python3.8 also Oktober 2019 *** )
  3. unten sieht man daß eine logische Zeile, falls sie zu lang wird, relativ beliebig zwischen öffnender [ und schliessender ] umgebrochen werden kann…
  4. und praktisch überall die Methode …getByName durch eben diesen dictionary--access mit den eckigen Klammern drumrum ersetzt werden kann.
  5. … die String-formatierung per f"…{ }…" gibts schon schon lang genug.

***falls heute noch LO-versionen ab 7.5 für Windows|Mac immer noch mit python-versionen < 3.8 ausgeliefert werden ist das eher ein strukturelles Problem von LO !!

Diese paar Zeilen ohne Arrays, ohne Dictionaries, ohne Stringmanipulation, ohne Loops sind mit StarBasic viel einfacher und schneller in ein Dokument zu schreiben. Jeder kann diesen Code mit Bordmitteln ansehen und schrittweise testen. Außerdem hat Robert noch nie etwas in Python geschrieben.

Das bestreite ich doch garnicht. Aber es gibt auch »erweiterte« Bordmittel (APSO, Mri) … Ansonsten hab geschrieben was meine Intention ist, wo ist jetzt das Problem?

Die erweiterten Bordmittel hat aber nicht jeder, und ich habe lediglich den Code eines anderen Autors verändert. Da werde ich doch nicht die Sprache wechseln.

Was trotzdem eine gute Idee wäre, wenn wir häufiger hätten:
So ist die Lösung in Star Basic und
so ist die Lösung in Python.

Hat vielleicht einen entsprechenden Lerneffekt.
… und ich lerne ja gerade, wie das mit Python auch gehen könnte.

Auch das hab ich nicht verlangt!
Was mich jetzt aber interessiert: wie kommst du »nur mit der Basic-IDE« an die Eigenschaften von oEvent ran, ohne diese bereits vorher zu kennen und ohne XRay oder Mri

Genau, Danke Robert das ist eigentlich meine Idee dahinter.

Nun ja. Wer Python schreiben kann, kopiert sich die sehr simple Basic Sub in den Texteditor und verändert so gut wie gar nichts. Bei der “wörtlichen” Übersetzung habe ich nur die Deklaration, den Verkettungsoperator & in + geändert und # als Kommentareinleitung. Das ganze als .py in den Scripts/python-Ordner, fertig ist die Übersetzung (falls man in Basic die Groß/Kleinschreibung API-konform gesetzt hat).

def ListwertUebertragen(oEvent):
	oListbox = oEvent.Source.Model
	ThisComponent = XSCRIPTCONTEXT.getDocument()
#	oDoc = oListbox.Parent  das ist das Forumular und wird hier nicht gebraucht
	stEinfueg = oListbox.Tag #Information in den Zusatzinformationen der Listbox
	stName = oListbox.SelectedValue
	oTextFieldMasters = ThisComponent.getTextFieldMasters()
	oMaster = oTextFieldMasters.getByName("com.sun.star.text.fieldmaster.User."+ stEinfueg)
	oMaster.Content = stName

Nicht ganz, »ThisComponent« wäre unbekannt, und wenn ich daß durch »oDoc« aus Zeile 3 ersetze werden die 2 fehlenden Instanzen von »Parent« angemeckert werden. ( AttributError: getTextFieldMasters in Zeile 6 )
und nein: eine mit OpenOffice2.0 rückwärtskompatible Übertragung war mir etwas zu wenig.

Stimmt. Die schlecht benannte Variable oDoc hat mich glauben lassen, dass das Dokument deklariert sei. Daher werden viele meiner Python-Makros mit folgender Zeile eingeleitet: ThisComponent = XSCRIPTCONTEXT.getDocument(). :wink:

Ja … Geschmackssache »thisComponent« ist in python ok, wäre mir aber etwas zu lang wenn ich das häufiger bräuchte, daher tendiere ich eher zu »doc« ohne das nichtssagende o vornedran.
In Basic würde ich die mehrmalige Verwendung von »thisComponent« ablehnen, weil das ja eine globale Funktion ist, und ich schon Code gesehen habe wo innerhalb der Sub das dahinterstehende Dokument gewechselt wurde → peng.
Ich hab meinen ersten Beitrag noch editiert weil ich eben genau das »thisComponent« in Zeile 6 übersehen habe.

Noch mal die Frage @Villeroy

Mit dem Cursor auf der ersten Zeile F9 drücken, um eine Stopmarke zu setzen. Dann mit dem Kontrollelement das Makro triggern. Der Screenshot zeigt den angehaltenen Code auf der Stopmarke.
Bildschirmfoto von 2023-11-01 20-19-58
Den Textcursor auf den Variablennamen ev setzen und F7 drücken, um die Variable im “Watch Window” anzuzeigen.
Bildschirmfoto von 2023-11-01 20-20-15
Man kann dort auch einen Variablennamen eintragen. Objektvariablen werden als Baumstruktur angezeigt, einfache Variablen mit ihrem Wert.
F8 führt die Zeile aus und spring zur nächsten Anweisung
Shift+F8 überspringt einen Prozeduraufruf (führt andere Prozedur aus und stoppt wieder in dieser Prozedur).
F5 führt weiter aus bis zum Ende oder bis zur nächsten Stopmarke.

Das ganze ist ein Remake der allerersten VBA-IDE von Office 7 (1995). Office 8 (1997) hatte schon eine vollwertige IDE mit Auto-Completion und direktem Aufruf der Hilfeseiten zu wirklich jeder Eigenschaft, jedem Event und jeder Methode. Einfach F1 bei einer beliebigen Objektvariable drücken.
Und heute bekommen wir von MS vorgeführt, wie Python in einer Tabellenkalkulation funktionieren kann, indem man Python-Code statt einer (Matrix-)Formel in Zellen eingibt. Erste Schritte mit Python in Excel - Microsoft-Support

Ah … war mir nicht bewusst, daß Event-getriggerte Sachen tatsächlich mit Stopmarken und Einzelschrittmodi zur »Kommunikation« überredet werden können, mein prototypischer Ansatz ist dann:

def someFunc(event):
    # mri ist hier bereits initialisiert
    mri.inspect(event)

Ich kam nie wirklich mit Excel VBA in Berührung.
( Anfang der 80er VHS basic-kurs auf Papier :slight_smile: !Highlight!: Innenbesichtigung des Hochschulrechenzentrums Giessen ) dann lange nix dergleichen…
(1998 erster eigener Rechner, gleich von Anfang an mit Linux (SuSe) und wenig genutztem Dualboot mit Windows.) später hab ich Windows auf eine VM umgezogen, damits nicht so viel Unsinn macht)

@python-Excel: soweit ich das sehe:

  1. Frankenstein-schnittstelle Excel-Pandas-Numpy-matplotlib (also nicht neues unter der Sonne ausser der interaktiven Schnittstelle Excel nach draussen! )
  2. Gibts erstmal nur für Windows, und daß obwohl es nur remote in der Cloud läuft, was für mich schon mal ein Ausschlusskriterium ist.

@melvinw
Typischerweise will man ja nicht nur einen Namen auswählen, der dann hier und da im Text erscheint. Wenn es z.B. um die Adressierung eines Briefes geht, will man ja einen Namen auswählen und dann Straße, Hausnummer, PLZ, Ort, Anrede zu diesem Namen in das Dokument einfügen. Das funktioniert ganz anders und sogar ohne Makro-Code.

@Villeroy
Genau wie deine Lösung weiter oben sollte es funktionieren.
Deine Datei funktioniert auch bei mir.

Wenn ich das Makro jedoch in meine Datei einfüge, dann kommt die folgende Fehlermeldung:
BASIC-Laufzeitfehler.
Es ist eine Ausnahme aufgetreten
Type: com.sun.star.container.NoSuchElementException
Message: SwXTextFieldMasters::getByName(com.sun.star.text.fieldmaster.User.).