Von Access nach Word

Zusammenfassung

Erfahren Sie, wie Sie Word-Dokumente dynamisch erstellen.

Techniken

VBA, Word

Voraussetzungen

Access 2000 und höher

Beispieldatei

AccessToWord.mdb

André Minhorst, Duisburg

“Von Access nach Word” – da kommt doch nicht zum x-ten Male diese (zugegebenermaßen oft gefragte) Serienbrief-Geschichte Jein. Serienbriefe hat Access im Unternehmen (eigentlich) schon ausreichend behandelt. Welche Gründe soll es noch geben, Word zur Ausgabe von Access-Daten zu nutzen Diese und die Frage nach der Umsetzung beantwortet der vorliegende Beitrag. Dabei erfahren Sie unter anderem, wie Sie Word starten und beenden, Dokumente und Bereiche referenzieren und diese mit den gewünschten Daten aus einer Access-Datenbank füllen.

Serienbriefe sind – ganz klar – die Nummer Eins, wenn es um Anwendungen geht, die Access und Word miteinander verknüpfen. Ob die Access-Datenbank nun eine Tabelle oder Abfrage zum Füllen eines durch den Benutzer unter Word initiierten Serienbriefs liefert oder ob man diese Aufgabe von Access aus startet – das Thema ist in Newsgroups und Foren immer wieder gefragt. Das Prinzip dabei ist ganz einfach: Man definiert in Word ein paar Serienbrieffelder für Informationen, die sich von Brief zu Brief ändern: Adressdaten, Begrüßung, direkte Anrede im eigentlichen Text. Diese füllt man mit den passenden Inhalten aus der gewünschten Tabelle oder Abfrage.

Individualität in Serie

Dem Erzeuger eines solchen Dokuments spart dies eine ganze Menge Arbeit. Der Empfänger denkt sich nicht viel dabei, denn er ist es gewohnt, in Anschreiben persönlich angeredet zu werden. Was aber, wenn nicht nur Adresse und diverse Floskeln individuell gestaltet werden sollen, sondern noch mehr: Etwa, um einem Kunden interessante Produkte nahe zu bringen, zu denen er Informationen wünscht

Man könnte meinen, das sei ja nicht viel anders als ein herkömmlicher Serienbrief: Jeder Kunde bekommt ja ohnehin ein individuelles Anschreiben, dann kann man auch den Inhalt individuell gestalten. Oder etwa nicht Nun, soweit sich der Inhalt in ein oder mehrere Felder der verwendeten Datenherkunft quetschen lässt, ist das kein Problem. Wenn auf diese Weise etwa mehrere Produktbeschreibungen integriert werden sollen, die mehr als den reinen Beschreibungstext enthalten – also beispielsweise eine überschrift mit dem Produktnamen, eine Abbildung oder Informationen wie Preis oder Lieferzeit – wird es hingegen schwierig: Das Ganze mag für ein einziges Produkt funktionieren, weil man dann für jedes Feld eine eigene Formatierung festlegen kann.

Wenn aber jedes Anschreiben mehrere Produkte enthalten soll, wird es problematisch: Die Anzahl der Felder lässt sich nämlich nicht dynamisch anpassen wie etwa im Detailbereich eines Berichts, der die Datensätze einfach untereinander weg schreibt.

Das Problem lässt sich genauer umreißen: Dies ist der Versuch, das Ergebnis der Abfrage über zwei Tabellen mit einer m:n-Beziehung in einem Word-Dokument abzubilden, wobei die eine Seite der Beziehung die Tabelle der Empfänger und die andere Seite die Produkttabelle ist (bei einer 1:n-Beziehung wäre die Darstellung im übrigen nicht wesentlich einfacher – Beispiel Kategorien und Artikel).

VBA kann alles

Ohne die komfortable Serienbrieffunktion wird es eng: Auch das programmatische Füllen einer Dokumentenvorlage mit vorbereiteten Textmarken scheitert zunächst, da auch hier die Anzahl der für die Anzeige des Produkts benötigten Absätze nicht ohne Weiteres dynamisch einstellbar ist.

Zum Glück können Sie unter Word VBA einsetzen und genauso können Sie Word von Access aus per VBA fernsteuern. Das ist die Grundlage für die nachfolgend vorgestellten Techniken.

Zum Fernsteuern von Word legen Sie am besten zunächst einen Verweis auf die passende Objektbibliothek an (siehe Bild 1).

Hinweis

Sie kommen zwar auch ohne aus, wenn Sie Late Binding verwenden möchten (mehr dazu siehe Hinweis), aber zum Entwickeln sollten Sie die Vorzüge des Early Bindings (deutsch: frühe Bindung) genießen: Dazu gehört unter anderem die Unterstützung von IntelliSense für die Elemente der referenzierten Bibliothek.

Bild 1: Herstellen eines Verweises auf die Word-Objektbibliothek

Hinweis

Early Binding (also das Setzen eines Verweises und das Verwenden konkreter Objekte) setzt voraus, dass die verwendeten Bibliotheken auf allen Zielrechnern vorhanden sind. Sicherer ist der Einsatz von Late Binding: Dabei lassen Sie den Verweis weg und verwenden jeweils den Datentyp Object statt eines konkreten Typs wie etwa Word.Application bei der Deklaration. Wenn Sie eine Anwendung von Early Binding auf Late Binding umstellen, müssen Sie außerdem berücksichtigen, dass die sprechenden Konstanten nicht mehr zur Verfügung stehen. Statt dessen verwenden Sie die konkreten Zahlenwerte. Welcher Zahlenwert welcher Konstante entspricht, erfahren Sie im Objektkatalog: Suchen Sie einfach nach der gewünschten Konstanten und lesen Sie im unteren Bereich den Zahlenwert ab – in Bild 2 ist dies beispielsweise der Wert -2 für die Konstante wdBorderLeft. Um sicherzugehen, dass Sie alle Konstanten durch die passenden Zahlenwerte ersetzt haben, kompilieren Sie einfach die Anwendung. Option Explicit sollte dabei allerdings aktiviert sein.

Die Routine aus Quellcode 1 arbeitet zunächst nur mit der Word-Anwendung, ohne irgendwelche Dokumente zu öffnen. Dabei deklariert sie eine Objektvariable für den Verweis auf die gewünschte Instanz von Word.

Offen ist noch, wie man an diese Instanz kommt: Gegebenenfalls ist Word schon geöffnet. In diesem Fall verwendet man diese Instanz und stellt die Variable objWord mit der GetObject-Methode auf diese Instanz ein. Es kann natürlich auch sein, dass Word noch nicht geöffnet ist: Dann startet die Routine mit CreateObject eine neue Instanz und verweist mit objWord auf diese.

Bild 2: Ermitteln des Wertes einer Konstanten im Objektkatalog

Der Clou dieser Routine ist, dass die Suche nach einer vorhandenen Instanz am einfachsten über das Provozieren eines Fehlers möglich ist: Vor dem Versuch, eine bestehende Instanz zu referenzieren, stellt die Routine die Fehlerbehandlung so ein, dass diese beim Auftreten eines Fehlers einfach zum nächsten Befehl springt.

Diese Anweisung prüft, ob die Eigenschaft Number des Err-Objekts einen Wert größer 0 hat – was auf das Auftreten eines Fehlers hinweist. Dieser kann eigentlich nur durch das Scheitern der Herstellung eines Verweises auf eine bestehende Word-Instanz entstanden sein, woraufhin die Routine eine neue Instanz erzeugt.

Tritt kein Fehler auf, was beim “übernehmen” einer bestehenden Instanz von Word der Fall ist, aktiviert die Routine diese.

Zwischen der With- und der End With-Zeile findet die eigentliche Fernsteuerung (Automation) von Word statt. Hier ist Platz zum öffnen oder Anlegen eines Word-Dokuments, für seine Bearbeitung und das Schließen des Dokuments.

Zu guter Letzt beendet die Routine die Word-Instanz.

Quellcode 1: Initialisieren von Word und anschließendes Beenden

Public Sub WordInitialisieren()
    Dim objWord As Word.Application
    On Error Resume Next
    Set objWord = GetObject(, _        "Word.Application")
    If Err.Number > 0 Then
        On Error Goto 0
        Set objWord = _            CreateObject("Word.Application")
    Else
        objWord.Activate
    End If
    With objWord
        .Visible = True
        ''Word etwas tun lassen
    End With
    objWord.Quit
    Set objWord = Nothing
End Sub

Es gibt drei Möglichkeiten, um an ein Dokument zum Eintragen von Daten zu kommen:

  • Anlegen eines neuen Dokuments ohne Vorlage
  • Anlegen eines neuen Dokuments mit Vorlage
  • öffnen eines bestehenden Dokuments
  • Alle drei Varianten erfordern das Vorhandensein einer Objektvariablen, mit der Sie auf das Dokument verweisen, um es anschließend bearbeiten, drucken, speichern oder schließen zu können. Fügen Sie daher die folgende Zeile zu der Routine aus Quellcode 1 hinzu:

    Dim objDocument As Word.Document

    Neues Dokument ohne Vorlage anlegen

    Die folgenden Zeilen fügen Sie in Quellcode an der Stelle ein, an der sich der Kommentar “Word etwas tun lassen” befindet:

    Set objDocument = .Documents.Add
    objDocument.SaveAs "c:\test.doc"
    objDocument.Close

    Dies legt ein neues Word-Dokument ohne Vorlage an, speichert es unter dem Dateinamen c:\test.doc und schließt das Dokument wieder.

    Neues Dokument unter Verwendung einer Vorlage anlegen

    Die Add-Methode der Documents-Auflistung von Word bietet einen Parameter zum Angeben der gewünschten Formatvorlage. Wenn Sie die Add-Methode wie folgt ergänzen, legt Word ein neues Dokument auf Basis der angegebenen Formatvorlage an (in einer Zeile):

    Set objDocument = .Documents.Add("MeineFormatvorlage.dot")

    Dabei geht Word davon aus, dass sich die Formatvorlage im Vorlagenverzeichnis befindet. Welches das ist, finden Sie mit folgender Anweisung, abgesetzt im Direktfenster, heraus:

    Debug.Print Word.Options.DefaultFilePath(Path:= wdUserTemplatesPath)

    Bestehendes Dokument öffnen

    Das öffnen eines bestehenden Dokuments ist ebenfalls ganz einfach. In diesem Fall verwenden Sie die Open-Methode der Documents-Auflistung:

    Set objDocument = .Documents.Open("c:\test.doc")

    VBA-Prozeduren nennt man in Word Makros (in den anderen Office-Anwendungen außer Access übrigens auch). Die von Access bekannten Makros haben damit also nichts gemein.

    Makros von Word & Co. haben einen entscheidenden Vorteil: Sie können viele Ihrer Tätigkeiten mit Word damit aufzeichnen und sich anschließend den so generierten VBA-Code ansehen und diesen anpassen.

    Wer sich nicht gut mit dem Objektmodell etwa von Word auskennt, findet hier einen guten Einstieg. Das Aufnehmen eines Makros geht ganz einfach:

  • Wählen Sie in Word den Menüeintrag Extras/Makro/Aufzeichnen… aus und bestätigen Sie den nun erscheinenden Dialog mit der Schaltfläche OK, nachdem Sie gegebenenfalls einen alternativen Makro-Namen eingegeben haben (siehe Bild 3).
  • Führen Sie die gewünschten Aktionen aus – legen Sie ein neues Dokument an, fügen Sie Text hinzu oder was Ihnen sonst gerade einfällt.
  • Klicken Sie auf die Schaltfläche Aufzeichnung beenden der Mini-Menüleiste, die nach dem Start der Aufzeichnung erscheint. (
  • Bild 3: Eigenschaften eines aufzunehmenden Makros festlegen

    Fertig! Sie müssen nun noch mit Alt + F11 die VBA-Entwicklungsumgebung öffnen und im Projekt-Explorer das Modul Normal/Module/NewMacros auswählen – Word legt Makros standardmäßig an diesem Ort in der Formatvorlage Normal.dot an (siehe Bild 4).

    Eine große Hilfe bei Programmierfragen zu Word-VBA ist die FAQ von René Probst unter folgender Adresse: http://mypage.bluewin.ch/reprobst/WordFAQ/VBA.htm

    Die Inhalte dieser Seite verdeutlichen, dass der mit dem Makrorekorder erzeugte Code nur suboptimal ist – so wird dort überwiegend mit dem Selection-Objekt gearbeitet, das gut geeignet ist, die manuell vorgenommenen änderungen am Dokument aufzuzeichnen. Viel mächtiger und schneller ist jedoch das Range-Objekt, mit dem sich Bereiche direkt ansprechen lassen.

    Dadurch fällt das für das Selection-Objekt typische Navigieren weg – wer programmiert, will schließlich zielgerichtet arbeiten und nicht hier und da ein Zeichen einfügen, bis das Dokument fertig gestellt ist.

    Außerdem ist es bei der Programmierung von Word per VBA wichtig, sich das Word-Dokument nicht als Objekt mit Seiten und Zeilen vorzustellen – diese lassen sich nämlich per VBA ganz schlecht erfassen.

    Ende des frei verfügbaren Teil. Wenn Du mehr lesen möchtest, hole Dir ...

    den kompletten Artikel im PDF-Format mit Beispieldatenbank

    diesen und alle anderen Artikel mit dem Jahresabo

    Schreibe einen Kommentar