PDF per VBA erstellen im Detail

Im Beitrag „PDF erstellen mit Access im Detail“ (www.access-im-unternehmen.de/1523) haben wir uns bereits angesehen, wie wir PDF-Dokumente über die Benutzeroberfläche erstellen können. Typischerweise möchte man einem Benutzer allerdings nicht die Aufgabe überlassen, einen Bericht zu öffnen und dann die entsprechenden Schaltflächen im Ribbon aufzurufen, um den Bericht als PDF-Dokument zu speichern. Dazu stellen wir einen eigenen Button zur Verfügung, mit dem wir den Bericht direkt als PDF speichern. Es fehlt also nur noch der passende VBA-Befehl. In diesem Beitrag schauen wir uns an, wie dieser lautet und welche Alternativen es gibt. Außerdem werfen wir einen Blick darauf, wie wir Dokumente im PDF/A-Format erzeugen. Während wir dazu über die Benutzerfläche lediglich eine Option im Dateiauswahl-Dialog aktivieren mussten, ist der Aufwand unter VBA bereits deutlich höher. Aber immerhin ist dieser nur einmalig durchzuführen, weshalb wir gern darauf eingehen.

Bericht als PDF exportieren per DoCmd.OutputTo

Die erste und offensichtliche Möglichkeit zum Exportieren eines Berichts ist die OutputTo-Methode des DoCmd-Objekts.

Diese Methode erwartet die folgenden Parameter:

  • ObjectType: Typ des zu exportierenden Objekts, in diesem Fall acOutputReport
  • ObjectName: Name des Berichts
  • OutputFormat: Ausgabeformat, hier acFormatPDF
  • OutputFile: Pfad der zu erstellenden Datei
  • Autostart: Gibt an, ob die exportierte Datei nach dem Export automatisch angezeigt werden soll.
  • TemplateFile: Relevant für Exporte in andere Dateiformate wie Word oder Excel.
  • Encoding: Nur relevant für den Export in das Textformat.
  • OutputQuality: Gibt die Qualität der zu erstellenden Datei an. Wir können die beiden Werte acExportQualityPrint und acExportQualityScreen angeben.

Ein Aufruf sieht beispielsweise wie folgt aus:

DoCmd.OutputTo acOutputReport, "rptBeispiel", acFormatPDF, CurrentProject.Path & "\rptBeispiel_Screen.pdf", True, , , acExportQualityScreen

Bericht mit Kriterium als PDF exportieren

Natürlich kommt es immer mal vor, dass man einen Bericht genau so als PDF-Dokument speichern möchte, wie man diesen auch per Doppelklick auf seinen Namen im Navigationsbereich anzeigen würde – also ohne die Angabe von Kriterien et cetera.

Allerdings gibt es auch Berichte, die vor der Ausgabe im PDF-Format gefiltert werden sollen. Zu Beispielzwecken haben wir einen weiteren Bericht namens rptArtikel angelegt, der in der Entwurfsansicht wie in Bild 1 erscheint.

Entwurf eines Beispielberichts mit einer Artikelliste

Bild 1: Entwurf eines Beispielberichts mit einer Artikelliste

Wenn wir den Bericht nun gefiltert öffnen, sodass er beispielsweise nur die Artikel mit den Werten bis 10 im Feld ArtikelID ausgibt, öffnen wir diesen wie folgt:

DoCmd.OpenReport "rptArtikel", acViewPreview, , "ArtikelID <= 10"

Das Ergebnis sehen wir in Bild 2. Hier gibt der Bericht wie erwartet nur die ersten zehn Datensätze aus.

Bericht mit Where-Bedingung

Bild 2: Bericht mit Where-Bedingung

Nun schließen wir diesen Bericht und exportieren ihn im PDF-Format:

DoCmd.OutputTo acOutputReport, "rptArtikel", acFormatPDF, CurrentProject.Path & "\rptArtikel.pdf", True, , , acExportQualityScreen

Dies liefert logischerweise den Bericht mit allen Datensätzen (siehe Bild 3). Nun wollen wir diesen allerdings in gefilterter Form in einem PDF-Dokument speichern.

Artikel-Bericht als PDF

Bild 3: Artikel-Bericht als PDF

Dummerweise liefert uns die DoCmd.OutputTo-Methode keine Möglichkeit, einen Parameter namens WhereCondion für den Bericht anzugeben.

Also müssen wir einen alternativen Weg finden, um den Bericht gefiltert auszugeben.

Dazu gehen wir zunächst den folgenden Weg:

  • Wir öffnen den Bericht unter Angabe der WhereCondition in der Seitenansicht.
  • Dann exportieren wir den Bericht.

Das läuft nun ohne Probleme und liefert das gewünschte Ergebnis. Wir öffnen den Bericht, dessen Namen wir zuvor in der Variablen strReport gespeichert haben, mit DoCmd.OpenReport, geben diesen dann mit DoCmd.OutputTo aus und schließen ihn mit DoCmd.Close wieder.

Die verwendete Prozedur sieht wie in Listing 1 aus.

Public Sub ArtikellisteGefiltert()
     Dim strReport As String
     Dim strPfad As String
     strReport = "rptArtikel"
     strPfad = CurrentProject.Path & "\" & strReport & ".pdf"
     DoCmd.OpenReport strReport, acViewPreview, , "ArtikelID <= 10"
     DoCmd.OutputTo acOutputReport, strReport, acFormatPDF, strPfad
     DoCmd.Close acReport, strReport
End Sub

Listing 1: Exportieren der zuvor gefilterten Artikelliste

Achtung, Fehler 2501!

Es kann beim Aufruf der Prozedur DoCmd.OutputTo passieren, dass wir den Fehler 2501 erhalten. Wir haben einige Minuten gebraucht, um herauszufinden, weshalb dieser aufgetreten ist. Der Grund war einfach: Wir hatten die zuvor bereits einmal erzeugte PDF-Datei namens rptArtikel.pdf bereits geöffnet. Eine geöffnete PDF-Datei kann jedoch nicht einfach überschrieben werden. Dabei erscheint die hier wenig aussagekräftige Meldung Die Aktion OutputTo wurde abgebrochen.

Bericht mit dem Standard PDF/A-3 speichern

Im Beitrag PDF erstellen im Detail (www.access-im-unternehmen.de/1523) haben wir gezeigt, wie wir zumindest mit neueren Access-Versionen Berichte so als PDF-Dokumente exportieren konnten, dass diese dem PDF/A-3-Standard entsprechen. Dazu mussten wir im Speichern-Dialog, den wir mit dem Ribbonbefehl Seitenansicht|Daten|PDF oder XPS geöffnet haben, die Optionen einblenden und dort die Option PDF/A-kompatibel aktivieren (siehe Bild 4). Dies führte je nach Access-Version dazu, dass die PDF-Datei im Format PDF/A-1 oder PDF/A-3 erzeugt wurde.

Exportieren im PDF/A-3-Format über die Benutzeroberfläche

Bild 4: Exportieren im PDF/A-3-Format über die Benutzeroberfläche

Wenn wir uns den Speichern-Dialog genauer ansehen, finden wir hier mit Datei nach dem Veröffentlichen öffnen und Optimieren für auch noch zwei Optionen, die wir bereits von der OutputTo-Methode des DoCmd-Objekts kennen. Da stellt sich die Frage, ob wir vielleicht auch noch die PDF/A-3-Kompatibilität per VBA sicherstellen können. Allerdings liefert selbst die Aktivierung der Anzeige versteckter Elemente im Objektkatalog keinerlei Hinweise auf weitere Möglichkeiten.

Wenn wir den Export-Vorgang über diesen Dialog abschließen, taucht jedoch noch der Schritt Exportschritte speichern auf (siehe Bild 5). Vielleicht liefert dieser ja noch hilfreiche Informationen?

Speichern der Exportschritte

Bild 5: Speichern der Exportschritte

Und was geschieht eigentlich, wenn wir das Speichern der Exportschritte wie im Screenshot aktivieren? Also probieren wir das einmal aus und nennen den Export Exportschritte_rptArtikel.

Danach stellt sich allerdings die Frage, wo diese Exportschritte überhaupt gespeichert werden und wie wir diese nutzen können. Wenn wir erneut versuchen, den Bericht zu exportieren, finden wir jedenfalls keine Gelegenheit, diese auszuwählen.

Suchen wir ein wenig weiter, finden wir allerdings im Ribbon unter Externe Daten einen Befehl namens Gespeicherte Exporte (siehe Bild 6).

Im Ribbon befindet sich ein Button namens Gespeicherte Exporte.

Bild 6: Im Ribbon befindet sich ein Button namens Gespeicherte Exporte.

Klicken wir diesen an, öffnet sich ein Dialog, der unseren gespeicherten Export anzeigt (siehe Bild 7).

Unser gespeicherter Export

Bild 7: Unser gespeicherter Export

Hier haben wir jedoch auch nur die Möglichkeit, den Export nochmals zu starten.

Gespeicherten Export per VBA aufrufen

Logischerweise gibt es auch noch einen VBA-Befehl, mit dem wir einen gespeicherten Export starten können.

Dieser ist ebenfalls eine Methode des DoCmd-Objekts und heißt RunSavedImportExport und wir rufen diese wie folgt auf:

DoCmd.RunSavedImportExport "Exportschritte_rptArtikel"

Mit dieser Methode können wir den Bericht exportieren. Die Frage ist noch, ob wir damit eine PDF/A-3-kompatible Datei erstellt haben. Dazu wollen wir nun einen Validierer hinzuziehen.

Validieren, ob ein PDF-Dokument dem Standard PDF/A-3 entspricht

Unter dem folgenden Link haben wir unsere mit Access erzeugten Dokumente auf PDF/A-3 validiert:

https://avepdf.com/de/pdfa-validation

Hier kann man sein Dokument angeben und dieses prüfen lassen. In unserem Beispiel kam das Ergebnis aus Bild 8 heraus. Auch in der kostenpflichtigen Version von Adobe Acrobat können wir erkennen, ob es sich um eine PDF/A-3-Datei handelt. Wenn wir das PDF-Dokument damit öffnen, erscheint erstens oben die Meldung, dass die Datei schreibgeschützt geöffnet wurde, weil sie Konformität mit dem PDF/A-Standard verlangt (siehe Bild 9).

Validieren von PDF/A-3-Dateien

Bild 8: Validieren von PDF/A-3-Dateien

Validieren von PDF/A-3-Dateien im Adobe Acrobat

Bild 9: Validieren von PDF/A-3-Dateien im Adobe Acrobat

Außerdem sehen wir rechts ein Icon, mit dem wir den Bereich Standards öffnen können (der übrigens bei Dateien ohne PDF/A-Standard gar nicht erscheint). In diesem Bereich erhalten wir die Information, dass dieses Dokument dem Standard PDF/A-3B entspricht.

PDF-Dateien, die nicht mit neueren Access-Versionen erstellt wurden, weisen teilweise nur den Standard PDF/A-1B auf. Wir konnten nicht genau herausfinden, ab welchen Versionen PDF/A-3B erzeugt wird, daher sollte man dies immer selbst prüfen, wenn PDF-Dokumente mit diesem Standard benötigt werden – beispielsweise als Basis für ZUGFeRD-Rechnungen.

Damit haben wir grundsätzlich eine Lösung, mit der wir unseren Bericht im PDF/A-3-Format exportieren können. Wir benötigen allerdings nun noch eine Möglichkeit, die auszugebenden Daten wie im vorherigen Beispiel durch eine WhereCondition festzulegen. Lässt sich dies genau wie zuvor erledigen, indem wir den Bericht mit WhereCondition öffnen, diesen über den gespeicherten Export als PDF-Dokument speichern, und den Bericht dann wieder schließen?

So etwas findet man nur heraus, indem man es ausprobiert. Unsere Testprozedur sieht wie folgt aus, und diesmal wollen wir die ersten 15 Datensätze ausgeben:

Public Sub GespeicherterExportGefiltert()
     Dim strReport As String
     Dim strPfad As String
     strReport = "rptArtikel"
     strPfad = CurrentProject.Path & "\" & strReport & ".pdf"
     DoCmd.OpenReport strReport, acViewPreview, , _
         "ArtikelID <= 15"
     DoCmd.RunSavedImportExport "Exportschritte_rptArtikel"
     DoCmd.Close acReport, strReport
End Sub

Aber können wir damit nun beispielsweise auch einen anderen Bericht öffnen und diesen im PDF/A-3-Format speichern? Wir öffnen also einfach mal unseren ganz einfachen Beispielbericht von Anfang des Beitrags und versuchen, den gespeicherten Export auf diesen anzuwenden:

DoCmd.OpenReport "rptBeispiel", acViewPreview
DoCmd.RunSavedImportExport "Exportschritte_rptArtikel"
DoCmd.Close acReport, strReport

Dies führt allerdings nicht zum gewünschten Ergebnis – es wird der Bericht rptArtikel exportiert, und zwar diesmal mit allen Datensätzen.

Das bedeutet also: Der gespeicherte Export legt das PDF immer für den beim Erstellen des Exports angegebenen Bericht an. Wenn wir den gleichen Bericht während des gespeicherten Exports geöffnet haben, holt sich die Methode RunSavedImportExport aber wohl die WhereCondition vom aktuell geöffneten Datensatz.

Gespeicherten Export anpassen

Damit bleibt noch eine Frage: Wie können wir mithilfe eines gespeicherten Exports einen beliebigen Bericht exportieren, ohne dass wir für jeden zu exportierenden Bericht zuvor einen gespeicherten Export angelegt haben? Hier stellt sich erst einmal die Frage, ob es so viele Berichte gibt, dass man sich genauer ansieht, wie man dies automatisieren könnte. Wenn wir davon ausgehen, dass das PDF/A-3-Format überwiegend zum Erstellen von PDFs für ZUGFeRD-Rechnungen verwendet werden soll, dürfte die Anzahl in den meisten Anwendungen überschaubar sein.

Aber uns reizt schon die Aufgabe, herauszufinden, wo die gespeicherten Exporte gespeichert werden – um diese dann auch noch anpassen zu können. Wie das gelingt, schauen wir uns allerdings in einem eigenen Beitrag namens Gespeicherte Importe und Exporte verwalten (www.access-im-unternehmen.de/1526) an.

Anpassbaren gespeicherten Export für PDF/A-3-Dokumente

Nachdem wir dort herausgefunden haben, wie wir auf die gespeicherten Importe und Exporte zugreifen können, passen wir dies nun auf unsere hier vorliegende Anforderung an.

Dazu legen wir noch einmal einen neuen gespeicherten Export an, den wir gleich entsprechend benennen:

  • Markieren eines zu exportierenden Berichts im Navigationsbereich
  • Anklicken des Ribbonbefehls Externe Daten|Exportieren|PDF oder XPS
  • Anklicken des Befehls Optionen… im Dialog Als PDF oder XPS veröffentlichen
  • Aktivieren der Option PDF/A-kompatibel (wobei wir diese auch noch später einstellen können)
  • Betätigen des Befehls Veröffentlichen
  • Im Dialog Exportieren – PDF die Option Exportschritte speichern aktivieren
  • Für Speichern unter: einen Text wie Export PDF/A-3 eintragen
  • Auf Export speichern klicken

Damit ist der gespeicherte Export mit den wichtigsten Optionen bereits angelegt. Nun wollen wir zwei Parameter anpassen können:

  • den Namen des zu exportierenden Berichts und
  • den Speicherort.

Bevor wir uns den XML-Code ansehen, fügen wir einen Verweis auf die Bibliothek Microsoft XML v3.0 zum VBA-Projekt hinzu (siehe Bild 10).

Hinzufügen des Verweises auf die XML-Bibliothek

Bild 10: Hinzufügen des Verweises auf die XML-Bibliothek

XML-Code des gespeicherten Exports betrachten

Um den Code vorab einmal zu sichten, reichen uns nun die folgenden Anweisungen.

Wichtig ist, dass wir den korrekten, soeben festgelegten Namen für den gespeicherten Export als Index angeben:

Public Sub GespeichertenExportAnpassen()
     Dim objSpecification As ImportExportSpecification
     Dim objXML As MSXML2.DOMDocument
     Set objSpecification = CurrentProject. _
         ImportExportSpecifications("Export PDF/A-3")
     Set objXML = New MSXML2.DOMDocument
     objXML.loadXML objSpecification.XML
     Debug.Print objXML.XML
End Sub

Hier ist das Ergebnis:

<ImportExportSpecification     Path="C:\Users\User\Documents\rptArtikel.pdf"     xmlns="urn:www.microsoft.com/office/access/imexspec">
   <ExportPDF AccessObject="rptArtikel"       ObjectType="Report"       AutoStart="false"       Quality="screen"       UseISO19005_1="true"/>
</ImportExportSpecification>

Wir müssen hier zwei Elemente anpassen. Das erste ist das Attribut Path des Elements ImportExportSpecification, das den Pfad der zu erstellenden Datei enthält.

Das zweite ist der Name des zu exportierenden Berichts, hier aktuell auf rptArtikel eingestellt.

Diese Elemente ändern wir durch einfache XML-Operationen. Damit wir diese flexibel ändern können, fügen wir diese als Parameter zu der Prozedur GespeichertenExportAnpassen hinzu. Außerdem wollen wir dort noch den Namen des gespeicherten Exports hinzufügen, damit wir die Prozedur flexibel nutzen können.

Das Ergebnis sehen wir in Listing 2. Die Prozedur erwartet die folgenden Parameter:

Public Sub GespeichertenExportAnpassen(strSpecification As String, strPath As String, strAccessObject As String)
     Dim objSpecification As ImportExportSpecification
     Dim objXML As MSXML2.DOMDocument
     Dim objNode_ImportExportSpecification As MSXML2.IXMLDOMNode
     Dim objNode_ExportPDF As MSXML2.IXMLDOMNode
     Dim objAttribute_Path As MSXML2.IXMLDOMAttribute
     Dim objAttribute_AccessObject As MSXML2.IXMLDOMAttribute
     Dim objAttribute_UseISO19005_1 As MSXML2.IXMLDOMAttribute
     
     Set objSpecification = CurrentProject.ImportExportSpecifications(strSpecification)
     
     Set objXML = New MSXML2.DOMDocument
     objXML.loadXML objSpecification.XML
     Set objNode_ImportExportSpecification = objXML.selectSingleNode("ImportExportSpecification")
     
     Set objAttribute_Path = objNode_ImportExportSpecification.Attributes.getNamedItem("Path")
     objAttribute_Path.nodeTypedValue = strPath
     
     Set objNode_ExportPDF = objNode_ImportExportSpecification.selectSingleNode("//ExportPDF")
     
     Set objAttribute_AccessObject = objNode_ExportPDF.Attributes.getNamedItem("AccessObject")
     objAttribute_AccessObject.nodeTypedValue = strAccessObject
         
     Set objAttribute_UseISO19005_1 = objNode_ExportPDF.Attributes.getNamedItem("UseISO19005_1")
     If objAttribute_UseISO19005_1 Is Nothing Then
         Set objAttribute_UseISO19005_1 = objXML.createAttribute("UseISO19005_1")
         objNode_ExportPDF.Attributes.setNamedItem objAttribute_UseISO19005_1
     End If
     objAttribute_UseISO19005_1.nodeTypedValue = "true"
     objSpecification.XML = objXML.XML
End Sub

Listing 2: Anpassen des gespeicherten Exports

  • strSpezification: Name der Spezifikation wie zuvor festgelegt
  • strPath: Pfad der zu erstellenden Datei
  • strAccessObject: Name des zu exportierenden Elements, hier der Name des Berichts

In der Prozedur deklarieren wir ein Objekt des Typs ImportExportSpecification sowie ein XML-Dokument mit dem Typ MSXML2.DOMDocument.

Außerdem benötigen wir ein paar Variablen für Node– und Attribute-Elemente. Mit den Node-Variablen referenzieren wir die eigentlichen Elemente, mit den Attribute-Variablen die innerhalb der Elemente angegebenen Attribute.

Im ersten Schritt referenzieren wir über die Auflistung ImportExportSpecifications des Objekts CurrentProject den mit strSpezification übergebenen gespeicherten Export.

Dann erstellen wir das DOMDocument-Objekt und füllen es über die loadXML-Methode mit dem XML-Inhalt der Spezifikation.

Über die selectSingleNode-Methode referenzieren wir das Element ImportExportSpecification mit der Variablen objNode_ImportExportSpecification. Daraus holen wir uns mit Attributes.getNamedItem(„Path“) das Attribut namens Path und referenzieren es mit objAttribute_Path.

Den Wert dieses Attributes passen wir über die Eigenschaft nodeTypedValue auf den Wert aus dem Parameter strPath an.

Danach widmen wir uns dem Unterelement ExportPDF, das wir mit der Variablen objNode_ExportPDF erfassen. Sein Attribut AccessObject enthält den Namen des zu im- oder exportierenden Access-Objekts. Dieses Attribut referenzieren wir mit der Objektvariablen objAttribute_AccessObject und stellen seinen Wert über die Eigenschaft nodeTypedValue auf den Wert aus strAccessObject ein.

Schließlich fehlt, dass wir sicherstellen, dass das Objekt im Format PDF/A-3 exportiert wird. Weiter oben haben wir diese Einstellung bereits beim Erstellen der Spezifikation über die Benutzeroberfläche vorgenommen, aber wir haben dort auch angemerkt, dass wir diese Eigenschaft programmatisch setzen können.

Wenn wir diese nicht im Dialog eingestellt haben, liegt das Attribut UseISO19005_1 normalerweise einfach nicht vor, statt den Wert false zu enthalten.

Also prüfen wir zunächst, ob das Objekt vorhanden ist. Dazu referenzieren wir es über die Attributes.getNamedItem-Funktion mit dem Wert UseISO19005_1 als Parameter. Danach prüfen wir durch den Operator Is Nothing, ob das so gefüllte Objekt objAttribute_UseISO19005_1 vorhanden ist. Ist das nicht der Fall, erstellen wir es mit der createAttribute-Methode des DOMDocument-Objekts aus objXML und fügen es der Auflistung Attributes des Objekts aus objNode_ExportPDF hinzu.

Danach ist sichergestellt, dass das Attribut vorhanden ist und wir können es auf den Wert true einstellen.

Schließlich weisen wir den Wert der Eigenschaft XML des DOMDocument-Objekts der gleichnamigen Eigenschaft von objSpecification zu, wodurch die geänderte Spezifikation gespeichert wird.

Einen Testaufruf können wir nun über die folgende Prozedur starten:

Public Sub Test_GespeichertenExportAnpassen()
     Dim strSpezifikation As String
     Dim strPfad As String
     Dim strBericht As String
     strSpezifikation = "Export PDF/A-3"
     strPfad = CurrentProject.Path & "\Artikel_PDFA3.pdf"
     strBericht = "rptArtikel"
     Call GespeichertenExportAnpassen(strSpezifikation, _
         strPfad, strBericht)
End Sub

Danach sollte der Inhalt der XML-Eigenschaft wie gewünscht aussehen.

Aufruf der Prozedur zum Anpassen des gespeicherten Exports

Diese Prozedur können wir nun so aufrufen, nachdem wir den Bericht geöffnet haben (sofern dieser gefiltert werden soll) und bevor wir den gespeicherten Export mit der Methode RunSaveImportExport aufrufen. Das würde etwa wie folgt aussehen:

Public Sub GespeicherterExportGefiltert_PDFA3()
     Dim strBericht As String
     Dim strPfad As String
     Dim strSpezifikation As String
     strBericht = "rptArtikel"
     strPfad = CurrentProject.Path & "\" _
         & strBericht & ".pdf"
     DoCmd.OpenReport strBericht, acViewPreview, , _
         "ArtikelID <= 15"
     strSpezifikation = "Export PDF/A-3"
     strPfad = CurrentProject.Path & "\Artikel_PDFA3.pdf"
     Call GespeichertenExportAnpassen(strSpezifikation, _
         strPfad, strBericht)
     DoCmd.RunSavedImportExport strSpezifikation
     DoCmd.Close acReport, strBericht
End Sub

Gespeicherten Export komplett selbst erstellen

Bleibt noch eine Optimierung: Wir sparen uns das Zusammenstellen des gespeicherten Exports über die Benutzeroberfläche und erstellen diesen direkt komplett selbst per VBA.

Damit gehen wir dem Risiko aus dem Weg, dass der Benutzer einmal meint, er müsste die Datenbank entschlacken und die gespeicherten Importe und Exporte löschen.

Außerdem kennen wir die Struktur des XML-Dokuments und können dieses nun leicht nachbauen.

Dazu nutzen wir wieder die entsprechenden XML-Objekte. Die dazu benötigte Prozedur finden wir in Listing 3. Die Prozedur erwartet wieder die gleichen Parameter. Sie erstellt ein DOMDocument-Objekt und fügt diesem die übliche erste Zeile hinzu:

Public Sub GespeichertenExportErstellen(strSpezification As String, strPath As String, strAccessObject As String)
     Dim objSpecification As ImportExportSpecification
     Dim objXML As MSXML2.DOMDocument
     Dim objNode_ImportExportSpecification As MSXML2.IXMLDOMNode, objNode_ExportPDF As MSXML2.IXMLDOMNode
     Dim objAttribute_Path As MSXML2.IXMLDOMAttribute, objAttribute_AccessObject As MSXML2.IXMLDOMAttribute
     Dim objAttribute_ObjectType As MSXML2.IXMLDOMAttribute, objAttribute_AutoStart As MSXML2.IXMLDOMAttribute
     Dim objAttribute_Quality As MSXML2.IXMLDOMAttribute, objAttribute_UseISO19005_1 As MSXML2.IXMLDOMAttribute
     
     Set objXML = New MSXML2.DOMDocument
     objXML.appendChild objXML.createProcessingInstruction("xml", "version=''1.0''")
     
     Set objNode_ImportExportSpecification = objXML.createNode(NODE_ELEMENT, "ImportExportSpecification", _
         "urn:www.microsoft.com/office/access/imexspec")
     objXML.appendChild objNode_ImportExportSpecification
     
     Set objAttribute_Path = objXML.createAttribute("Path")
     objAttribute_Path.nodeTypedValue = strPath
     objNode_ImportExportSpecification.Attributes.setNamedItem objAttribute_Path
     
     Set objNode_ExportPDF = objXML.createNode(NODE_ELEMENT, "ExportPDF", "urn:www.microsoft.com/office/access/imexspec")
     objNode_ImportExportSpecification.appendChild objNode_ExportPDF
     
     Set objAttribute_AccessObject = objXML.createAttribute("AccessObject")
     objAttribute_AccessObject.nodeTypedValue = strAccessObject
     objNode_ExportPDF.Attributes.setNamedItem objAttribute_AccessObject
     
     Set objAttribute_ObjectType = objXML.createAttribute("ObjectType")
     objAttribute_ObjectType.nodeTypedValue = "Report"
     objNode_ExportPDF.Attributes.setNamedItem objAttribute_ObjectType
     
     Set objAttribute_AutoStart = objXML.createAttribute("AutoStart")
     objAttribute_AutoStart.nodeTypedValue = "false"
     objNode_ExportPDF.Attributes.setNamedItem objAttribute_AutoStart
     
     Set objAttribute_Quality = objXML.createAttribute("Quality")
     objAttribute_Quality.nodeTypedValue = "screen"
     objNode_ExportPDF.Attributes.setNamedItem objAttribute_Quality
     
     Set objAttribute_UseISO19005_1 = objXML.createAttribute("UseISO19005_1")
     objNode_ExportPDF.Attributes.setNamedItem objAttribute_UseISO19005_1
     objAttribute_UseISO19005_1.nodeTypedValue = "true"
     
     On Error Resume Next
     CurrentProject.ImportExportSpecifications.Item(strSpecification).Delete
     On Error GoTo 0
     Set objSpecification = CurrentProject.ImportExportSpecifications.Add(strSpecification, objXML.XML)
End Sub

Listing 3: Gespeicherten Export vollständig per VBA erzeugen

<?xml version="1.0"?>

Dann erstellt sie das ImportExportSpecification-Element und weist diesem den entsprechenden Namespace zu, bevor es dieses Element an das DOMDocument anhängt. Danach erstellt sie das Attribut Path und weist den Pfad aus strPath zu.

Danach wird das Element ExportPDF eingefügt, wieder mit dem gleichen Namespace. Die folgenden Sätze von jeweils drei Anweisungen erstellen das jeweilige Attribut, weisen diesem den entsprechenden Wert zu und hängen das Attribut an das Element an.

Danach ist das XML-Dokument vollständig. Wir löschen nun bei deaktivierter Fehlerbehandlung eine eventuell vorhandene Import/Export-Spezifikation mit dem Namen aus strSpecification. Dazu nutzen wir die Delete-Methode für das entsprechende Item-Element der ImportExportSpecifications-Auflistung.

Danach erstellen wir dieses neu. Dazu rufen wir die Add-Methode der ImportExportSpecifications-Auflistung auf und übergeben dieser als ersten Parameter den Namen der zu erstellenden Spezifikation aus der Variablen strSpecification und als zweiten den XML-Code aus objXML.XML.

Um diese Prozedur zu testen, verwenden wir die Routine aus Listing 4. Diese definiert wieder den Bericht, den Pfad der zu erstellenden Datei und den Namen der zu erstellenden Spezifikation.

Public Sub Test_GespeichertenExportErstellen()
     Dim strSpezifikation As String
     Dim strPfad As String
     Dim strBericht As String
     strBericht = "rptArtikel"
     strPfad = CurrentProject.Path & "\" & strBericht & "_PDFA3.pdf"
     strSpezifikation = "Export PDF/A-3"
     DoCmd.OpenReport strBericht, acViewPreview, , "ArtikelID <= 15"
     Call GespeichertenExportErstellen(strSpezifikation, strPfad, strBericht)
     DoCmd.RunSavedImportExport strSpezifikation
     DoCmd.Close acReport, strBericht
End Sub

Listing 4: Testen des Erstellens eines gespeicherten Exports

Dann öffnet sie den gegebenenfalls zu filternden Bericht und ruft die Prozedur GespeichertenExportErstellen auf. Diese legt den gespeicherten Export vollständig neu an und löscht einen gegebenenfalls bereits vorhandenen Export gleichen Namens.

Dann führt die aufrufende Prozedur den Export mit der Methode RunSavedImportExport auf und schließt den Bericht wieder.

Zusammenfassung und Ausblick

Die DoCmd.OutputTo-Methode in Microsoft Access bietet eine einfache Möglichkeit, Berichte als PDF-Dokumente zu exportieren, jedoch fehlen ihr gewisse Funktionen, wie das direkte Filtern von Berichten vor dem Export.

Alternativlösungen, wie das Öffnen des Berichts in der Seitenansicht vor dem Export oder das Arbeiten mit gespeicherten Exportschritten, erweitern die Möglichkeiten und bieten Wege zur Erstellung von PDF/A-3-kompatiblen Dokumenten. Dies ist besonders nützlich für rechtlich verbindliche Dokumente, beispielsweise für ZUGFeRD-Rechnungen.Mit etwas VBA-Programmierung lassen sich gespeicherte Exporte flexibel anpassen oder neu erstellen, was die Verwaltung und Automatisierung vereinfacht.

Zukünftig könnte eine tiefere Integration und weitere Anpassung dieser Exporte zusätzliche Möglichkeiten eröffnen, zum Beispiel für Unternehmen, die regelmäßig Dokumentationen im PDF/A-Standard aus Access exportieren möchten.

Downloads zu diesem Beitrag

Enthaltene Beispieldateien:

PDFErstellenVBA.accdb

Download

Schreibe einen Kommentar