Umsteigen auf OpenOffice: Von VBA zu OpenOffice-Basic

01.08.2006 von Rene Martin
Wer von Microsoft Office auf OpenOffice migrieren will, steht vor einem Problem – zumindest wenn er viele Makros und Scripts mit VBA erstellt hat. Wir zeigen die wichtigsten Unterschiede und geben Hinweise zur Umstellung der Scripts.

Mit dem Durchbruch des Open-Source-Betriebssystems Linux fand das kostenlose OpenOffice.org (im Folgenden OOo genannt) und damit auch das von Sun unterstützte StarOffice mehr und mehr Nutzer. Ebenso wie bei MS Office liegt eine Basic-Sprache darunter, mit der die Applikation (von innen und außen) gesteuert werden kann.

Bislang gibt es aber noch sehr wenige Quellen zu OOo-Basic. Dieser Artikel stellt das Objektmodell vor, zeigt, wie man an die Befehle gelangt und geht der Frage nach, ob sich ein Umstieg von VBA nach OOo-Basic lohnt.

VBA versus OOo-Basic

In diesem Artikel zeigen wir am Beispiel eines Reporting-Tools für StarCalc in OpenOffice.org, welche Ähnlichkeiten, Vorteile und Nachteile OOo-Basic gegenüber VBA bietet. Dabei stehen als zentrale Elemente der Sprachkern, Dialoge und der Zugriff auf OOo-Calc im Vordergrund.

Das fertige Reporting-Tool finden Sie auf der CD herunterladen. Es ist sehr einfach aufgebaut:

Dialoge

An ein Calc-Dokument soll ein Dialog gebunden werden. Über Extras / Makros / Makro gelangen Sie in den Basic-Editor, wo Sie einen neuen Dialog erstellen. Im Gegensatz zu VBA finden sich dort mehr Steuerelemente: Datumsfelder, nummerische Felder, Fortschrittsbalken oder Dateiauswahlfelder, um nur einige zu nennen. Die Eigenschaften werden – ähnlich wie in VBA – über ein Feld festgelegt.

Um nun den Dialog zu starten, erstellen Sie in einem Modul ein Makro mit folgenden Befehlen:

Public Dlg As Object
Sub Start
DialogLibraries.LoadLibrary("Standard")
Dlg = CreateUnoDialog(DialogLibraries.Standard.dlgVerkaeufer)
Dlg.Execute()

Dabei ist „Standard“ die Bibliothek, in der sich der Dialog befindet (es kann selbstredend auch eine andere Bibliothek sein), und dlgVerkaeufer, der Name des Dialogs.

Der Sprachkern

Um den Dialog dynamisch halten zu können, schreibt man in einem Modul Prozeduren und Funktionen. Der Sprachkern von OOo-Basic unterscheidet sich nur geringfügig von anderen Basic-Dialekten, insbesondere von VBA:

Fehlende Sprachelemente

Die Unterschiede zwischen VBA und OOo-Basic sind im Sprachkern sehr gering. Als Hauptunterschied bleibt zu nennen, dass erfahrene VBA-Programmierer einige Sprachelemente in OOo-Basic vermissen werden:

Starten des Dialogs

Durch Deklaration und Initialisierung einer Objektvariable starten Sie den Dialog. Und so kann ein Makro erstellt werden, das Kontrollfelder (Steuerelemente) ein- und ausblendet, aktiviert und deaktiviert, Beschriftungen verändert und so weiter (siehe Listing 1). Die Ereignisprozeduren in den Modulen werden über eine Schaltfläche an die entsprechenden Ereignisse der Kontrollfelder gebunden.

Sub lstListe_Change
With Dlg
.getControl("cmdAendern").Label = "Daten ändern"
.getControl("txtZielvorgabe").Enable = False
.getControl("cboVerkaeufer").Enable = False
.getControl("txtNeuerVerkaeufer").Visible = False
.getControl("lblNeuerVerkaeufer").Visible = False
.getControl("cmdNeu").Model.Label = "Neuer Verkäufer"

If .getControl("lstListe").selectedItemPos > 0 Then
.getControl("cmdAendern").Model.Enabled = True
.getControl("cmdLoeschen").Model.Enabled = True
Else
.getControl("cmdAendern").Model.Enabled = False
.getControl("cmdLoeschen").Model.Enabled = False
End If
End With
End Sub

Die API

Bis hierher dürfte für den versierten VBA-Programmierer die etwas andere Entwicklungsumgebung noch keine Schwierigkeit darstellen. Problematischer wird es jedoch, wenn es darum geht, Daten in ein Tabellenblatt einzutragen oder auszulesen, neue Tabellenblätter zu erstellen, zu formatieren und so weiter – kurzum das, was in MS Office durch das Objektmodell einer jeden Applikation beschrieben wird.

Das Komponentenmodell von OOo heißt „API“ (Application Programming Interface). Mit ihrer Hilfe wird OOo automatisiert. Die API stellt eine Definition aller Objekte und Interfaces zur Verfügung, die angesteuert werden können. Sie lässt sich aber auch von außen automatisieren, das heißt von VS.NET, Java oder C++. Dies wiederum wird durch die Technologie mit dem Namen UNO (Universal Network Objects) ermöglicht (vergleichbar mit COM).

Services

Einer der zentralen Unterschiede zwischen VBA und OOo-Basic ist, dass OOo kein geschlossenes Objektmodell zur Verfügung stellt, sondern Services, die hinzugeladen werden können und müssen.

Ein Service ist – anders als ein Objekt – nicht direkt aufrufbar. Man muss eine Variable vom Typ Object deklarieren, um UNO in StarOffice zu verwenden. Durch die Initialisierung erhält sie den Verweis auf den gewünschten Service.

Dim Obj As Object
Obj = createUnoService("com.sun.star.frame.Desktop")

Über diesen Aufruf wird beispielsweise ein Verweis auf die StarOffice-Applikation hergestellt. Einige Services stehen nur in einer gewissen Umgebung (Dokument, Arbeitsblatt, …) zur Verfügung, andere Services hängen nicht von einer entsprechenden Umgebung ab. Sie werden mit der Methode createUnoService() erstellt.

Desktop

Beim Umgang mit Dokumenten kommen im Wesentlichen zwei Services zum Einsatz:

Der zentrale Service ist com.sun.star.frame.Desktop. Er stellt die Funktionen für das Rahmenobjekt von StarOffice zur Verfügung, unter dem sich alle Dokumentfenster öffnen lassen. Damit wird deutlich, dass alle Befehle, die der Benutzer über das Menü Datei ausführt, über diesen Service ablaufen.

Der Service com.sun.star.frame.Desktop steht mit dem Start von StarOffice automatisch zur Verfügung. Dazu erzeugt StarOffice ein Objekt, das über den globalen Namen StarDesktop erreichbar ist. Es muss nicht explizit hinzugeladen werden.

Die Basisfunktionalität für die einzelnen Dokumentobjekte liefert der Service com.sun.star.document.OfficeDocument. Er bietet die Methoden zum Speichern, Exportieren und Drucken von Dokumenten.

Schnittstellen (Interfaces)

Neben den Begriffen Modul und Service führt UNO den Begriff der Schnittstelle (Interface) ein. Ein Interface fasst mehrere Methoden zusammen. Streng genommen unterstützt ein Service in UNO keine Methoden, sondern Schnittstellen, die wiederum verschiedene Methoden bereitstellen. Anders ausgedrückt: Die Methoden werden dem Service in Schnittstellen zusammengefasst zugeordnet. Denn dort wird die Schnittstelle für den Aufruf einer Methode benötigt. In StarOffice Basic ist dies irrelevant. Hier rufen Sie die Methoden direkt über das jeweilige Objekt auf.

Die wichtigste Schnittstelle des StarDesktop lautet com.sun.star.frame.XComponentLoader. Sie umfasst im Wesentlichen die Methode loadComponentFromURL, die für das Erzeugen, Importieren und Öffnen von Dokumenten zuständig ist.

ThisComponent und CurrentComponent

In StarOffice erfolgt der Zugriff auf das aktive Dokumentobjekt über die Eigenschaften StarDesktop.CurrentComponent und ThisComponent. Der Unterschied ist – ähnlich wie in VBA – das Objekt, das im Vordergrund liegt, beziehungsweise das Objekt des OOo-Desktops, an welchem der Code hängt. Wenn Sie StarDesktop.CurrentComponent aus der Entwicklungsumgebung testen, werden Sie einen Fehler erhalten, da mit diesem Objekt der Makroeditor selbst gemeint ist.

Neues Dokument erzeugen

Um ein leeres Dokument zu erzeugen, kann man die Methode loadComponentFromURL des Service Desktop verwenden:

Dim objDT Obj As Object
Dim objDok As Object

objDT = createUnoService("com.sun.star.frame.Desktop")
objDok = objDT.loadComponentFromURL("private:factory/scalc", "_blank", 0, NoArgs())

Mit der gleichen Methode wird auch eine Datei geöffnet:

objDok = objDT.loadComponentFromURL("file:///C:/Eigene%20%Dateien/test.sxc", "_blank", 0, NoArgs())

Achtung: RFC1738

Der wichtigste Unterschied zwischen der Methode loadComponentFromURL und VBA-Methoden ist, dass die Dateinamen in URL-Notation angegeben werden, da StarOffice als plattformunabhängige Anwendung konzipiert wurde. OOo verwendet für Dateinamen die betriebssystemunabhängige URL-Notation gemäß dem Internet-Standard RFC 1738.

Gewöhnliche Dateinamen beginnen dabei mit dem Präfix file:/// gefolgt vom lokalen Pfad. Enthält der Dateiname Unterverzeichnisse, so werden diese mit einfachen Schrägstrichen getrennt (also nicht mit dem unter Windows üblichen rückwärtsgewandten Schrägstrich). Der folgende Pfad verweist auf die Datei test.sxc im Verzeichnis Eigene Dateien auf dem Laufwerk C.

file:///C:/Eigene%20%Dateien/test.sxc

Zur Umwandlung von lokalen Dateinamen in eine URL bietet StarOffice die Funktionen ConvertToUrl und ConvertFromUrl an. So liefert beispielsweise die Befehlsfolge MsgBox ConvertToUrl("C:\xyz\test.sxc") die Ausgabe file:///C:/xyz/test.sxc.

Der zu Grunde liegende Internet-Standard RFC 1738 gestattet die Verwendung der Zeichen 0-9, a-z und A-Z. Alle anderen Zeichen werden in einer Escape-Kodierung in die URLs eingefügt. Dazu werden sie in ihren Hexadezimalwert im Zeichensatz ISO 8859-1 (ISO-Latin) umgewandelt und bekommen ein Prozentzeichen vorangestellt. Aus einem Leerzeichen in einem lokalen Dateinamen wird so beispielsweise ein %20 in der URL.

Die Methode loadCompontentFromURL() aus dem Interface XComponentLoader legt durch die Wahl der Argumente bestimmte Eigenschaften des Dokuments fest:

loadCompontentFromURL(string aURL, string aTargetFrameName, long nSearchFlags, sequence <com::sun::star::beans::PropertyValue> aArgs)

Strukturen (structs)

Eine große Anzahl von Daten wird in so genannten Strukturen (structs) gespeichert. Im Beispiel loadComponentFromURL lässt sich dies anschaulich zeigen:

Sub API1

Dim Obj As Object
Dim objDok As Object
Dim strURL As String
Dim docArgs(1) As New com.sun.star.beans.PropertyValue

Obj = createUnoService("com.sun.star.frame.Desktop")

strURL = "C:\xyz\Versuch.xls"
strURL = ConvertToUrl(strURL)
docArgs(0).Name = "FilterName"
docArgs(0).Value = "MS Excel"
docArgs(1).Name = "AsTemplate"
docArgs(1).Value = True

ObjDok = Obj.loadComponentFromURL(strURL, "_blank", 0, docArgs())

End Sub

Ein Datenfeld wird über die beiden Wertepaare Name und Value gefüllt – dieses Array stellt die Struktur zum Öffnen des Dokuments dar. An einem anderen Beispiel soll der Begriff „Struktur“ näher erläutert werden: Wir weisen einer Zelle ein benutzerdefiniertes Zahlenformat (beispielsweise ein Datumsformat) mit einer Long-Variablen zu:

objZelle.NumberFormat = lngNumberFormatId

Zuvor muss jedoch die Long-Variable erzeugt werden:

strNummerFormat = "TT.MM.JJJJ"
lngNumberFormatId = objNummerFormat.queryKey(strNummerFormat, objLocalSettings, True)

Eigenschaften zuweisen

Die darin verwendete Struktur objLocalSettings kann nun verschiedene Eigenschaften erhalten:

Dim objLocalSettings As New com.sun.star.lang.Locale
[...]
objLocalSettings.Language = "de"
objLocalSettings.Country = "de"

Man könnte das ebenso über ein Datenfeld realisieren, das mit den Wertepaaren Name und Value gefüllt und anschließend der Variablen lngNumberFormatId zugewiesen wird:

Dim objPropLocalSettings(1) As New com.sun.star.beans.PropertyValue
objPropLocalSettings(0).Name = "Language"
objPropLocalSettings(0).Value = "de"
objPropLocalSettings(1).Name = "Country"
objPropLocalSettings(1).Value = "de"
lngNumberFormatId = objNummerFormat.queryKey(strNummerFormat, objPropLocalSettings(), True)

Konstanten

Eine Reihe von Parametern lassen sich über ihren internen Wert oder über Konstanten ansprechen. Im folgenden Beispiel löschen wir mit der Methode clearContents() den Inhalt einer Zelle:

ThisComponent.sheets(1).getCellRangebyName("A4").clearContents(com.sun.star.sheet.CellFlags.ANNOTATION)

Folgende Parameter stehen für clearContents zur Verfügung:

Tabelle 1: Ein Beispiel für Konstanten

Parameter

Wert

Bedeutung

EDITATTR

256

alles löschen

STRING

4

Zeichenketten

VALUE

1

Zahlen

DATETIME

2

Datum & Zeit

FORMULA

16

Formeln

ANNOTATION

8

Notizen

HARDATTR

32

Formate

OBJECTS

128

Objekte