Access / VBA und OpenOffice

02. April 2014

Die "Fernsteuerung" von Word und Excel durch eine Access-Datenbank ist relativ einfach. Ein bisschen anders sieht die Sache aus, wenn man von Access aus Dokumente mit OpenOffice Writer oder Calc erstellen und bearbeiten soll, weil man es in OpenOffice mit einer ganz anderen Programmiersprache zu tun hat und zum Beispiel die Möglichkeit zum Aufzeichnen von Makros deshalb nicht ad hoc verwenden kann.

Die Programmiersprache OpenOffice.org ist objekt-orientiert. Das OOo API (OpenOffice.org API) selbst ist mit UNO (Universal Network Objects) implementiert, dem component model von OpenOffice.org. UNO ermöglicht die Zusammenarbeit von OpenOffice.org mit unterschiedlichen Programmier­sprachen und anderen component models, so auch mit Visual Basic bzw. VBA.

Wir stellen hier ein paar Basis-Konzepte und -Funktionen vor, mit denen man sich die ersten Schritte bei der Nutzung von OpenOffice Writer von Microsoft Access aus hoffentlich ein bisschen erleichtern kann.

OpenOffice starten

Mit folgenden Zeilen erstellt man ein Desktop-Object. Ein Desktop ermöglicht Zugriff auf OpenOffice-Komponenten, z.B. auf Textdokumente. Es entspricht damit etwa CreateObject("Word.Application").

Dim ServMan As Object    ' Basisobjekt für den Zugriff auf OpenOffice
Dim Desktop As Object    ' Zugriff auf OpenOffice-Objekte 
    
  Set ServMan = CreateObject("com.sun.star.ServiceManager")
  Set Desktop = ServMan.CreateInstance("com.sun.star.frame.Desktop")

Im folgenden gehen wir davon aus, dass diese beiden Objekte global gesetzt sind.

Ein Dokument in OpenOffice öffnen

Mit der Funktion loadComponentFromURL() wird ein bestehendes Dokument geöffnet. Ob das Dokument in Writer, Calc oder Base geladen wird, hängt von der Extension der Datei ab.

  Set Doc = Desktop.loadComponentFromURL(FileURL, "_blank", 0, Arg())

Dabei ist FileURL ein Dateiname in URL-Notation, d.h. anstelle von "d:\dokumente\mein test.doc" wird "file:///d:/dokumente/mein%20test.doc" angegeben.

Bereits geöffnetes Dokument anzeigen

Mit folgendem Code kann man prüfen, ob eine bestimmte Datei bereits geladen ist und ggf. das Fenster in den Vordergrund holen:

  Set Components = Desktop.getComponents()
  Set Docs = Components.CreateEnumeration()
  Do While Docs.hasMoreElements()
    Set Doc = Docs.nextElement()
    FName = Doc.geturl()
    If Dateiname(FName) = Datei Then
      Doc.currentcontroller.frame.containerwindow.toFront
      Exit Do
    End If
  Loop

Ein Dokument in OpenOffice speichern

Mit der Methode Store wird ein Dokument gespeichert, mit Close geschlossen. Der Parameter True besagt dabei, dass das Dokument auch dann geschlossen werden soll, wenn es z.B. vorher nicht gespeichert wurde. Je nach Kontext muss man hier also eventuell vorher noch Prüfungen einbauen.

  Call Doc.Store
  Call Doc.Close (True)

Textmarken füllen

Mit folgenden Zeilen trägt man einen Text in den Textbereich (Range) einer Textmarke ein:

Dim Rg As Object

  Set Rg = Doc.Bookmarks.getByName("Textmarke1").getAnchor()
  Rg.String = "Dieser Text wird an der Textmarke eingetragen"
Dim Rg As Object    ' Range
Dim Cur As Object   ' Text cursor

  Set Rg = Doc.Bookmarks.getByName("Anrede").getAnchor()
  Set Cur = Doc.Text.createTextCursorByRange(Rg)
  Cur.String = "Sehr geehrte Frau Mayr"

Mit einem Text cursor kann man sich aber auch im Text bewegen und Zeichen, Worte und Absätze auswählen und bearbeiten. Mit folgendem Code kann man z.B. einen Absatz löschen:

Text ändern

Will man vorhandenen Text auswählen und bearbeiten, so verwendet man innerhalb des Textbereichs einen Text Cursor. Mit diesem kann man Zeichen, Worte, Absätze oder Seiten selektieren. Mit folgenden Zeilen kann man z.B. einen Absatz löschen:

Dim Cur As Object   ' Text cursor

  Set Cur = Doc.Text.createTextCursorByRange(Rg)
  Cur.gotoStartOfParagraph False
  Cur.gotoEndOfParagraph True        ' Absatz auswählen
  Cur.String = ""                    ' Text entfernen
  Cur.goLeft 1, True                   
  Cur.String = ""                    ' Absatzende davor entfernen

Weitere Infos zur Verwendung von Text Cursor findet man » im Open Office Wiki.

Textstellen in einem geöffneten Dokument suchen und bearbeiten

Zum Durchsuchen eines Writer-Dokuments verwendet man einen sogenannten SearchDescriptor.

Im folgenden Beispiel werden in einem geöffneten Dokument Doc alle Vorkommen des Wortes "Achtung" ermittelt und rot eingefärbt:

Dim SearchDesc As Object
Dim Rgs As Object
Dim SText As Object
Dim I As Integer

  Set SearchDesc = Doc.createSearchDescriptor
  SearchDesc.setSearchString ("Achtung")
  SearchDesc.SearchRegularExpression = True
  Set Rgs = Doc.findAll(SearchDesc)
  For I = 0 To Rgs.Count - 1
    Set SText = Rgs.getByIndex(I)
    SText.CharColor = RGB(0, 0, 255)
  Next

Die Liste aller Eigenschaften von Text (CharacterProperties) findet man in der Dokumentation von OpenOffice.

Text suchen und ersetzen

Mit Hilfe eines ReplaceDescriptors kann man in einem geöffneten Dokument einen Text Was suchen und durch Wodurch ersetzen.

Dim ReplDesc As Object   ' ReplaceDescriptor
Dim X As Variant

  Set ReplDesc = Doc.createReplaceDescriptor
  ReplDesc.setSearchString (Was)
  ReplDesc.setReplaceString (Wodurch)
  X = Doc.ReplaceAll(ReplDesc)

Für das Ersetzen gibt es diverse Parameter und Optionen. Mit folgendem Code zum Beispiel wird der ersetzte Text gleichzeitig rot markiert und mit Fontsize 16 dargestellt:

Dim ReplDesc As Object
Dim Args(1) As Object
Dim X As Variant
      
  Set ReplDesc = Doc.createReplaceDescriptor
  ReplDesc.setSearchString (Was)
  ReplDesc.setReplaceString (Wodurch)
  ReplDesc.SearchRegularExpression = True
  ReplDesc.SearchStyles = True
  ReplDesc.SearchAll = True
  Set Args(0) = ServMan.Bridge_GetStruct("com.sun.star.beans.PropertyValue")
  Args(0).Name = "CharColor"
  Args(0).Value = RGB(0, 0, 255)
  Set Args(1) = ServMan.Bridge_GetStruct("com.sun.star.beans.PropertyValue")
  Args(1).Name = "CharHeight"
  Args(1).Value = 16
  ReplDesc.SetReplaceAttributes (Args())
  X = Doc.ReplaceAll(ReplDesc)

Eine Grafik bearbeiten

In OpenOffice sind alle Grafikobjekte benannt. Man kann ein Grafikobjekt folgendermaßen ansprechen:

Dim Graphic As Object

  Set Graphic = Doc.getGraphicObjects.getByName("Grafik1")
  Graphic.GraphicURL = DATEINAME
  Graphic.Width = 6500
  Set Graphic = Nothing

Der Dateiname muss dabei wieder in der oben beschriebenen Form angegeben werden.

Hier findet man alle Eigenschaften von Grafikobjekten.

Tabellen

Auch Tabellen kann man über ihren Namen ansprechen. Das folgende Beispiel zeigt, wie man am Ende einer Tabelle eine neue Zeile anlegen und darin Daten eintragen kann.

Anders als in Microsoft Office werden in OpenOffice die Zellen einer Tabelle mit (Spalte, Zeile) angesprochen - also mathematisch korrekt als (X, Y).

Die erste Zeile und die erste Spalte haben den Index 0.

Dim Table As Object
Dim Rows As Object
Dim N As Integer

  Set Table = Doc.TextTables.getByName("Tabelle1")
  Set Rows = Table.GetRows
  N = Rows.getCount()            ' aktuelle Anzahl von Zeilen ermitteln
  Rows.InsertByIndex N, 1        ' 1 Zeile als neue Zeile N einfügen
  Table.getCellByPosition(0, N).String = "Beispiel-Text"

Ein Dokument ausdrucken

Mit folgender Funktion kann ein Dokument Doc auf dem gewünschten Drucker ausgegeben werden (für die Ausgabe auf dem Standard-Drucker einfach die Printer-Argumente weglassen):

Function OpenOffice_PrintDoc(Doc As Object, DruckerName, AnzKopien)

Dim PrinterArgs(1) As Object  ' Größe je nach Anzahl Printer-Argumente
Dim PrintArgs(0) As Object
Dim X As Variant
  
  Set PrinterArgs(0) = ServMan.Bridge_GetStruct("com.sun.star.beans.PropertyValue")
  PrinterArgs(0).Name = "Name"
  PrinterArgs(0).Value = DruckerName

  Set PrinterArgs(1) = ServMan.Bridge_GetStruct("com.sun.star.beans.PropertyValue")
  PrinterArgs(1).Name = "CopyCount"
  PrinterArgs(0).Value = AnzKopien

  Doc.Printer = PrinterArgs()
  
  Set PrintArgs(0) = ServMan.Bridge_GetStruct("com.sun.star.beans.PropertyValue")
  ' Option "Wait" bewirkt, dass die Print-Methode sich erst dann zurückmeldet,
  ' wenn der Job in der Druckerqueue steht. Option sollte gesetzt sein, wenn
  ' man das Dokument nach dem Drucken schließen möchte.
  PrintArgs(0).Name = "Wait"
  PrintArgs(0).Value = True
  
  X = Doc.Print(PrintArgs())

  Exit Function
  
End Function

Links zur Programmierung von OOo API mit VBA

» Apache OpenOffice Wiki
» Dokumentation zu Writer Objekten im API (Abschnitt API Documentation)
» Methoden des Desktop zum Umgang mit OO Dokumenten
» Beschreibung aller OOo Interfaces
» XrayTool - hilft dem VBA-Programmierer, die richtige Syntax zu finden