Mit etwas Know-how passen Sie Datenbankanwendungen in LibreOffice Base maßgeschneidert an Ihre Bedürfnisse an.
Oft versuchen Benutzer, in einer Datenbanktabelle einen bereits vorhandenen Eintrag erneut abzuspeichern. Erlaubt die Datenbank für das jeweilige Attribut keine doppelten Einträge, wirft sie eine für den Anwender relativ unverständliche Fehlermeldung aus. Hier wären benutzerdefinierte Fehlermeldungen wesentlich benutzerfreundlicher.
Das – und noch viele andere Dinge – lässt sich in LibreOffice Base mit Makros realisieren. Um die nützlichen Codeschnipsel verwenden zu können, brauchen Sie lediglich die LibreOffice-Suite [1] zu installieren (Listing 1). Danach erstellen Sie die Datenbank und verknüpfen die Makros mit den Formularen.
Listing 1
LibreOffice installieren
### beliebiger Desktop $ sudo apt install libreoffice ### KDE $ sudo apt install libreoffice-plasma libreoffice ### Gnome $ sudo apt install libreoffice-gnome libreoffice
Features
Makros können unter anderem Dialogboxen realisieren, Benutzereingaben verarbeiten, Datenbanken manipulieren, Operationen im Dateiverzeichnis vornehmen sowie LibreOffice-Dokumente erstellen und bearbeiten. Sie lassen sich in Bibliotheken und Dokumenten abspeichern, wobei sich Ersteres empfiehlt: In einem Dokument abgespeicherte Makros kann man ausschließlich innerhalb dieses Dokuments einsetzen.
LibreOffice verwaltet Makros hierarchisch. So beinhaltet ein Dokumenten-Container keine oder beliebig viele Bibliotheken. Eine Bibliothek beherbergt hingegen Module und Dialoge. Alle Funktionen und Subroutinen lagern in einem Modul. Ein Makro kann mehrere Subroutinen umfassen, die gegebenenfalls Funktionen anderer Module und Bibliotheken verwenden. Da wir in diesem Artikel nicht auf alle Features von Makros eingehen können, empfehlen wir Ihnen die Lektüre des kostenlosen Tutorials “Macros explained” von Andrew Pitonyak [2].
Schaltbrett
Schaltbretter (englisch: Switchboards) ermöglichen den direkten Zugriff auf ein Formular durch einen Klick auf den entsprechenden Button. Das erspart dem Anwender unter Umständen mehrere Klicks, und er findet sich auf dem Switchboard leichter zurecht (Abbildung 1).
Beim Switchboard gehen Sie zunächst wie bei einem Formular vor, indem Sie links auf Formulare klicken und dann in der Entwurfsansicht ein Formular erstellen. Anschließend fügen Sie für jedes Formular, das über das Switchboard aufgerufen wird, einen Button hinzu. Das Makro selbst erstellen Sie unter Extras | Makros | Makros verwalten | Basic.
Im Fenster Basic Makros sehen Sie alle Makros, auf die Sie innerhalb des LibreOffice-Dokuments zugreifen können. Benötigen Sie ein neues Modul für das Makro, klicken Sie auf den Button Verwalten und anschließend auf Neu. Im daraufhin erscheinenden Fenster legen Sie den Speicherort für das Modul fest und geben ihm einen aussagekräftigen Namen (Abbildung 2).
Für das Erstellen von Makros integriert LibreOffice eine eigene Entwicklungsumgebung (Integrated Development Environment, IDE), die Sie in der Entwurfsansicht eines Formulars unter Extras | Makros | Makros bearbeiten aufrufen.
Eine Funktion namens OpenForm dient dazu, redundanten Code beim Switchboard zu vermeiden. Sie erhält als Argument einen String, der den Namen des Formulars übergibt. Der Button Edit Jobs aus dem Switchboard zeigt auf die Subroutine OpenJobsForm, die die Funktion OpenForm aufruft (Abbildung 3).

Abbildung 3: Die integrierte IDE von LibreOffice Base verfügt über ein Debug-Tool, das beim Aufspüren von Fehlern hilft.
Um den Button mit dem Makro zu verknüpfen, öffnen Sie durch einen Rechtsklick auf den Button das Kontextmenü. Dort klicken Sie auf Steuerelement-Eigenschaften und wechseln in den Reiter Ereignisse. Beim Eintrag Aktion ausführen wählen Sie das gewünschte Makro beziehungsweise die passende Subroutine aus (Abbildung 4).
Formulare erstellen
Das Makro sollte Benutzereingaben validieren, bevor es sie in der Datenbank ablegt. Auf diese Weise lassen sich fehlerhafte Datensätze in der Datenbank verhindern. Als Beispiel dient im Folgenden ein Formular, das nach einem Klick auf den Button Save die Daten von Mitarbeitern in der Datenbank speichert. Dafür gibt es die beiden Tabellen Jobs mit den Jobtiteln (Abbildung 5) und Staff mit den Daten der einzelnen Mitarbeiter (Abbildung 6).
Über den Formularassistenten erstellen Sie nun ein Formular, das die entsprechenden Daten in der Datenbank hinterlegt. Dazu klicken Sie links auf das Formular-Icon und dann auf den Link Formulare unter Verwendung des Assistenten erstellen. Im Assistenten wählen Sie die entsprechende Tabelle aus und geben an, aus welchen Attributen sich das Formular zusammensetzt.
Da in unserem Beispiel die Tabelle Staff auf die Daten der Tabelle Jobs zugreift, empfiehlt es sich, ein Ausklappmenü zu verwenden: Die Mitarbeitertabelle Staff hält zu jedem Mitarbeiter seine Funktionsbezeichnung im Unternehmen fest. Um redundante Einträge in der Datenbank zu vermeiden, genügt es, lediglich die Job-ID des zugehörigen Job-Titels in der Mitarbeitertabelle abzuspeichern (Abbildung 7).
Im Entwurfsmodus befinden sich links die Steuerelemente, die sich per Drag & Drop an der entsprechenden Stelle im Formular ablegen lassen. Das Ausklappmenü realisieren Sie beispielsweise über ein Listenfeld. Um dem Benutzer mitzuteilen, was sich mit dem Listenfeld auswählen lässt, ziehen Sie per Drag & Drop ein Label in das Formular. Sie beschriften es im Kontextmenü des Labels durch einen Klick auf Steuerelement-Eigenschaften und geben im Feld Titel den Namen dafür ein.
Das Listenfeld lässt sich anhand eines SQL-Befehls, einer Tabelle oder Abfrage befüllen. Dazu klicken Sie links auf den Steuerelementeassistenten und ziehen das Listenfeld ins Formular. Im Assistenten wählen Sie zunächst aus, aus welcher Tabelle die Daten stammen, in unserem Fall aus der Tabelle Jobs.
Als Nächstes geben Sie an, welches Attribut der Tabelle im Listenfeld erscheint. Üblicherweise handelt es sich dabei um lesbare Attribute wie Titel oder Namen. Außerdem müssen Sie die Tabellen noch miteinander verknüpfen, damit das Makro beim Betrachten der Datensätze die richtigen Daten lädt. In unserem Beispiel verbinden Sie dabei das Attribut job_id der Tabelle Staff mit dem Attribut ID der Tabelle Jobs.
Formulare überprüfen
Die Validierung der eingegebenen Daten übernimmt in unserem Beispiel das Makro. Dazu erstellen Sie zunächst wie bereits beschrieben ein Modul, das die Subroutine samt Funktionen aufnimmt.
Listing 2 deklariert zunächst in der Subroutine InsertStaff die Variablen lokal, indem es das Schlüsselwort DIM vor den Variablennamen setzt (Zeile 2 bis Zeile 24). Variablen, die auf das Formular oder die Steuerelemente zugreifen, sind üblicherweise vom Typ OBJECT. Die Werte der einzelnen Steuerelemente können beispielsweise Ganzzahlen (INTEGER), Fließkommazahlen (DOUBLE), boolesche Variablen (BOOLEAN) oder Zeichenketten (STRING) sein. LibreOffice unterstützt noch weitere Datentypen, die das Tutorial “Macros explained” auf Seite 37 auflistet.
Listing 2
Prüfmodul
Sub InsertStaff (oEvent AS OBJECT)
# Variablen deklarieren
DIM oDoc AS OBJECT
DIM oDrawpage AS OBJECT
DIM oForm AS OBJECT
DIM oFName AS OBJECT
DIM oLName AS OBJECT
DIM oNotes AS OBJECT
DIM oUsername AS OBJECT
DIM oJob AS OBJECT
DIM fName AS STRING
DIM lName AS STRING
DIM sNotes AS STRING
DIM sUsername AS STRING
DIM sJob AS STRING
DIM oSQL_Statement AS OBJECT
DIM oSQL_Statement2 AS OBJECT
DIM stSql AS STRING
DIM stSql2 AS STRING
DIM oResult AS OBJECT
DIM oResultStaff AS OBJECT
DIM iResult AS INTEGER
DIM iJobId AS INTEGER
DIM oConnection AS OBJECT
# Formular und Subformular in Variablen speichern
oDoc = thisComponent
oDrawpage = oDoc.Drawpage
oForm = oDrawpage.forms.getByName("MainForm")
oSubForm = oForm.getByName("SubForm")
# Datenbankverbindung herstellen
oConnection = oForm.activeConnection()
# Werte aus Steuerelementen in Variablen speichern
oFName = oForm.getByName("txtfirst_name")
fName = oFName.Text
oLName = oForm.getByName("txtlast_name")
lName = oLName.Text
oNotes = oForm.getByName("txtnotes")
sNotes = oNotes.Text
oUsername = oForm.getByName("txtusername")
sUsername = oUsername.Text
oJob = oSubForm.getByName("jobtitles")
sJob = oJob.getCurrentValue()
# Daten aus der Tabelle Staff abrufen
oResultStaff = GetStaffRecord(sUsername)
# Wenn Daten aus der Tabelle Staff abgerufen werden konnten
If oResultStaff.next Then
MsgBox ("Benutzername bereits vergeben!", 0, "Error")
# Mitarbeiterdaten in Tabelle Staff abspeichern
Else
stSql2 = "SELECT * FROM ""Jobs"" " & "WHERE LOWER(""job"") LIKE ? "
oSQL_Statement2 = oConnection.prepareStatement(stSql2)
oSQL_Statement2.setString(1,LCase(sJob))
oResult = oSQL_Statement2.executeQuery(stSql2)
oResult.next
iJobId = oResult.getInt(1)
stSql = "INSERT INTO ""Staff"" " & "(""first_name"", ""last_name"", ""notes"", ""username"", ""job_id"") VALUES(?, ?, ?, ?, ?)"
oSQL_Statement = oConnection.prepareStatement(stSql)
oSQL_Statement.setString(1,fName)
oSQL_Statement.setString(2,lName)
oSQL_Statement.setString(3,sNotes)
oSQL_Statement.setString(4,sUsername)
oSQL_Statement.setInt(5,iJobId)
iResult = oSQL_Statement.executeUpdate
MsgBox ("Daten wurden gespeichert", 0, "Success")
End If
End Sub
Function GetStaffRecord(name AS STRING) As Object
DIM oForm AS OBJECT
DIM oResult AS OBJECT
DIM stSql AS STRING
DIM oSQL_Statement AS OBJECT
DIM oConnection AS OBJECT
# SQL-Statement als String speichern
stSql = "SELECT * FROM ""Staff"" " & "WHERE ""username"" = " & name
oForm = ThisComponent.Drawpage.forms.getByName("MainForm")
# Verbindung zur Datenbank herstellen
oConnection = oForm.activeConnection()
# String in SQL-Statement umwandeln
oSQL_Statement = oConnection.createStatement()
# Abfrage in Datenbank vornehmen
oResult = oSQL_Statement.executeQuery(stSql)
# gefundene Datensätze zurückgeben
GetStaffRecord = oResult
End Function
Um das Formular als Objekt in einer Variablen festzuhalten, benötigen Sie dessen Namen, den Sie im Formularentwurf durch einen Klick auf den Formularnavigator ermitteln. Dort klicken Sie mit der rechten Maustaste auf den Eintrag MainForm und ein weiteres Mal mit der linken Maustaste auf Eigenschaften. Im Feld Name erscheint dann der Name des Formulars. Auf das Formular greifen Sie im Makro zu wie in den Zeilen 26 bis 28 von Listing 2.
Die Namen der Steuerelemente ermitteln Sie in deren Kontextmenüs durch einen Klick auf Steuerelemente-Eigenschaften und lesen den Wert im Feld Name ab. In Zeile 29 sehen Sie, wie Sie ein Steuerelement als Objekt speichern. Anschließend lesen Sie die eingegebenen Werte aus und speichern sie in Variablen, die dem Datentyp des Werts entsprechen (ab Zeile 32). Bei Eingabefeldern vom Typ Text entnehmen Sie den Wert dem Eingabefeld wie in Zeile 40 gezeigt. Ähnlich funktioniert das für den ausgewählten Eintrag eines Listenfelds (Zeile 42).
Da in unserem Fall der Benutzername des Mitarbeiters nur einmal in der Spalte username vorkommen darf, nehmen Sie eine SQL-Abfrage in der Tabelle Staff vor, um zu ermitteln, ob der Benutzername bereits vergeben ist. Diese Prüfung übernimmt in Listing 2 die Funktion GetStaffRecord ab Zeile 68. Dieser Funktion übergeben Sie als Argument den eingegebenen Benutzernamen. Als Ergebnis liefert die Funktion einen gefundenen Datensatz zurück (Zeile 84). Im Kopf der Funktion geben Sie dazu den Datentyp an, den die Funktion zurückgibt (Zeile 70).
Um zu überprüfen, ob die SQL-Abfrage (Zeile 44) mindestens einen Datensatz finden konnte, benutzen Sie eine If-Anweisung (ab Zeile 46). Kommt der Benutzername bereits in der Tabelle vor, geben Sie über die Anweisung MsgBox eine entsprechende Meldung aus (Zeile 47). Andernfalls speichert das Makro aus Listing 2 die Mitarbeiterdaten in die Tabelle Staff. Dazu ermittelt es zunächst die ID des Jobtitels (Zeile 50), fügt sie zusammen mit den anderen Daten in die Tabelle Staff ein (Zeilen 56 bis 63), und gibt zu guter Letzt die Benachrichtigung aus, dass die Daten gespeichert wurden (Zeile 64).
Eingaben löschen
Hin und wieder kommt es vor, dass Anwender sich vertippen oder im Listenfeld falsche Einträge auswählen. Das notwendige Zurücksetzen der Werte kann dann ein Makro übernehmen. Der Code aus Listing 3 speichert dazu zunächst das Formular MainForm sowie die Eingabefelder in Variablen ab. Beim Zurücksetzen übergibt er dem Eingabefeld einen leeren String und teilt anschließend dem Formular den neuen Wert durch einen Aufruf von commit mit.
Listing 3
Eingaben löschen
Sub ResetForm (oEvent AS OBJECT)
DIM oForm AS OBJECT
DIM oSubForm AS OBJECT
DIM oDocument As Object
DIM oDispatcher As Object
DIM oFName AS OBJECT
DIM oLName AS OBJECT
DIM oNotes AS OBJECT
DIM oUsername AS OBJECT
DIM oJob AS OBJECT
DIM oStaffId AS OBJECT
oForm = ThisComponent.Drawpage.forms.getByName("MainForm")
oSubForm = oForm.getByName("SubForm")
# Eingabefelder zurücksetzen
oFName = oForm.getByName("txtfirst_name")
oFName.Text = ""
oFName.commit()
oLName = oForm.getByName("txtlast_name")
oLName.Text = ""
oLName.commit()
oNotes = oForm.getByName("txtnotes")
oNotes.Text = ""
oNotes.commit()
oUsername = oForm.getByName("txtusername")
oUsername.Text = ""
oUsername.commit()
oStaffId = oForm.getByName("txt_idStaff")
oStaffId.Text = ""
oStaffId.commit()
End Sub
Daten durchlaufen
Statt der Navigationsleiste kann ebenso gut ein Makro die Datensätze anzeigen. Für die Iteration benötigen Sie zwei global deklarierte Variablen: ein Zähler sowie eine Variable, die den maximalen Wert des Zählers festhält (Listing 4).
Listing 4
Zählervariable
GLOBAL counter AS LONG GLOBAL maxCounter AS LONG
Außerdem erstellen Sie einen Button namens Reset und verknüpfen ihn mit der Subroutine aus Listing 5. Sie setzt den globalen Zähler counter zurück und ruft die Funktion SetMaxCounter auf, die die Zahl der Datensätze ermittelt. Diese Zahl landet in der globalen Variablen maxCounter (Listing 6). Generell ist es wichtig, beim Datensatz die Methode next aufzurufen (Zeile 16): Die Datensätze liegen in einem Array, sodass Sie den ersten Datensatz durch den Aufruf von .next erhalten. Außerdem liefert die verwendete SQL-Abfrage lediglich die Zahl der Datensätze zurück. Die lässt sich daher durch den Befehl Datensatz.getInt(1) abrufen (Zeile 18).
Listing 5
Zähler zurücksetzen
Sub ResetCounter (oEvent AS OBJECT) counter = 0 SetMaxCounter End Sub
Listing 6
Zähler ermitteln
Function SetMaxCounter()
DIM oForm AS OBJECT
DIM oResult AS OBJECT
DIM stSql AS STRING
DIM oSQL_Statement AS OBJECT
DIM oConnection AS OBJECT
# Formular in Variable abspeichern
oForm = ThisComponent.Drawpage.forms.getByName("MainForm")
# Verbindung zur Datenbank aufbauen
oConnection = oForm.activeConnection()
# Zahl der Datensätze ermitteln
stSql = "SELECT COUNT(""ID"") as count_staff FROM ""Staff"" "
oSQL_Statement = oConnection.createStatement()
# SQL-Abfrage vornehmen
oResult = oSQL_Statement.executeQuery(stSql)
oResult.next
# Abfrageergebnis in globaler Variable speichern
maxCounter = oResult.getInt(1)
End Function
Sie benötigen einen weiteren Button namens next, um durch die Datensätze zu iterieren. Dazu klicken Sie auf das Steuerelement Schaltfläche und ziehen es ins Formular. Den so erzeugten Button verknüpfen Sie in unserem Beispiel mit der Subroutine NextItem aus Listing 7. Genauso wie beim Zurücksetzen des Formulars definiert auch diese Subroutine zunächst die Variablen der einzelnen Eingabefelder, um sie manipulieren zu können.
Danach erfolgt der Aufruf der Funktion CheckStaffRecord, die Listing 8 zeigt. Sie stellt zunächst sicher, dass der aktuelle Stand des Zählers nicht den Höchstwert übersteigt, und ruft dann die Funktion GetStaffRecord auf. Das Entscheidende an dieser Methode ist die SQL-Anweisung in Zeile 24, die dafür sorgt, dass der gewünschte Datensatz der Zeilennummer (counter) entspricht. Danach speichert die Funktion die Daten aus dem gefundenen Datensatz in den einzelnen Eingabefeldern ab.
Listing 7
Über Datensätze iterieren
Sub NextItem (oEvent AS OBJECT)
DIM oForm AS OBJECT
DIM oStaffID AS OBJECT
DIM oFName AS OBJECT
DIM oLName AS OBJECT
DIM oNotes AS OBJECT
DIM oUsername AS OBJECT
DIM oStaff AS OBJECT
DIM indexStaff AS INTEGER
oForm = ThisComponent.Drawpage.forms.getByName("MainForm")
# Datensatz aus der Tabelle Staff abrufen
oStaff = CheckStaffRecord()
If oStaff.next Then
# Eingabefelder mit Daten füllen
oStaffID = oForm.getByName("txt_idStaff")
oStaffID.Text = oStaff.getInt(1)
oStaffID.commit()
oFName = oForm.getByName("txtfirst_name")
oFName.Text = oStaff.getString(2)
oFName.commit()
oLName = oForm.getByName("txtlast_name")
oLName.Text = oStaff.getString(3)
oLName.commit()
oNotes = oForm.getByName("txtnotes")
oNotes.Text = oStaff.getString(5)
oNotes.commit()
oUsername = oForm.getByName("txtusername")
oUsername.Text = oStaff.getString(6)
oUsername.commit()
Else
MsgBox ("Keine weiteren Daten verfügbar.", 0, "Error")
End If
End Sub
Listing 8
Datensatz auslesen
# Setzt den Zähler und liefert einen
# Datensatz aus der Tabelle Staff zurück
Function CheckStaffRecord() As Object
DIM oStaff AS OBJECT
If counter < maxCounter Then
oStaff = GetStaffRecord(counter)
counter = counter + 1
Else
counter = 0
oStaff = GetStaffRecord(counter)
counter = counter + 1
End If
CheckStaffRecord = oStaff
End Function
# Ruft einen Datensatz aus der Tabelle
# Staff an einer bestimmten Stelle ab
Function GetStaffRecord(id AS INTEGER) As Object
DIM oForm AS OBJECT
DIM oResult AS OBJECT
DIM stSql AS STRING
DIM oSQL_Statement AS OBJECT
DIM oConnection AS OBJECT
stSql = "SELECT * FROM ""Staff"" " & "LIMIT 1 OFFSET " & id
oForm = ThisComponent.Drawpage.forms.getByName("MainForm")
oConnection = oForm.activeConnection()
oSQL_Statement = oConnection.createStatement()
oResult = oSQL_Statement.executeQuery(stSql)
GetStaffRecord = oResult
End Function
Dateien kopieren
In Formularen verlinkte Bilder befinden sich meist an unterschiedlichen Orten. Um alle Bilder im selben Pfad abzulegen, bedarf es Funktionen, um auf Dateien und Ordner zuzugreifen (Abbildung 8).
Zunächst erstellen Sie einen Button namens save, der zusätzlich zu den Datenbankoperationen die Bilder in ein Arbeitsverzeichnis kopiert. Dazu definieren Sie die Subroutine InsertItems(oEvent AS OBJECT) (Listing 9) und verknüpfen sie mit dem Button.
Listing 9
Datensatz erstellen
# Erstellt einen neuen Datensatz in der
# Tabelle Staff und aktualisiert diese
Sub InsertItems (oEvent AS OBJECT)
DIM iResult AS INTEGER
DIM newPicturePath AS STRING
DIM oPic AS OBJECT
DIM sPic AS STRING
[...]
oPic = oForm.getByName("Image Control 1")
sPic = oPic.ImageUrl
[...]
iResult = InsertItem (sArticleName, bInStock, dPrice, sPic, dSPU, sSKU, sEAN, 0, 0)
newPicturePath = SavePicture (sPic,iResult)
UpdateItem (iResult, newPicturePath)
End Sub
Beim Speichern der Daten aus den Eingabefeldern gehen Sie so wie in Listing 10 vor. Die Funktion InsertItem gibt nach dem Speichern des Datensatzes eine ID vom Typ INTEGER zurück, die der ID des soeben abgespeicherten Datensatzes entspricht. Diese ID übergibt sie zusammen mit der URL, die sie dem Steuerelement für Bilder entnimmt, der Funktion SavePicture.
Listing 10
Speichern des Artikels
# Speichert einen Artikel in der Tabelle Items ab
Function InsertItem (n AS STRING, stock AS BOOLEAN, p AS DOUBLE, pp AS STRING, spu AS DOUBLE, sku AS STRING, ean AS STRING, s AS INTEGER, a AS INTEGER) AS INTEGER
DIM oConnection AS OBJECT
DIM oForm AS OBJECT
DIM iResult AS INTEGER
DIM stSql AS STRING
DIM oSQL_Statement AS OBJECT
stSql = "INSERT INTO ""Items"" " & "(""name"", ""in_stock"", ""price"", ""picture_path"", ""smallest_purchasing_unit"", ""sku"", ""ean"", ""status"", ""assigned"") VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?)"
oForm = ThisComponent.Drawpage.forms.getByName("MainForm")
oConnection = oForm.activeConnection()
oSQL_Statement = oConnection.prepareStatement(stSql)
oSQL_Statement.setString(1,n)
oSQL_Statement.setBoolean(2,stock)
oSQL_Statement.setDouble(3,p)
oSQL_Statement.setString(4,pp)
oSQL_Statement.setDouble(5,spu)
oSQL_Statement.setString(6,sku)
oSQL_Statement.setString(7,ean)
oSQL_Statement.setInt(8,s)
oSQL_Statement.setInt(9,a)
iResult = oSQL_Statement.executeUpdate
InsertItem = iResult
End Function
# Aktualisiert beim Artikel den Pfad des Bilds
Function UpdateItem (i AS INTEGER, pp AS STRING) AS INTEGER
DIM oConnection AS OBJECT
DIM oForm AS OBJECT
DIM iResult AS INTEGER
DIM stSql AS STRING
DIM oSQL_Statement AS OBJECT
stSql = "UPDATE ""Items"" " & " SET ""picture_path"" = ? " & "WHERE ID = ?"
oForm = ThisComponent.Drawpage.forms.getByName("MainForm")
oConnection = oForm.activeConnection()
oSQL_Statement = oConnection.prepareStatement(stSql)
oSQL_Statement.setString(1,pp)
oSQL_Statement.setInt(2,i)
iResult = oSQL_Statement.executeUpdate
UpdateItem = iResult
End Function
SavePicture (Listing 11) ruft wiederum die Funktion SetPath auf. Sie legt das global definierte (GLOBAL workingPath AS STRING) Arbeitsverzeichnis fest, sodass mehrere Funktionen darauf zugreifen können.
Listing 11
Bild abspeichern
# Speichert das Bild eines Artikels
# ab und gibt den neuen Pfad zurück
Sub SavePicture (pic AS STRING, itemId AS INTEGER) AS STRING
DIM picturepath AS STRING
DIM fileName AS STRING
DIM extension AS STRING
DIM newFileName AS STRING
SetPath
MsgBox ("old-filename: " & pic & CHR(13), 0, "Pla")
picturepath = workingPath & itemId
fileName = FileNameoutofPath(GetFileNameWithoutExtension(pic))
extension = GetFileNameExtension(pic)
filename = fileName & "." & extension
If NOT FileExists(picturepath) Then
MkDir picturepath
End If
picturepath = picturepath & "/" & filename
If NOT FileExists(picturepath) Then
FileCopy(pic, picturepath)
End If
newFileName = FileNameoutofPath(GetFileNameWithoutExtension(picturepath)) & "." & extension
SavePicture = newFileName
End Sub
LibreOffice stellt bereits vordefinierte Pfade zur Verfügung, die sowohl unter Linux als auch unter Windows gelten. So steht in Listing 12 die Variable $(home) (Zeile 6) sowohl für das Home-Verzeichnis unter Linux als auch für den Ordner Dokumente und Einstellungen unter Windows. Das Tutorial “Macros explained” nennt auf Seite 193 noch weitere Pfadvariablen.
Listing 12
Speicherort festlegen
# Speicherort für Bilder
# als String festlegen
Function SetPath()
DIM oPathSub
DIM name
name = "$(home)"
oPathSub = CreateUnoService("com.sun.star.util.PathSubstitution")
workingPath = oPathSub.getSubstituteVariableValue(name)
workingPath = workingPath & "/" & "warehouse" & "/" & "item-"
End Function
In unserem Beispiel landet das Bild im Unterverzeichnis warehouse/item-ID/ (Listing 11, Zeile 10). Mit anderen Worten: Jeder Artikel erhält seinen eigenen Ordner, um die Bilder des Artikels dort abzuspeichern.
Nach dem Definieren des Verzeichnisses für die einzelnen Artikel kommt zum Pfad noch der Dateiname samt Erweiterung des Bilds hinzu. Der Dateiname lässt sich mittels GetFileNameWithoutExtension(Datei) extrahieren (Listing 11, Zeile 11), GetFileNameExtension(Datei) ermittelt die Dateierweiterung (Zeile 12). Das Kopieren des Bilds von A nach B übernimmt die Funktion FileCopy (Zeile 19).
Fazit
Wie unsere Beispiele zeigen, erreichen Makros schnell eine beachtliche Länge und werden dann unübersichtlich. Von daher sollten Sie so wenige wie möglich einsetzen, damit die Datenbanksoftware fehlerfrei funktioniert. Zum Erlernen der Makrosprache empfiehlt sich neben dem bereits mehrfach erwähnten Tutorial “Macros explained” das Base-Handbuch [3] des LibreOffice-Teams. (jlu)
Infos
-
LibreOffice: https://de.libreoffice.org
-
“Macros explained”: https://www.uni-due.de/~abi070/ooo.html
-
LO-Base-Handbuch: https://wiki.documentfoundation.org/images/1/1a/Base_Gesamtband_einseitig_V62.pdf











