Serienbriefe sind der Klassiker der Office-Automation: Aus einer Access-Tabelle sollen individuelle Briefe entstehen — jeder mit Anrede, Adresse und Betrag des jeweiligen Kunden. Word bringt zwar eine eigene Seriendruckfunktion mit, doch aus Access heraus hast du mit Automation die volle Kontrolle: Du öffnest eine Vorlage, füllst Platzhalter, speicherst als PDF und erzeugst in einer Schleife beliebig viele Dokumente.
Diese Lektion zeigt den kompletten Weg — inklusive des sauberen Beendens, damit
kein WINWORD.EXE-Geisterprozess zurückbleibt.
Das Word-Objektmodell
Wie bei Excel steuerst du Word über sein Objektmodell: An der Spitze die
Word.Application, darunter Documents (offene Dokumente), darunter der Inhalt mit
Bookmarks (Textmarken), Range und Content. Von Access aus greifst du darauf
zu, als wärst du in Words eigenem VBA.
Für IntelliSense setzt du im VBE unter Extras → Verweise die Microsoft Word
xx.x Object Library. Die folgenden Beispiele nutzen Late Binding über
CreateObject, damit sie ohne Verweis und versionsübergreifend laufen; die nötigen
Konstanten schreibe ich als Zahl dazu.
Die Vorlage vorbereiten
Zwei Techniken sind gebräuchlich, um Platzhalter im Dokument zu füllen:
| Technik | Vorlage enthält | Vorteil | Nachteil |
|---|---|---|---|
Textmarken (Bookmarks) | benannte Textmarken | präzise, mehrfach nutzbar | Textmarke „verbraucht" sich beim Ersetzen |
| Find/Replace | Platzhaltertext wie «Name» | einfach, gut lesbar | ersetzt jedes Vorkommen |
Für Textmarken legst du in Word an der Einfügestelle über Einfügen →
Textmarke eine benannte Marke an (z. B. Anrede, Adresse). Für Find/Replace
schreibst du sichtbare Platzhalter wie {Name} oder «Name» in die Vorlage.
Speichere die Vorlage als .dotx (echte Word-Vorlage) oder als normales .docx,
von dem du eine Kopie öffnest.
Dokument aus Vorlage öffnen und Textmarken füllen
Documents.Add mit dem Vorlagenpfad erzeugt ein neues Dokument auf Basis der
Vorlage — die Vorlage selbst bleibt unangetastet. Textmarken erreichst du über
doc.Bookmarks("Name").Range.Text.
Public Sub BriefAusVorlage()
Dim wdApp As Object
Dim doc As Object
Set wdApp = CreateObject("Word.Application")
wdApp.Visible = True ' Word-Fenster zeigen
' Neues Dokument aus der Vorlage
Set doc = wdApp.Documents.Add("C:\Vorlagen\Brief.dotx")
' Textmarken füllen
FuelleTextmarke doc, "Anrede", "Sehr geehrter Herr Müller"
FuelleTextmarke doc, "Adresse", "Hauptstr. 5, 12345 Berlin"
FuelleTextmarke doc, "Betrag", Format(1234.5, "#,##0.00 €")
doc.SaveAs2 "C:\Briefe\Mueller.docx"
End Sub
' Hilfsroutine: setzt Text an einer Textmarke und erhält die Marke
Private Sub FuelleTextmarke(doc As Object, marke As String, wert As String)
Dim rng As Object
If doc.Bookmarks.Exists(marke) Then
Set rng = doc.Bookmarks(marke).Range
rng.Text = wert
doc.Bookmarks.Add marke, rng ' Textmarke neu setzen
End If
End Sub
Der Trick in der Hilfsroutine: Beim Schreiben in Range.Text verschwindet die
Textmarke. Mit doc.Bookmarks.Add marke, rng legst du sie über dem neuen Text
wieder an — so bleibt sie für spätere Zugriffe erhalten.
Alternative: Find/Replace
Wenn du lieber sichtbare Platzhalter verwendest, ersetzt du sie über das
Find-Objekt des Dokumentinhalts. Content.Find.Execute mit Replace:=2
(= wdReplaceAll) tauscht alle Vorkommen:
Private Sub Ersetze(doc As Object, platzhalter As String, wert As String)
With doc.Content.Find
.Text = platzhalter
.Replacement.Text = wert
.Execute Replace:=2 ' 2 = wdReplaceAll
End With
End Sub
' Aufruf:
' Ersetze doc, "{Name}", "Herr Müller"
' Ersetze doc, "{Betrag}", "1.234,50 €"
Viele Briefe über ein Recordset
Der eigentliche Serienbrief entsteht in einer Schleife über ein Recordset: Für jeden Kunden öffnest du ein frisches Dokument aus der Vorlage, füllst es und speicherst es — hier gleich als PDF.
Public Sub SerienbriefErzeugen()
Dim db As DAO.Database
Dim rs As DAO.Recordset
Dim wdApp As Object
Dim doc As Object
Dim pfad As String
Set db = CurrentDb
Set rs = db.OpenRecordset( _
"SELECT Anrede, Name, Adresse, Betrag FROM tblKunden", _
dbOpenSnapshot)
Set wdApp = CreateObject("Word.Application")
wdApp.Visible = False ' im Hintergrund, schneller
Do Until rs.EOF
Set doc = wdApp.Documents.Add("C:\Vorlagen\Brief.dotx")
Ersetze doc, "{Anrede}", Nz(rs!Anrede, "")
Ersetze doc, "{Name}", Nz(rs!Name, "")
Ersetze doc, "{Adresse}", Nz(rs!Adresse, "")
Ersetze doc, "{Betrag}", Format(Nz(rs!Betrag, 0), "#,##0.00 €")
' Dateiname pro Kunde
pfad = "C:\Briefe\" & rs!Name & ".pdf"
' Als PDF exportieren: Format 17 = wdExportFormatPDF
doc.ExportAsFixedFormat OutputFileName:=pfad, ExportFormat:=17
doc.Close SaveChanges:=False ' Dokument ohne Speichern schließen
Set doc = Nothing
rs.MoveNext
Loop
' Aufräumen
wdApp.Quit
Set wdApp = Nothing
rs.Close
Set rs = Nothing
Set db = Nothing
MsgBox "Serienbrief fertig."
End Sub
Beachte wdApp.Visible = False: Im Hintergrund ist der Massenlauf spürbar
schneller, weil Word nichts neu zeichnen muss. Nz() fängt Null-Werte ab, sonst
bricht die Ersetzung mit Fehler ab.
Als PDF speichern
Das Herzstück ist ExportAsFixedFormat. Es erzeugt eine PDF ohne Umweg über einen
Druckertreiber:
doc.ExportAsFixedFormat _
OutputFileName:="C:\Briefe\Brief.pdf", _
ExportFormat:=17 ' 17 = wdExportFormatPDF
Mit Early Binding kannst du statt der 17 die Konstante wdExportFormatPDF
schreiben. Für den XPS-Export gäbe es 18 (wdExportFormatXPS) — für Briefe ist
PDF der Standard.
Sauber beenden — der Geisterprozess
Wie bei Excel gilt: Wer Word unsichtbar startet und die Objektvariablen einfach
fallen lässt, hinterlässt WINWORD.EXE als Geisterprozess im Task-Manager. Er
belegt Speicher und kann die Vorlagendatei sperren.
Die Regel ist dieselbe: erst alle Dokumente schließen, dann Quit, dann jede
Objektvariable auf Nothing — von innen nach außen. Und: jeden Zugriff mit
wdApp. oder doc. qualifizieren, denn unqualifizierte Aufrufe erzeugen versteckte
Referenzen, die das Beenden verhindern.
Damit auch bei einem Fehler mitten in der Schleife aufgeräumt wird, gehört alles in einen Fehlerbehandler:
Public Sub SerienbriefRobust()
Dim wdApp As Object, doc As Object
On Error GoTo Aufraeumen
Set wdApp = CreateObject("Word.Application")
wdApp.Visible = False
Set doc = wdApp.Documents.Add("C:\Vorlagen\Brief.dotx")
' ... füllen und exportieren ...
doc.ExportAsFixedFormat "C:\Briefe\Test.pdf", 17
doc.Close SaveChanges:=False
Set doc = Nothing
Aufraeumen:
If Err.Number <> 0 Then MsgBox "Fehler: " & Err.Description
On Error Resume Next
If Not doc Is Nothing Then doc.Close SaveChanges:=False
If Not wdApp Is Nothing Then wdApp.Quit
Set doc = Nothing
Set wdApp = Nothing
End Sub
Falle: Setze
wdApp.Quitnie, während noch ein Dokument mit ungespeicherten Änderungen offen ist und Word unsichtbar läuft — dann hängt der Prozess auf einer unsichtbaren Rückfrage („Speichern?"). Schließe Dokumente immer explizit mitClose SaveChanges:=False.
Zusammengefasst
- Word-Automation läuft über
Word.Application→Documents.Add(Vorlage)→Bookmarks/Findzum Füllen der Platzhalter. - Textmarken sind präzise (nach dem Schreiben mit
Bookmarks.Addneu setzen), Find/Replace mitExecute Replace:=2ist einfacher bei sichtbaren Platzhaltern. - Eine Schleife über ein Recordset erzeugt pro Datensatz ein Dokument;
Nz()fängtNull-Werte ab. ExportAsFixedFormatmitExportFormat:=17speichert direkt als PDF, ganz ohne Druckertreiber.- Immer Dokumente mit
Close SaveChanges:=Falseschließen, dannQuit, dann alle Objekte aufNothing— sonst bleibt einWINWORD.EXE-Geisterprozess.