Python in LibreOffice Calc: Formular auslesen und auswerten
In diesem Projekt geht es um ein überschaubares, gut verständliches Python-Skript, das zeigt, wie man mit einem Formular in LibreOffice Calc arbeitet und die eingegebenen Daten in ein Tabellenblatt speichert.
Wir nutzen dafür ein Formular mit ganz typischen Elementen wie:
-
Textfeldern
-
Zahlenfeldern
-
Listen
-
Checkboxen
-
Radiobuttons
-
und einem Datumsfeld
Das Skript liest diese Formulareingaben aus, prüft die wichtigsten Werte (zum Beispiel ob ein Name eingetragen wurde oder ob der Betrag größer als 0 ist) und schreibt die Daten anschließend Zeile für Zeile in das Tabellenblatt „Daten“.
Zusätzlich gibt es:
-
einfache Fehlermeldungen, wenn etwas fehlt
-
eine kurze Rückmeldung nach dem Speichern
-
und ein automatisches Zurücksetzen des Formulars
Das Ganze ist bewusst nicht kompliziert aufgebaut, sondern so geschrieben, dass man den Ablauf gut nachvollziehen und das Script leicht an die eigenen Bedürfnisse anpassen kann.
Ideal also, um den Einstieg in Formulare + Python in LibreOffice zu finden oder um ein kleines Alltagsproblem pragmatisch zu lösen.
⬇️ Den vollständigen Code kannst du weiter unten über den Downloadlink herunterladen.
Hinweis: Die gezeigten Code-Beispiele dienen Lernzwecken. Änderungen und Einsatz erfolgen auf eigene Verantwortung – bitte teste alles vorab in einer Kopie deiner Dateien.
🔹 Wo müssen Python-Skripte in LibreOffice liegen?
LibreOffice bringt Python bereits mit – du musst also kein eigenes Python installieren, um Makros nutzen zu können.
Damit LibreOffice dein Skript erkennt, muss es jedoch im richtigen Benutzerverzeichnis liegen.
📁 Pfade für Python-Makros (Benutzerprofil)
Windows
🐧 Linux
🍎 macOS
Hinweis:
Ersetze<DEIN_USERNAME>entsprechend durch deinen tatsächlichen Benutzernamen.
🔹 Wichtiger Hinweis: Ordner ggf. selbst anlegen
Gerade bei einer frischen LibreOffice-Installation ist es völlig normal, dass die OrdnerScripts und python noch nicht existieren.
👉 In diesem Fall kannst (und sollst) du sie einfach selbst anlegen:
-
Groß- und Kleinschreibung beachten (
Scripts, nichtscripts) -
LibreOffice nach dem Anlegen der Ordner neu starten
LibreOffice erkennt die Ordner automatisch beim nächsten Start.
🔹 Wie wird das Skript ausgeführt?
Sobald dein Python-Skript im richtigen Ordner liegt und LibreOffice neu gestartet wurde, findest du es unter:
Dort wird deine .py-Datei als Ordner angezeigt, und darunter die enthaltene Makro-Funktion, die du ausführen kannst.
🔹 Code – Schritt für Schritt erklärt
Teil 1: Imports und Vorbereitung
import uno
from com.sun.star.util import Date as UnoDate
from com.sun.star.awt.MessageBoxType import INFOBOX, WARNINGBOX, ERRORBOX
Wir importieren das uno Modul, um mit LibreOffice zu kommunizieren. Zusätzlich laden wir spezielle Hilfsmittel: UnoDate hilft uns später beim Umgang mit Datumsfeldern, und die Importe aus MessageBoxType benötigen wir, um dem Programm zu sagen, ob eine Nachricht nur eine Info, eine Warnung oder ein Fehler ist.
Teil 2: Die Helfer-Funktion für Nachrichten
def show_message(message, title="Hinweis", message_type="info"):
Wir definieren eine eigene Funktion namens show_message. Da Python in Calc kein einfaches print Fenster hat, bauen wir uns hier einen Wrapper, um später mit nur einer Zeile Code Popup-Fenster aufrufen zu können.
ctx = XSCRIPTCONTEXT.getComponentContext()
sm = ctx.ServiceManager
toolkit = sm.createInstanceWithContext("com.sun.star.awt.Toolkit", ctx)
Wir verbinden uns mit dem internen Service-Manager von LibreOffice und erstellen ein "Toolkit". Das ist der Werkzeugkasten, der nötig ist, um grafische Elemente wie Fenster auf den Bildschirm zu zeichnen.
parent = XSCRIPTCONTEXT.getDesktop().getCurrentFrame().getContainerWindow()
Hier holen wir uns das Hauptfenster der LibreOffice-Anwendung (den Desktop-Frame). Das ist wichtig als "Eltern-Fenster" für unsere Messagebox, damit diese stabil angezeigt wird und nicht im Hintergrund verschwindet oder Fehler verursacht.
if message_type == "warning":
box_type = WARNINGBOX
elif message_type == "error":
box_type = ERRORBOX
else:
box_type = INFOBOX
Wir prüfen, welche Art von Nachricht angezeigt werden soll. Je nach Wunsch ("warning", "error" oder "info") wählen wir den passenden internen Typ aus, damit LibreOffice das richtige Symbol (Ausrufezeichen, rotes X oder Info-i) anzeigt.
try:
box = toolkit.createMessageBox(parent, box_type, 1, title, message)
box.execute()
except:
pass
Schließlich erstellen wir die Messagebox mit unserem Text und Titel und führen sie mit .execute() aus. Der try-Block sorgt dafür, dass das Skript nicht abstürzt, falls beim Erzeugen des Fensters etwas Unerwartetes passiert.
Teil 3: Die Hauptfunktion und Zugriff auf das Formular
def ausgabe_speichern(event=None):
Das ist unsere Hauptfunktion, die wir später mit dem Button im Formular verknüpfen. Das Argument event wird von LibreOffice automatisch übergeben und enthält Informationen über das Klick-Ereignis.
doc = XSCRIPTCONTEXT.getDocument()
sheet_daten = doc.Sheets.getByName("Daten")
sheet_eingabe = doc.Sheets.getByName("Eingabe")
Wir greifen auf das aktuelle Dokument zu und speichern Referenzen auf unsere zwei Tabellenblätter: "Daten" (wo wir speichern wollen) und "Eingabe" (wo unser Formular liegt).
formular = event.Source.Model.Parent
Das ist der entscheidende Schritt, um an die Eingabefelder zu kommen. event.Source ist der Button, der geklickt wurde. Sein Parent (Elternteil) ist der Formular-Container, in dem alle anderen Felder (Textfelder, Checkboxen etc.) liegen.
Teil 4: Validierung (Der "Türsteher")
txt_name_ctrl = formular.getByName("txt_name")
name = txt_name_ctrl.Text
Wir suchen das Textfeld mit dem Namen "txt_name" und lesen dessen Inhalt über die Eigenschaft .Text aus.
if not name or name.strip() == "":
show_message("Bitte gib einen Namen ein!", "Fehlende Eingabe", "error")
return
Wir prüfen, ob der Name leer ist oder nur aus Leerzeichen besteht (strip). Wenn ja, zeigen wir eine Fehlermeldung an und beenden die gesamte Funktion sofort mit return. Das verhindert, dass unvollständige Daten gespeichert werden.
num_betrag_ctrl = formular.getByName("num_betrag")
betrag = num_betrag_ctrl.Value
Wir holen uns das Zahlenfeld für den Betrag. Wichtig: Hier nutzen wir .Value statt .Text, da wir den echten numerischen Wert zum Rechnen brauchen.
if betrag <= 0:
show_message("Der Betrag muss größer als 0 sein!", "Ungültiger Betrag", "error")
return
Auch hier eine Sicherheitsprüfung: Wenn der Preis 0 oder negativ ist, brechen wir mit einer Fehlermeldung ab.
Teil 5: Daten auslesen
try:
auswahl = formular.getByName("lst_auswahl").CurrentValue
if not auswahl:
auswahl = "Sonstiges"
except:
auswahl = "-"
Wir lesen das Listenfeld aus. Hier nutzen wir .CurrentValue, um den gewählten Eintrag zu bekommen. Falls nichts gewählt ist oder ein Fehler auftritt, setzen wir einen Standardwert ("Sonstiges" oder "-"), damit das Skript weiterläuft.
try:
raw_date = formular.getByName("date_datum").Date
if raw_date.Year == 0:
datum_str = "Kein Datum"
else:
datum_str = f"{raw_date.Day:02d}.{raw_date.Month:02d}.{raw_date.Year}"
except:
datum_str = "Fehler"
Wir greifen auf das Datumsfeld zu. LibreOffice gibt ein Datums-Objekt zurück. Wenn das Feld leer ist, ist das Jahr oft 0. Wir fangen das ab und formatieren das Datum ansonsten sauber als String im Format "TT.MM.JJJJ".
ist_bar = formular.getByName("opt_bar").State == 1
zahlart = "Bar" if ist_bar else "Karte"
Wir prüfen den Status des "Bar"-Radiobuttons. Die Eigenschaft .State ist 1, wenn der Punkt gesetzt ist. Wenn ja, speichern wir "Bar", ansonsten gehen wir davon aus, dass es "Karte" ist.
chk_beleg = formular.getByName("chk_beleg")
hat_beleg = "Ja" if chk_beleg.State == 1 else "Nein"
chk_rabatt = formular.getByName("chk_rabatt")
ist_rabatt = "Ja" if chk_rabatt.State == 1 else "Nein"
Ähnlich wie bei den Radiobuttons fragen wir hier die Checkboxen ab. Ist der .State gleich 1 (Haken gesetzt), speichern wir "Ja", sonst "Nein".
Teil 6: Speichern in der Datenbank-Tabelle
curs = sheet_daten.createCursor()
curs.gotoEndOfUsedArea(False)
neue_zeile = curs.RangeAddress.EndRow + 1
Wir erzeugen einen Cursor im Daten-Blatt und springen ans Ende des benutzten Bereichs. So ermitteln wir dynamisch die Nummer der ersten komplett leeren Zeile, damit wir keine alten Daten überschreiben.
sheet_daten.getCellByPosition(0, neue_zeile).String = datum_str
sheet_daten.getCellByPosition(1, neue_zeile).String = name
sheet_daten.getCellByPosition(2, neue_zeile).String = auswahl
sheet_daten.getCellByPosition(3, neue_zeile).String = zahlart
sheet_daten.getCellByPosition(4, neue_zeile).Value = betrag
sheet_daten.getCellByPosition(5, neue_zeile).String = hat_beleg
sheet_daten.getCellByPosition(6, neue_zeile).String = ist_rabatt
Jetzt schreiben wir die gesammelten Daten Zelle für Zelle in die neue Zeile. getCellByPosition erwartet erst die Spaltennummer (0=A, 1=B…) und dann die Zeilennummer. Beim Betrag (Spalte 4) nutzen wir .Value, bei allen anderen Texten .String.
Teil 7: Feedback und Reset
feedback_text = f"✅ Gespeichert: {name} - {auswahl} ({betrag:.2f} €)"
sheet_eingabe.getCellRangeByName("A20").String = feedback_text
Wir bauen einen Bestätigungstext zusammen, wobei wir den Betrag auf zwei Nachkommastellen formatieren (:.2f). Diesen Text schreiben wir in Zelle A20 unter das Formular, damit der Nutzer sieht, dass es geklappt hat.
txt_name_ctrl.Text = ""
num_betrag_ctrl.Value = 0
chk_beleg.State = 0
chk_rabatt.State = 0
formular.getByName("opt_bar").State = 1
Um das Formular für den nächsten Kunden vorzubereiten, setzen wir alle Felder zurück. Textfelder werden geleert, Zahlen auf 0 gesetzt und Checkboxen entmarkiert. Der Radiobutton wird standardmäßig wieder auf "Bar" gesetzt.
return None
Wir beenden die Funktion ordnungsgemäß.
Teil 8: Sichtbarkeit einschränken (Optional, aber empfohlen)
Füge diese Zeile ganz am Ende deines Skripts ein:
g_exportedScripts = (ausgabe_speichern,)
Dies ist eine spezielle Variable für LibreOffice. Wir legen damit fest, welche Funktionen im Makro-Menü überhaupt sichtbar sein sollen. In diesem Fall wollen wir nur ausgabe_speichern anzeigen. Die Helfer-Funktion show_message wird dadurch "versteckt", damit der Nutzer sie nicht versehentlich direkt ausführt.
Achte unbedingt auf das Komma am Ende in der Klammer: (ausgabe_speichern,). Das ist Python-Syntax. Ohne das Komma ist es nur eine Klammer um einen Namen, mit Komma ist es ein "Tupel" (eine Liste). Ohne das Komma funktioniert es nicht!
Hier habt Ihr den Code noch als Downloaddatei:
Download LibreOffice Calc – Formular-mit-Python-auslesen.zip
Download Formular_auslesen_pyton_script.zip
Vergesst bitte nicht ein Like auf YouTube dazulassen, wenn Ihr meinen Content nützlich findet 🙂

