Antwortschreiben auf Bewerbungen werden oft generisch verfasst und greifen auf Standardtextbausteine zurück. Diese Aufgabe lässt sich in LibreOffice Writer über Makros elegant ohne Copy & Paste erledigen.
Aller Anfang ist schwer. Das trifft vor allem auf das Erstellen eines neuen Programms zu. Allerdings lässt sich mit LibreOffice [1] eine grafische Oberfläche für Dialoge schnell erstellen. Mittels Drag & Drop stellen Sie ein geeignetes Dialogfenster wie das hier vorgestellte Bewerber-Tool auf einfache Weise zusammen.
Für den erforderlichen Code dahinter müssen Sie jedoch schon etwas Zeit mitbringen: Es kommen gut und gern 500 Zeilen an Code zusammen. Zudem erfordert das Testen des Werkzeugs ein wenig Zeit. Zusätzlich müssten die Eingabefelder auf Richtigkeit hin geparst werden, was jedoch nicht Bestandteil des Artikels ist. Dennoch stellen Sie mithilfe des hier vorgestellten Codes problemlos einen kompletten Brief oder ein Antwortschreiben auf die Beine.
Vorlage im Überblick
Die Überschriftenstile von LibreOffice eignen sich grundsätzlich zur Formatierung des Betreffs, Sie sollten sie aber noch ein wenig anpassen. Außerdem setzt das Beantworten von Bewerbungen beziehungsweise das Verfassen eines Briefs einen neuen Stil voraus, um das Datum zu formatieren. Dazu klicken Sie mit der rechten Maustaste auf den obersten Stil und im Kontextmenü ein weiteres Mal auf neu. Zunächst vergeben Sie im Tab Verwalten einen Namen für den Stil. Dann geben Sie die Folgevorlage an, also welchen Stil Writer verwenden soll, sobald die Formatierung mit dem aktuellen abgeschlossen ist. Hier wählen Sie Textkörper aus. Anschließend legen Sie im Tab Ausrichtung über die Option Rechts fest, dass das Datum am rechten Rand des Dokuments erscheint.
Die Entwicklungsumgebung beherbergt links den Objektkatalog, von wo aus Sie auf die Module, Funktionen und Variablen zugreifen können (Abbildung 1). Sobald Sie auf den Namen klicken, den Sie für Ihr Dialogfenster vergeben haben, können Sie per Drag & Drop alle erforderlichen Steuerelemente ins Fenster ziehen. Zur Eingabe von freiem Text wie beispielsweise Adressen oder Telefonnummern eignen sich Textboxen. Für die Beschriftung der Steuerelemente können Sie Labels verwenden.

Abbildung 1: In der Entwicklungsumgebung von LibreOffice definieren Sie die Funktionen und Variablen.
Darüber hinaus benötigen Sie für das Beispiel aus diesem Artikel ein Datums- sowie ein Zeitfeld. Zur Bestimmung der Antwortart dienen zwei Optionsfelder (Radiobuttons). Das Starten sowie Abbrechen der Anwendung regeln zwei Buttons, die Sie ebenfalls von der Leiste der Steuerelemente ins Fenster ziehen können.
Achten Sie bei den Steuerelementen, deren Werte das Makro abruft, darauf, ihnen Namen zuzuweisen, denn über diese greift das Makro auf den jeweiligen Inhalt zu. Sie vergeben einen Namen für das Steuerelement, indem Sie es markieren und im Eigenschaftsfenster im Feld Name einen Bezeichner dafür eingeben. Die Radiobuttons sollten neben dem Namen einen gemeinsamen Gruppennamen erhalten, sodass sich deren Werte bequem durch eine For-Schleife abrufen lassen. Das vermeidet Codedoppler.
Für dieses Beispiel brauchen Sie keine Namen für die Labels zu vergeben. Jedoch könnten Sie Labels interaktiv benutzen, indem Sie das Feedback mittels eines solchen ausgeben.
Textbausteine
Die Textbausteine einer Zusage [2], Absage [3] oder eines sonstigen Schreibens sollten vor dem Abspielen des Makros bereits in Variablen gespeichert sein. Darüber hinaus lässt sich die eigene Anschrift in einer Variablen ablegen, da sie bereits bekannt ist und sich nicht laufend von Brief zu Brief ändert. Um beim Einfügen von Textbausteinen auf die erforderlichen Variablen zuzugreifen, setzen Sie den Wert der Variablen in einer eigens definierten Funktion und rufen diese auf, sobald der Brief erstellt wird.
Die Textbausteine, die in jedem Schreiben erscheinen, stehen in der Funktion SetBoilerplates() (Listing 1). Für die Zusage gibt es die Funktion SetAcceptanceVars() (Listing 2), die den Variablen die für eine Zusage erforderlichen Werte zuweist. Die Funktion SetRejectionVars() (Listing 3) stellt darüber hinaus Textbausteine bereit, die für eine Absage relevant sind.
Abgesehen von den Textbausteinen lassen sich die Namen der Steuerelemente in global definierten Variablen vom Typ String festhalten (Listing 4). Dadurch brauchen Sie lediglich an einer Stelle etwas zu ändern, falls der Name des Steuerelements sich ändern sollte beziehungsweise Sie das Steuerelement aus dem Dialogfenster entfernen.
Listing 1
Feste Textbausteine
Function SetBoilerplates() sDear = "Sehr geehrte(r) " sGreeting = "Mit freundlichen Grüßen," smycompany = "Continental AG" smycompany2 = "Hauptverwaltung" smystreet = "Vahrenwalder Straße 9" smyzip = "30165" smytown = "Hannover" smycountry = "Germany" sSubject = "Ihre Bewerbung auf die Stelle als " End Function
Listing 2
Textbausteine Zusage
Function SetAcceptanceVars() sAcceptance1 = "Sie haben es geschafft! Wir sagen Ihnen mit Freude die Stelle als " sAcceptance2 = " zu." sJobStart1 = "Gehen wir gerne auf Ihren Wunsch auf einen Arbeitsbeginn am " sJobStart2 = " ein." sJobBegin1 = " aus unserer HR-Abteilung wird Sie um " sJobBegin2 = " am Eingang begrüßen." End Function
Listing 3
Textbausteine Absage
Function SetRejectionVars() firstP="an dieser Stelle möchten wir uns für Ihre Bewerbung und Ihr " _ & chr(13) & "Interesse an unserem Unternehmen bedanken. Wir haben uns sehr" _ & chr(13) & "gefreut, Sie in einem persönlichen Gespräch kennenlernen zu" & chr(13) & "können." secondP = "Dennoch müssen wir Ihnen heute leider mitteilen, dass wir uns für" _ & chr(13) & "einen anderen Kandidaten entschieden haben, der unserem" _ & chr(13) & "Anforderungsprofil noch besser entsprochen hat. Wir möchten" _ & chr(13) & "Ihnen jedoch versichern, dass unsere Entscheidung nichts mit" _ & chr(13) & "mangelnder Qualifikation noch mit der Bewerbungsgestaltung" & chr(13) & "zu tun hat." thirdP = "Gerne möchten wir Sie in unseren Talent Pool aufnehmen und für" _ & chr(13) & "zukünftige offene Stellen mit Ihnen in Kontakt bleiben. Sofern Sie" _ & chr(13) & "Teil unseres Talent Pools sein möchten, klicken Sie bitte auf den" _ & chr(13) & "folgenden Link " fourthP = "Bitte haben Sie Verständnis für unsere Entscheidung und verstehen" _ & chr(13) & "Sie die Absage nicht als Zweifel an Ihren Qualifikationen. Ihre" _ & chr(13) & "Bewerbungsunterlagen legen wir diesem Schreiben bei." fifthP = "Wir wünschen Ihnen für Ihre berufliche Zukunft weiterhin viel Erfolg." sLink = "https://www.continental.com/de/karriere/jobs-bei-continental/" End Function
Listing 4
Steuerelemente
REM Variablen mit den Namen der REM Steuerelemente versehen Function SetDialogVars() appName = "txtName" appSurname = "txtSurname" jobtitle = "txtJobtitle" startDay = "dtStart" contactName = "txtContactPerson" startHour = "tStarthour" sReject = "rdReject" sAccept = "rdAccept" radioGroup = "applicatonForm" responsibleName = "txtPersonInCharge" addressline1 = "txtAddressline1" addressline2 = "txtAddressline2" zipCode = "txtZip" town = "txtTown" country = "txtCountry" btnOK = "btnOK" btnCancel = "btnCancel" dialog = "Dialog1" libName = "MyLibrary" End Function
Profi-Dialoge
Zum Testen und später beim Arbeiten ist es auf die Dauer zu umständlich, das Makro über Extras | Makros | Makros bearbeiten aufzurufen. Aus diesem Grund sollten Sie im Makroeditor eine Subroutine definieren, die das Dialogfenster aufruft. Haben Sie die Namen der Steuerelemente in Variablen festgehalten, dann sollten Sie in dieser Subroutine gleich den Wert dieser Variablen setzen, also die Funktion aufrufen, die das erledigt (Listing 5).
Listing 5
Dialog starten
REM Dialogfenster aufrufen
Sub StartDialog()
BasicLibraries.LoadLibrary("Tools")
oDialog1 = LoadDialog(libName, dialog)
oDialog1.Execute()
End Sub
Als Nächstes verknüpfen Sie diese Subroutine mit einem Icon. Dazu wechseln Sie im LibreOffice Writer zu Extras | Anpassen und klicken auf das Register Symbolleisten. Um die entsprechende Subroutine zu finden, wählen Sie im Ausklappmenü Kategorie den Eintrag Makros aus und wechseln zu Meine Makros | Bibliothek | Modul | Subroutine. Ein Klick auf den Pfeil nach rechts fügt dem Standardmenü die markierte Subroutine hinzu.
Im rechten Fenster markieren Sie die Subroutine erneut und klicken auf Ändern | Symbol austauschen (Abbildung 2). Nun lässt sich die Subroutine zum Aufruf des Dialogfensters mit einem Icon versehen. Dadurch können Sie das Makro ausführen, sobald Sie ein neues Dokument anlegen.
Eingaben auslesen
Das Auslesen der Daten, die der Anwender ins Dialogfenster eingegeben hat, erfolgt üblicherweise per Knopfdruck (Abbildung 3). In diesem Beispiel geschieht das durch einen Klick auf den Button OK, der die selbst definierte Subroutine ReadDialog() (Listing 6) aufruft und die Steuerelemente wie folgt ausliest:
DIM oCandidateName as Object oCandidateName = oDialog1.GetControl(appName)

Abbildung 3: Um das Auslesen der Eingabefelder per Knopfdruck zu erledigen, wird der OK-Button mit der Subroutine ReadDialog verknüpft.
Listing 6
Daten einlesen
REM Vom User angegebene
REM Daten einlesen
Sub ReadDialog()
REM Hier für jedes Steuerelement, das
REM ausgelesen wird, ein Objekt anlegen
DIM oJobtitle as Object
DIM ostartDay as Object
DIM ostartHour as Object
REM ...
REM Für jedes Objekt eine Variable
REM anlegen, die den vom Anwender
REM eingegebenen Wert abspeichert
DIM sStartHour AS String
DIM sStartDate as String
REM ...
REM Die Variablen definieren,
REM die aus Textbausteinen sowie
REM Benutzereingaben bestehen
DIM isAccepted as boolean
DIM myText as String
DIM sBye as String
DIM oText as Object
REM ...
SetCharVars()
SetBoilerplates()
myText = ""
REM Die einzelnen Steuerelemente den
REM zugehörigen Objekten zuweisen
ostartDay = oDialog1.GetControl(startDay)
ostartHour = oDialog1.GetControl(startHour)
REM ...
REM Hier die vom Anwender eingegebenen
REM Werte in Variablen speichern
dStartDt = GetDate2(ostartDay)
sContactName = GetText(ocontactName)
sStartHour = GetTime(ostartHour)
REM ...
sTask = GetTask2()
isAccepted = SetTextMode(sTask)
sStartDate = DateToString(dStartDt)
applicantAddress = SetAddressField(sAppName, sAppSurname, saddressline1, saddressline2, szipCode, stown, scountry)
myAddress = smycompany & CHR(13) & smycompany2 & CHR(13) & sresponsibleName
myAddress = SetAddressField(myAddress, "", smystreet, "", smyzip, smytown, smycountry)
mySubject = sSubject & sJobtitle
sSalutation = sDear & sAppName & space & sAppSurname & comma
sBye = sGreeting & CHR(13) & CHR(13) & sresponsibleName
oText = InsertText(myAddress)
InsertParagraphs(5, oText)
AppendText(applicantAddress, oText, "Addressee")
InsertParagraphs(2, oText)
InsertDate(oText)
InsertParagraphs(3, oText)
AppendText(mySubject, oText, "Heading 1")
InsertParagraphs(2, oText)
AppendText(sSalutation, oText, "Text Body")
InsertParagraphs(2, oText)
REM ermittelt die Antwortart
If isAccepted Then
myText = SetAcceptance(sJobtitle, sStartDate, sStartHour, sContactName)
AppendText(myText, oText, "Text Body")
Else
myText = SetRejection()
AppendText(myText, oText, "Text Body")
End If
InsertParagraphs(3, oText)
AppendText(sBye, oText, "Text Body")
End Sub
Die eingegebenen Daten sind zu diesem Zeitpunkt im Objekt gespeichert und können bei einer Textbox wie in Listing 7 in einem String abgespeichert werden. Da bei einer Zusage das Datum des Arbeitsbeginns eine wichtige Rolle spielt, darf man das Auslesen des Datums nicht außer Acht lassen. Die selbst definierte Funktion GetDate2() (Listing 8) liest das eingegebene Datum vom Steuerelement aus und gibt es als Datum zurück.
Auch die Uhrzeit, zu der der neue Mitarbeiter am ersten Arbeitstag erscheinen soll, ist variabel und sollte im Dialogfenster abgefragt werden. Da jedoch der Umgang mit Variablen vom Typ Date oder Time nicht immer ganz leicht fällt, wird die Uhrzeit wie ein Objekt behandelt, das Text speichert. Hier verwenden Sie die Funktion GetText(), um die Zeit als String zu speichern.
Listing 7
Textbox auslesen
REM String aus einem Eingabefeld abrufen Function GetText(oField as Object) as String GetText = oField.Text End Function
Listing 8
Datum auslesen
REM Wert eines Datumsfelds auslesen Function GetDate2(oField as Object) AS New com.sun.star.util.Date GetDate2 = oField.getDate() End Function
Die Antwortart bestimmen Sie durch das Anklicken des entsprechenden Radiobuttons. Statt die Werte der Radiobuttons einzeln abzurufen, ermitteln Sie sie bequem mittels einer For-Schleife. So gibt die Funktion GetTask2 (Listing 9) den Namen des Radiobuttons zurück, auf den der Anwender zuvor geklickt hat. Wichtig dabei: Die Radiobuttons müssen derselben Gruppe angehören, anderenfalls gilt es, sie einzeln auszulesen.
Listing 9
Antwortart
REM Ausgewählten Radiobutton ermitteln
Function GetTask2() as String
DIM oCurrent as object
DIM oValues()
DIM sRdBtn as String
oDialog1.getModel().getGroupByName(radioGroup, oValues())
For each oCurrent in oValues()
If oCurrent.state = 1 Then
sRdBtn = oCurrent.Name
Exit For
End If
Next
GetTask2 = sRdBtn
End Function
Bevor das Makro den Brief erstellt, muss es noch wissen, um welche Antwortart es sich handelt. Die Funktion SetTextMode() (Listing 10) überprüft zunächst, ob der Anwender den Zusage– oder Absage-Radiobutton angeklickt hat. Dazu greift die Funktion auf vorhandene String-Methoden zurück, die in einem Tutorial des OpenOffice-Makro-Experten Andrew Pitonyak [4] vorkommen. Der Rückgabewert dieser Funktion ist vom Typ Boolean, was dazu führt, dass sich die If-Abfrage zur Antwortart einfacher gestaltet.
Listing 10
Antwortart
REM Antwortart ermitteln
Function SetTextMode(sTask as String) as Boolean
DIM iResReject as Integer
DIM iResAccept as Integer
DIM isAccepted as boolean
iResReject = InStr(sTask, sReject)
iResAccept = InStr(sTask, sAccept)
If iResReject > 0 Then
isAccepted = False
Elseif iResAccept > 0 Then
isAccepted = True
End If
SetTextMode = isAccepted
End Function
Zur Definition der Adressfelder erhält die Funktion SetAddressField() (Listing 11) als Parameter die entsprechenden Argumente wie Ort, Postleitzahl, Ländername und Name übergeben. Sie baut Absätze in die Ausgabe ein (siehe myAddress und applicantAddress in ReadDialog()).
Auch der String mit dem Betreff (mySubject in ReadDialog()) wird durch Anhängen des zuvor eingegebenen Stellentitels zusammen mit dem dazugehörigen Textbaustein angepasst. Ähnliches erfolgt mit dem Gruß, bei dem der Name des Personalsachbearbeiters zusammen mit dem dazugehörigen Textbaustein einen neuen String bildet (sBye in ReadDialog()).
Listing 11
Adressierung
REM Adressfelder zu einem String verknüpfen Function SetAddressField(n as String, sname as String, a1 as String, a2 as String, zip as String, town as String, c as String) as String DIM addressField as String addressField = n & space & sname & CHR(13) & a1 & CHR(13) & a2 & CHR(13) & zip & space & town & CHR(13) & UCase(c) SetAddressField = addressField End Function
Brief automatisieren
Zum Einfügen eines Texts in ein neues LibreOffice-Writer-Dokument holt die Funktion InsertText() (Listing 12) zunächst den aktuellen View-Cursor vom Controller ab: Er enthält die aktuelle Position der Schreibmarke. Anschließend wird der Text am Anfang des Dokuments eingefügt (Abbildung 4).
Listing 12
Text einfügen
REM Text am Anfang des Dokuments einfügen Function InsertText(s as String) as Object DIM oText As Object DIM oVCurs as Object DIM oCursor as Object oText = ThisComponent.Text oVCurs = ThisComponent.CurrentController.getViewCursor() oCursor = oText.createTextCursorByRange(oVCurs.getStart()) oText.insertString(oCursor,s, False) InsertText = oText End Function

Abbildung 4: Das Bewerber-Tool ermittelt aufgrund des markierten Optionsfelds die passende Antwortart.
Da ein professioneller Brief nicht ohne Absätze auskommt, lassen sich mittels der Funktion InsertParagraphs() eine Anzahl (n) Leerzeilen jeweils an der aktuellen Stelle des Cursors einfügen (Listing 13). Zum Einfügen von Text dient hier neben der bereits erwähnten Methode InsertText() die Methode AppendText() (Listing 14). Hierbei wird dem Text ein Stil zugeordnet, mittels dessen er formatiert und anschließend an der aktuellen Position des Cursors eingefügt wird.
Listing 13
Absätze einfügen
REM Leerzeilen einfügen
Function InsertParagraphs(n as integer, oText as Object)
DIM oVCurs as Object
DIM oCursor as Object
DIM i as Integer
i = 0
oVCurs = ThisComponent.CurrentController.getViewCursor()
oCursor = oText.createTextCursorByRange(oVCurs.getEnd())
Do While i < n
oText.insertControlCharacter(oCursor, com.sun.star.text.ControlCharacter.PARAGRAPH_BREAK, False)
Succ(i)
Loop
End Function
REM Hilfsfunktion: erhöht
REM eine Ganzzahl um 1
Function Succ(iVal as Integer)
iVal = iVal + 1
End Function
Listing 14
Text einfügen
REM Text an der aktuellen REM Cursor-Position einfügen Function AppendText(s as String, oText as Object, style as String) DIM oVCurs as Object DIM oCursor as Object oVCurs = ThisComponent.CurrentController.getViewCursor() oCursor = oText.createTextCursorByRange(oVCurs.getEnd()) oCursor.gotoStartOfParagraph(False) oCursor.gotoEndOfParagraph(True) oCursor.paraStyleName = style oText.insertString(oCursor, s, False) End Function
Die Formatierung des Datums sollte der Sprache des Dokuments entsprechen. Die Funktion InsertDate() (Listing 15) wendet zunächst den eigens dazu definierten Stil MyDate auf einen Absatz an. Außerdem fügt sie das aktuelle Datum ein, indem sie die Spracheinstellungen des Dokuments abruft und das Datum entsprechend formatiert.
Der OpenOffice-Experte Pitonyak hat extra für die Formatierung von Zahlen die Funktion FindCreateNumberFormatStyle() (Listing 16) erstellt, die allerdings nicht immer fehlerfrei läuft. Unter Einsatz dieser Funktion schreibt das Makro das Datum aus, liefert also anstelle des Kurzformats “26.01.22” den “26. Januar 2022”.
Listing 15
Datum einfügen
REM Aktuelles Datum ins
REM Dokument einfügen
Function InsertDate(oText as Object)
DIM oVCurs as Object
DIM oCursor as Object
DIM oDateTime As Object
DIM oFormats as Object
DIM aLocale As New com.sun.star.lang.Locale
oVCurs = ThisComponent.CurrentController.getViewCursor()
oCursor = oText.createTextCursorByRange(oVCurs.getEnd())
oFormats = ThisComponent.NumberFormats
oCursor.gotoStartOfParagraph(False)
oCursor.gotoEndOfParagraph(True)
oCursor.paraStyleName = "MyDate"
oDateTime = ThisComponent.createInstance("com.sun.star.text.TextField.DateTime")
oDateTime.IsFixed = TRUE
REM oDateTime.NumberFormat = FindCreateNumberFormatStyle("DD. MMMM YYYY", ThisComponent)
oDateTime.NumberFormat = oFormats.getStandardFormat(com.sun.star.util.NumberFormat.DATE, aLocale)
oText.insertTextContent(oCursor, oDateTime, FALSE)
End Function
Listing 16
Datumsformat
REM Formatiert das Datum
Function FindCreateNumberFormatStyle(sFormat$, Optional oDoc, Optional locale)
DIM oDocument As Object
DIM aLocale as new com.sun.star.lang.Locale
DIM oFormats As Object
DIM formatNum As Long
oDocument = IIf(IsMissing(oDoc), ThisComponent, oDoc)
oFormats = oDocument.getNumberFormats()
If ( Not IsMissing(locale)) Then
aLocale = locale
End If
formatNum = oFormats.queryKey (sFormat, aLocale, TRUE)
If (formatNum = -1) Then
formatNum = oFormats.addNew(sFormat, aLocale)
If (formatNum = -1) Then
formatNum = 0
End If
End If
FindCreateNumberFormatStyle = formatNum
End Function
Der Hauptteil des Briefs wird wie weiter oben schon erwähnt mittels der Funktion AppendText() realisiert. Zuvor überprüft die If-Abfrage den Rückgabewert aus der Funktion GetTask2() und fügt je nach Ergebnis entweder die passenden Textbausteine für die Zusage (Listing 17) oder die für die Absage (Listing 18) ein.
Zu diesem Zeitpunkt liegt die Variable, die den Arbeitsbeginn enthält, als Typ Date vor. Daher muss das Makro diesen Wert noch in einen lesbaren String umwandeln (Listing 19). Auch am Briefende kommt die Funktion AppendText() zum Einsatz, um den Gruß samt dem Namen des Personalsachbearbeiters auszugeben.
Listing 17
Zusage
REM Textbausteine samt Variablen zu REM einem String verknüpfen, der in REM eine Zusage eingefügt wird Function SetAcceptance(sJob as String, sDate as String, sHour as String, sContact as String) as String DIM s as String SetAcceptanceVars() s = sAcceptance1 & CHR(13) & sJob & sAcceptance2 & CHR(13) & sJobStart1 & CHR(13) & sDate & sJobStart2 s = s & CHR(13) & sContact & sJobBegin1 & sHour & sJobBegin2 SetAcceptance = s End Function
Listing 18
Absage
REM Textbausteine samt Variablen zu REM einem String verknüpfen, der in REM eine Absage eingefügt wird Function SetRejection() as String DIM s as String SetRejectionVars() s = firstP & CHR(13) & secondP & CHR(13) & thirdP & leftP & sLink & rightP & CHR(13) & fourthP & CHR(13) & fifthP SetRejection = s End Function
Listing 19
Eintrittsdatum
REM Unodate-Objekt in eine REM Zeichenkette umwandeln Function DateToString(dt as NEW com.sun.star.util.Date) as String DIM y as Integer DIM m as Integer DIM d as Integer DIM strDate as String DIM separator as String separator = "." ExtractDate(dt, y , m , d) strDate = d & separator & m & separator & y DateToString = strDate End Function
Fazit
Abbildung 5 und Abbildung 6 zeigen die mithilfe des Makros erstellten Anschreiben (im Fall der Absage nur einen Ausschnitt). Dabei reduziert sich der Arbeitsaufwand für den Bearbeiter auf das Eintragen der wenigen benötigten Rahmendaten, woraus eine drastische Zeitersparnis resultiert. Mit etwas Eigeninitiative übertragen Sie das hier dargestellte Vorgehen auch problemlos auf andere wiederkehrende Formschreiben. Alle Listings aus diesem Beitrag finden Sie wie üblich im Download-Bereich zu diesem Artikel. (jlu)
Die Autorin
Anzela Minosi bietet unter dem Pseudonym pczoneminosi auf Fiverr diverse Dienstleistungen rund um IT an. Einer ihrer Gigs ist speziell der LibreOffice-Suite gewidmet.
Infos
-
LibreOffice: https://de.libreoffice.org
-
“OpenOffice.org Macro Information”: https://www.pitonyak.org/oo.php







