Zur Hauptseite ... Zum Onlinearchiv ... Zum Abonnement ... Zum Newsletter ... Zu den Tools ... Zum Impressum ... Zum Login ...

Gedrucktes Heft

Diesen Beitrag finden Sie in Ausgabe 3/2016.

Unser Angebot für Sie!

Lesen Sie diesen Beitrag und 500 andere sofort im Onlinearchiv, und erhalten Sie alle zwei Monate brandheißes Access-Know-how auf 72 gedruckten Seiten! Plus attraktive Präsente, zum Beispiel das bald erscheinende Buch 'Access 2010 - Das Grundlagenbuch für Entwickler'!

Diesen Beitrag twittern

Bericht per PDF und Mail verschicken

Es fragen immer wieder Leser an, ob wir nicht einmal beschreiben können, wie man einen Bericht als PDF-Dokument speichert und diesen dann per E-Mail verschickt. Kein Problem: Wir schauen uns erst die einzelnen Grundtechniken an und gehen dann dazu über, Lösungen für Spezialfälle zu entwickeln.

Bericht als PDF speichern

Während wir in früheren Access-Versionen noch eine externe Software benötigten, um PDF-Dokumente auf Basis von Access-Berichten zu erstellen, liefert Access nun zum Glück ein Export-Format für diese Anforderung mit. Also ist ja alles in Butter – wir müssen nur noch herausfinden, wie wir den Bericht per Knopfdruck im PDF-Format speichern.

Beispielbericht

Dazu benötigen wir erstmal einen passenden Bericht. Wir wollen allerdings nicht mit einem einfachen Bericht beginnen, der einfach per Doppelklick auf den Berichtsnamen im Navigationsbereich aufgerufen werden kann, sondern mit etwas Anspruchsvollerem. Was könnte das sein? Natürlich ein Bericht, dem wir beim Öffnen per WhereCondition ein Kriterium übergeben, nach dem die anzuzeigenden Daten ausgegeben werden. Dies ist nämlich üblicherweise der Fall – es gibt wohl nur selten Berichte, die alle Datensätze der zugeordneten Datenherkunft ausgeben. Die meisten Berichte liefern gefilterte Daten, beispielsweise in einer Rechnung, die nur die Daten zu einer bestimmten Bestellung enthalten soll.

Unser Beispielbericht ist so aufgebaut, dass Sie mit ihm alle Datensätze der Tabelle tblBestellungen ausgeben können oder auch nur eine einzige Rechnung. Er ist wie in Bild 1 aufgebaut und enthält beispielsweise einen Seitenkopf, der nur für die Folgeseiten der ersten Seite der jeweiligen Rechnung ausgegeben werden soll. Dazu enthält der Bericht ein paar Ereignisprozeduren, auf deren Bedeutung wir weiter unten zu sprechen kommen (den vollständigen Bericht stellen wir im Beitrag Rechnungsbericht vor – siehe www.access-im-unternehmen.de/1044).

Dialog zum Festlegen von Sortierungen und Gruppierungen

Bild 1: Dialog zum Festlegen von Sortierungen und Gruppierungen

Bericht öffnen

Wenn Sie diesen Bericht einfach über den Navigationsbereich öffnen, zeigt er alle Rechnungen zu den Datensätzen der Tabelle tblBestellungen an (immerhin einige hundert). Das ist natürlich nicht das Ziel – wir wollen am Ende genau einen Bericht öffnen, in ein PDF-Dokument speichern und dann per E-Mail verschicken.

Dazu bauen wir ein kleines Formular auf, das in der Entwurfsansicht wie in Bild 2 aussieht. Wenn wir nun auf eine der Schaltflächen klicken, soll immer genau die Rechnung für die aktuell angezeigte Bestellung ausgegeben werden.

Formular zum Anzeigen einer Bestellung und zum Ausgeben von Rechnungen

Bild 2: Formular zum Anzeigen einer Bestellung und zum Ausgeben von Rechnungen

Wenn wir die Schaltfläche cmdBerichtAnzeigen anklicken, soll der Bericht einfach nur in der Seitenansicht geöffnet werden. Dazu verwenden wir eine Ereignisprozedur, die den Bericht mit der Methode DoCmd.OpenReport öffnet und dabei mit dem Parameter WhereCondition den Ausdruck "BestellungID = " & Me!BestellungID übergibt. Dies gelingt auch, wie Bild 3 zeigt: Der Bericht enthält lediglich eine Seite mit den im Formular zu dieser Bestellung angezeigten Rechnungspositionen. Die Ereignisprozedur sieht wie folgt aus:

Formularansicht zum Anzeigen einer Bestellung und zum Ausgeben von Rechnungen

Bild 3: Formularansicht zum Anzeigen einer Bestellung und zum Ausgeben von Rechnungen

Private Sub cmdBerichtAnzeigen_Click()
     DoCmd.OpenReport "rptRechnungen", View:=acViewPreview, _
        WhereCondition:="BestellungID = " & Me!BestellungID
End Sub

Soweit, so gut: Aber wir wollen ja nicht die Berichtsvorschau, sondern ein PDF-Dokument mit dem gleichen Inhalt. Bei geöffnetem Bericht kommen wir relativ einfach dorthin: Wir müssen nur die Drucken-Schaltfläche des Ribbons betätigen und im nun erscheinenden Drucken-Dialog den Eintrag Microsoft Print To PDF auswählen (s. Bild 4). Nach einem Klick auf OK erscheint ein Dateiauswahl-Dialog, mit dem Sie festlegen, unter welchem Dateinamen die PDF-Datei gespeichert werden soll. Danach können Sie die PDF-Datei öffnen, die wie in Bild 5 aussieht.

Drucken-Dialog mit dem Microsoft-eigenen PDF-Treiber

Bild 4: Drucken-Dialog mit dem Microsoft-eigenen PDF-Treiber

Ein Bericht im PDF-Format

Bild 5: Ein Bericht im PDF-Format

PDF per VBA erstellen

Das ist allerdings nicht unser Ziel, wenn wir wollen ja nicht noch auf weitere Schaltflächen klicken geschweige denn Dateinamen für die zu erstellende PDF-Datei vergeben – und per Mail verschickt ist das PDF-Dokument nun noch längst nicht. Also wenden wir uns der folgenden Stufe zu – der Schaltfläche cmdBerichtAlsPDF. Die dadurch ausgelöste Prozedur soll den Bericht möglichst automatisch in ein PDF-Dokument schreiben. Als Erstes versuchen wir, bei geöffnetem Bericht die folgende Methode aufzurufen:

RunCommand acCmdPrint

Dies hilft leider nicht weiter, denn damit öffnen Sie nur den bereits bekannten Drucken-Dialog. Hilfe erhalten wir erst durch die Methode DoCmd.OutputTo. Dieser können wir folgende Parameter übergeben:

  • ObjectType: acOutputReport für einen Bericht
  • ObjectName: Name des Berichts in Anführungszeichen, hier "rptRechnungen"
  • OutputFormat: acFormatPDF für PDF
  • OutputFile: Dateiname der zu erstellenden Datei inklusive Verzeichnis

Die übrigen Parameter spielen für unseren Anwendungsfall keine Rolle. Die Methode liefert allerdings keine Möglichkeit, ein Kriterium für die Festlegung des zu druckenden Rechnungsdatensatzes zu definieren. Wie also wollen wir dafür sorgen, dass nur der gewünschte Datensatz berücksichtigt wird? Die einzige Möglichkeit ist, den Bericht tatsächlich zuvor in der Seitenansicht zu öffnen, dann die OutputTo-Methode aufzurufen und den Bericht dann wieder zu schließen (s. Listing 1).

Private Sub cmdBerichtAlsPDf_Click()
     Dim strDateiname As String
     DoCmd.OpenReport "rptRechnungen", View:=acViewPreview, _
        WhereCondition:="BestellungID = " & Me!BestellungID
     strDateiname = CurrentProject.Path & "\Bestellung_" & Me!BestellungID & ".pdf"
     DoCmd.OutputTo acOutputReport, "rptRechnungen", acFormatPDF, strDateiname
     DoCmd.Close acReport, "rptRechnungen"
     ShellExecute Me.hwnd, "Open", strDateiname, "", "", 1
End Sub 

Listing 1: Öffnen und Drucken des Berichtes als PDF-Dokument

Hier öffnen wir den Bericht mit der bereits zuvor verwendeten Methode. Dann speichern wir den Dateinamen in der Variablen strDateiname und rufen die DoCmd.OutputTo-Methode auf – unter anderem mit dem Dateinamen als Parameterwert.

Nach dem Schließen des Berichts verwenden wir die API-Funktion ShellExecute, um den Bericht direkt im PDF-Reader anzuzeigen.

Probleme mit bedingten Bereichen

Der von uns verwendete Bericht zeigt seinen Seitenkopfbereich mit Spaltenüberschriften nur dann an, wenn eine Folgeseite wie etwa die zweite oder dritte Seite angezeigt werden. Dafür sorgen einige VBA-Prozeduren, die durch die verschiedenen Berichtsereignisse ausgelöst werden. So stellt die Report_Open-Ereignisprozedur eine Variable namens bolCancelSeitenkopf auf True ein, damit in der Methode Seitenkopfbereich_Format der Cancel-Parameter mit genau diesem Wert gefüllt und die Anzeige des Seitenkopfes auf der ersten Seite unterbunden wird:

Private Sub Seitenkopfbereich_Format(Cancel As Integer,  FormatCount As Integer)
     Cancel = bolCancelSeitenkopf
End Sub

Nach dem Anzeigen der letzten Seite, auf der sich der Gruppenfuß für die Rechnung befindet, wird bolCancelSeitenfuss wieder auf True eingestellt, damit im Falle der Ausgabe mehrerer Rechnungen wieder der Seitenkopf mit den Spaltenüberschriften auf der ersten Seite der folgenden Rechnung ausgeblendet wird.

Das gelingt normalerweise ohne Probleme. Wenn wir aber den Bericht erst in der Seitenansicht anzeigen und diesen dann als PDF drucken, wird bei der Seitenansicht nur die erste Seite angezeigt. Das bedeutet, dass für die folgende Seite die Anzeige des Seitenkopfes mit den Spaltenüberschriften aktiviert ist. Normalerweise sollte man nun davon ausgehen, dass das Drucken des Berichtes auch wieder das Report_Open-Ereignis auslöst, aber das geschieht nicht. Also wird auf der ersten Seite auch der Seitenkopfbereich mit den Spaltenüberschriften gedruckt wie in Bild 6 zu sehen.

Bericht mit einem nicht erwünschten Bereich auf der ersten Seite

Bild 6: Bericht mit einem nicht erwünschten Bereich auf der ersten Seite

Nun gibt es zwei Möglichkeiten: Die erste ist, in die Abläufe des Klassenmoduls des Berichts einzugreifen und die Variable bolCancelSeitenkopf von außen zu ändern, bevor wir den Bericht als PDF-Dokument ausgeben. Stellen wir diesen Wert auf True ein, wird die Ausgabe des Seitenkopfbereichs auf der ersten Seite beim Drucken unterbunden. Alternativ können wir dafür sorgen, dass vor dem Drucken in ein PDF-Dokument die letzte Seite des Berichts aufgerufen wird. Dort befindet sich ja auch der Gruppenfußbereich für die aktuelle Rechnung, dessen Anzeige ein Ereignis auslöst, dass auch die Variable bolCancelSeitenkopf auf den Wert True einstellt. Aber wie können wir per Code zur letzten Seite der Seitenansicht springen?

Dies gelingt leider nur per SendKeys, und dies ist nicht immer komplett berechenbar. Sie können die beiden folgenden Zeilen vor der OutputTo-Methode einfügen:

SendKeys "{End}"
DoEvents

Die andere Methode haben wir in der Beispieldatenbank untergebracht.

PDF drucken und per E-Mail senden

Wenn der Bericht einmal gedruckt ist, fällt der Versand per E-Mail nicht mehr schwer. Sie benötigen einen Verweis auf die Outlook-Bibliothek (VBA-Editor, Menü Extras|Verweise) und die Prozedur aus Listing 2.

Private Sub cmdBerichtPerMail_Click()
     Dim objOutlook As Outlook.Application
     Dim objMail As Outlook.MailItem
     Dim strRechnung As String
     Set objOutlook = New Outlook.Application
     Set objMail = objOutlook.CreateItem(olMailItem)
     DoCmd.OpenReport "rptRechnungen", View:=acViewPreview, _
         WhereCondition:="BestellungID = " & Me!BestellungID
     bolCancelSeitenkopf = True
     strRechnung = CurrentProject.Path & "\Bestellung_" & Me!BestellungID & ".pdf"
     DoCmd.OutputTo acOutputReport, "rptRechnungen", acFormatPDF, strRechnung
     DoCmd.Close acReport, "rptRechnungen"
     With objMail
         .Recipients.Add Me!EMail
         .Subject = "Ihre Rechnung zur Bestell-Nr. " & Me.Bestelldatum
         .Body = "Sehr geehrte(r) " & Me.Kontaktperson & ", " & vbCrLf & vbCrLf _
             & "anbei finden Sie die Rechnung zur Ihrer Bestellung mit der Nummer " _
             & Me.BestellungID & "." & vbCrLf _
             & vbCrLf & "Viele Grüße" & vbCrLf & vbCrLf & Me.Vorname & " " & Me.Nachname
         .Attachments.Add strRechnung
         .Display
     End With
End Sub

Listing 2: Erzeugen eines PDF-Dokuments und Versenden des Berichts

Die Prozedur erstellt ein neues Outlook-Objekt und ein neues MailItem-Objekt. Dann öffnet es wie im vorherigen Beispiel den Bericht und speichert diesen im PDF-Format. In diesem Fall stellen wir hier die Option bolCancelSeitenkopf auf True ein, damit der Bericht korrekt gedruckt wird (wenn Sie selbst in Ihrem Bericht keinen derartigen Code zum Ein- und Ausblenden verwenden, brauchen Sie diese Zeile nicht). Danach füllt die Prozedur die Mail mit der E-Mail-Adresse des Kunden, den Betreff mit der Bestellnummer und den Inhalt und fügt die gespeicherte PDF-Datei über die Attachments-Auflistung als Anlage an. Danach zeigt die Display-Methode die so erstellte E-Mail an, die Sie dann verschicken können. Wenn Sie diese Methode durch die Send-Methode ersetzen, wird die Mail direkt abgeschickt.

Kompletten Artikel lesen?

Einfach für den Newsletter anmelden, dann lesen Sie schon in einer Minute den kompletten Artikel und erhalten die Beispieldatenbanken.

E-Mail:

Download

Download

Die .zip-Datei enthält folgende Dateien:

BerichtPerPDF.accdb

Beispieldateien downloaden

© 2003-2015 André Minhorst Alle Rechte vorbehalten.