PDF-Erzeugung – Teil 1

15.09.2006 von Lorenz  Hölscher
Das PDF-Format bietet sich immer zum Austausch von Dokumenten und Daten, beispielsweise Berichten aus Access an, wenn sie von Benutzern gelesen aber nicht verändern werden sollen. Das Erzeugen von PDF-Dateien ist aber in der Regel kompliziert, vor allem was die Auswahl eines Druckertreibers für die Druckausgabe in Access angeht. Die zweiteilige Artikelfolge zeigt Ihnen die Grundlagen der PDF-Erzeugung und stellt einige interessante Tools vor.

Adobe stellt zwar Developer-Bibliotheken von Acrobat zur Verfügung, mit denen Sie PDF-Dateien erzeugen können, die sind aber natürlich nicht kostenlos, sondern im Gegenteil sehr teuer. Daher lohnt es sich, über preiswerte Alternativen nachzudenken.

Die Möglichkeiten im Überblick

Da VBA auch den Einsatz externer Komponenten unterstützt, gibt es zwei Möglichkeiten, PDFDateien zu erzeugen. Beide können Sie auch in Access einsetzen:

Auch wenn Sie eine COM-Komponente verwenden, benötigen Sie oft zusätzlich einen PDFDruckertreiber, der dann von der Komponente verwendet wird. Der Vorteil ist dabei allerdings, dass Sie keine Probleme haben, in Access auf dem PDF-Druckertreiber zu drucken, weil das die Komponente übernimmt und steuert.

Die Voraussetzungen schaffen

Damit Sie die meisten der nachfolgenden Beispiele nutzen können, ist die Installation eines PDF-Druckertreibers notwendig. Verfügen Sie über Adobe Acrobat, können Sie den Destiller 4 oder höher oder alternativ den PDFWriter 4 oder höher von Adobe verwenden. Auch Adobe PDF 6 und 7 funktionieren.

Gerade wenn Sie Ihre Anwendungen für andere entwickeln, ist es sinnvoll, auf ein kostenloses oder preiswerteres Tool zurückzugreifen. Eine Reihe der Druckertreiber benötigt zusätzlich Ghostscript. Falls Sie einen solchen Treiber verwenden möchten, müssen Sie zuerst Ghostscript und erst danach den PDF Druckertreiber installieren.

PDF-Druckertreiber

- PDF-Machine: www.broadgun.de (ab 59 Euro), kostenlose Demo verfügbar
- FreePDF XP, http://freepdfxp.de/fpxp.htm (kostenlos)
- PDF4U, www.pdfpdf.com/pdf4u.html (ab 49 US-$), kostenlose Testversion verfügbar
- PDF995, www.wintotal.de/softw/index.php?id=1077 (ab 19,90 US-$) kostenlose Testversion (mit Popupwerbung) verfügbar
- PDFFactory, www.context-gmbh.de (ab 50 Euro), kostenlose Testversion verfügbar
- Win2pdf, www.win2pdf.com (ab 35 US-$), kostenlose Testversion verfügbar
- Ghostscript, http://prdownloads.sourceforge.net/ghostscript/ gs853w32.exe?use_mirror=mesh (kostenlos)

Info: AP-PDFPrint.DLL

Name: AP-PDFPrint.DLL
Anbieter: SEV (www.tools4vb.com)
Preis: ca. 70 Euro, 60-Tage-Testversion verfügbar
Voraussetzungen: Windows 2000/XP und ein unterstützter PDF-Druckertreiber

Die PDF-Ausgabe per Druckertreiber

Haben Sie einen der Druckertreiber installiert, können Sie PDF-Dateien erzeugen, indem Sie beispielsweise für Berichte den Druckertreiber als Standarddrucker für den Bericht festlegen und ihn dann auf dem Druckertreiber ausgeben. Das würde jedoch voraussetzen, dass Sie wissen, welchen der Druckertreiber Ihr Kunde oder Anwender zur Verfügung hat und dass die Definition des Standarddruckertreibers auch funktioniert.

Aufgrund verschiedener Probleme mit der Druckausgabe in Access ist es in der Praxis jedoch meist nur möglich, mit dem Standarddruckertreiber von Windows zu drucken. Diesen Treiben müssten Sie per API-Deklaration ändern, wenn Sie den PDF-Drucker wählen möchten. Darüber hinaus gibt es bei der Druckausgabe das Problem, dass die meisten PDF-Tools Fenster für Einstellungen anzeigen, in denen der Benutzer den Pfad und den Namen der PDF-Datei eingeben muss. Auch das macht den direkten Ausdruck auf diesen Druckertreibern problematisch. Dennoch gibt es natürlich eine Lösung für alle diese Probleme, die Komponente AP-PDF Print. DLL.

Die Komponente steuert den installierten Druckertreiber so, dass Sie damit problemlos PDFDateien ausgeben können. Unterstützt werden dazu die folgenden Treiber:

Nach dem Download installieren Sie die Komponente über das mitgelieferte Setup-Programm, bevor Sie sie nutzen können.

Anders als bei anderen Komponenten, die Sie im zweiten Teil der Artikelfolge kennen lernen werden, erstellen Sie hier das Druckdokument nicht über die Methoden und Eigenschaften der Komponente, sondern rufen lediglich den Drucken- Befehl von Access bzw. dem zu druckenden Bericht auf. Sie müssen also zunächst einen entsprechenden Bericht erstellen, um diesen dann auszudrucken zu können.

Es gibt zudem noch einen weiteren Unterschied. Diese DLL binden Sie nicht über Verweise in Ihr Projekt ein, sondern verwenden die in der DLL vorhandenen Funktionen über das DECLARE- Statement. Hierzu werden alle Funktionen über Declare-Anweisungen dem Programm bekannt gemacht. Sie müssen dazu einen ausführlichen Deklarationsblock erstellen (Listing 1). Den finden Sie allerdings in der mitgelieferten Hilfe, sodass Sie ihn nur kopieren müssen.

Public Declare Function apPDF_Init Lib "APPDFPRINT.DLL" Alias "PrintInit" ( _
ByVal sInit As String) As Integer
Public Declare Function apPDF_GetDefaultPrinter Lib "APPDFPRINT.DLL" _
Alias "GetDefaultPrinter" () As String
Public Declare Function apPDF_GetAllPrinters Lib "APPDFPRINT.DLL" Alias _
"GetAllPrinters" () As String
Public Declare Function apPDF_SetDefaultPrinter Lib "APPDFPRINT.DLL" Alias _
"SetDefaultPrinter" (ByVal sPrinter As String) As Integer
Public Declare Sub apPDF_PrintSetIniFile Lib "APPDFPRINT.DLL" Alias _
"PrintSetIniFile" (ByVal sIniFile As String)
Public Declare Function apPDF_PrintStart Lib "APPDFPRINT.DLL" Alias _
"PrintStart" (ByVal PDFType As Integer, ByVal sFilename As String) As Integer
Public Declare Function apPDF_PrintGetPath Lib "APPDFPRINT.DLL" Alias _
"PrintGetPath" (ByVal PDFType As Integer) As String
Public Declare Function apPDF_PrintEnd Lib "APPDFPRINT.DLL" Alias _
"PrintEnd" (ByVal PDFType As Integer, ByVal sDestFile As String) As Integer
'KONSTANTEN DER UNTERSTÜTZTEN PDF-TOOLS
Public Const PDF_ACROBATDISTILLER = 0
Public Const PDF_PDFWRITER = 1
Public Const PDF_ACROBAT67 = 2
Public Const PDF_PDFMACHINE = 3
Public Const PDF_FREEPDF = 4
Public Const PDF_PDF4U = 5
Public Const PDF_PDF995 = 6
Public Const PDF_PDFFACTORY = 7
Public Const PDF_WIN2PDF = 8
'FUNKTIONS-RÜCKGABEWERTE
Public Const ERR_PDF_OK = 1
Public Const ERR_PDF_INIT_FAILURE = -99
Public Const ERR_PDF_SYSTEM_NOT_SUPPORTED = -999

Hilfsfunktionen

Darüber hinaus benötigen Sie zur Nutzung der Komponente noch ein paar Hilfsfunktionen getDBPfad, Warten, Dateiinbenutzung und Dateivorhanden. (Listing 2).

Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As
Integer, ByVal dwMilliseconds As Integer) As Integer
Public Function Warten(ByVal intSek As Integer)
WaitForSingleObject -1, intSek
End Function
Function getDBPfad() As String
getDBPfad = Left(CurrentDb.Name, _
Len(CurrentDb.Name) - _
Len(Dir(CurrentDb.Name)))
End Function
Function Dateivorhanden(strDatei As String)
If Dir(strDatei) <> "" Then
Dateivorhanden = True
Else
Dateivorhanden = False
End If
End Function
Function Dateiinbenutzung(strDatei As String) As Boolean
Dim intD As Integer
Dateiinbenutzung = True
On Error GoTo FEHLER
'Versuchen, die Datei exklusiv zu öffnen
intD = FreeFile
Open strDatei For Binary Lock Read Write As #intD
Close #intD
Exit Function
FEHLER:
If Err.Number = 70 Then
Dateiinbenutzung = False
Resume Next
End If
End Function

Die Funktion Warten sorgt dafür, dass Access eine vorgegebene Zeitspanne wartet, bevor mit der nächsten Anweisung fortgefahren wird. Das ist deshalb notwendig, weil mit der Übergabe des Druckauftrags an den Druckertreiber der Auftrag aus Sicht von Access abgeschlossen ist. Die Komponente erfordert es jedoch, dass eine Wartezeit nach Initialisierung eingehalten wird, bis die Postscript-Datei erzeugt ist, aus der dann die PDF-Datei erstellt wird. Mit der Funktion Dateivorhanden können Sie prüfen, ob die Ausgabedatei schon vorhanden ist. Falls ja, können Sie mit der Funktion Dateiinbenutzung feststellen, ob diese noch geöffnet und damit noch nicht vollständig erzeugt wurde. Um das zu prüfen, versucht die Funktion einfach, die Datei binär zu öffnen. Gelingt dies nicht, wird die Datei noch verwendet, ansonsten wird sie geschlossen.

Ausdruck und PDF-Erzeugung

Der Ausdruck selbst ist mit diesen Vorbereitungen nun denkbar einfach (Listing 3). Zunächst rufen Sie die Funktion apPDF_Init auf. Verwenden Sie die Testversion, dann übergeben Sie eine leere Zeichenfolge, ansonsten den Lizenzcode, den Sie nach der Registrierung erhalten. Der Rückgabewert der Funktion gibt an, ob die Initialisierung korrekt erfolgt ist. In diesem Fall muss sie den Wert 1 (ERR_PDF_OK) zurückgeben. Falls das nicht der Fall ist, sollten Sie die Prozedur mit einer Fehlermeldung verlassen.

Option Compare Database
Const appName = "PDFAusgabe"
Sub PDFAusgabe()
Dim lngErg As Long
Dim strZielPfad As String
strZielPfad = getDBPfad() & "berDaten"
'Initialisieren
lngErg = apPDF_Init("")
If lngErg <> ERR_PDF_OK Then
MsgBox "Die Komponente konnte nicht initialisiert werden!", _
vbCritical, "Abbruch"
Exit Sub
End If
'Aufruf der PrintStart-Funktion
If apPDF_PrintStart(PDF_FREEPDF, strZielPfad & ".pdf") Then
'Warten, bis alle notwendigen Optionen eingestellt wurden
Warten 2000
'Ausdruck des Berichts
DoCmd.OpenReport "berDaten", acViewNormal
'Es wird geprüft, ob die Postscript-Datei be-reits existiert
Do While Dateivorhanden(strZielPfad & ".ps") = False
Warten 2000
Loop
'Prüfen, ob die PS-Datei noch vom FreePDF-Treiber in Benutzung ist
Do
DoEvents
Loop Until Dateiinbenutzung(strZielPfad & ".ps") = False
'Warten auf den Druckertreiber
Warten 2000
'Druck beenden
apPDF_PrintEnd PDF_FREEPDF, ""
Else
'Es ist ein Fehler beim Versuch, den Drucker zu wechseln, aufgetreten
MsgBox "Beim Drucken ist ein unbekannter Fehler aufgetreten.", _
vbOKOnly + vbCritical + vbDefaultButton1, appName
End If
End Sub

Mit der Funktion apPDF_PrintStart starten Sie die PDF-Erzeugung und geben mit dem ersten Parameter an, welches Tool dazu verwendet werden soll. Der zweite Parameter legt Namen und Pfad der zu erstellenden PDF-Datei fest. Hier wird dazu die Variable strZielpfad übergeben, die mit Hilfe der Funktion getDBPfad den Datenbankordner ermittelt und daran den Berichtsnamen ohne Dateinamenserweiterung anhängt.
Das ist wichtig, weil als Zwischenstufe für die PDF-Erzeugung eine PostScript-Datei (.ps) erzeugt wird. Daher benötigen Sie den Dateinamen mehrmals mit verschiedenen Dateinamenserweiterungen.

Bevor Sie fortfahren, müssen Sie nun dafür sorgen, dass das PDF-Tool gestartet und eingestellt wird. Dafür sorgt die Funktion Warten, die hier 2 Sekunden wartet, bevor der Code fortgesetzt wird. Anschließend starten Sie den Ausdruck. Hier erfolgt dies durch Öffnen des Berichts über die OpenReport-Methode. Danach führen Sie die Schleife so lange aus, bis eine Postscript- Datei erstellt ist, die den gleichen Namen und Pfad wie die PDF-Datei hat. Ist sie vorhanden, wird noch einmal eine Warteschleife von 2 Sekunden eingelegt und dann mit einer weiteren Schleife gewartet, bis die Funktion Dateiinbenutzung für die Postscript-Datei den Wert false zurückgibt. Dann ist der Druckertreiber FreePDF fertig und die PDF-Erzeugung wird mit PrintEnd abgeschlossen.

Zusammenfassung

AD-PDFPrint.DLL ist eine durchaus brauchbare Komponente, wenngleich sie nicht so flexibel einsetzbar ist wie Komponenten, bei denen Sie das PDF-Dokument unabhängig von einer Druckausgabe gestalten können.

Probleme könnten zudem die Wartezyklen machen, die ausreichend lang sein müssen, damit auch langsame Rechner damit zurechtkommen. Ein schneller Rechner wird damit allerdings etwas ausgebremst.

Diese beiden Nachteile macht jedoch der unglaublich günstige Preis wett, vor allem in Kombination mit FreePDF. Gerade für Entwickler, die nur gelegentlich Daten als PDF ausgeben müssen, ist sie daher durchaus sehr gut geeignet.

Wie geht es weiter?

Im nächsten Artikel der Artikelfolge lernen Sie alternative Tools kennen, die Sie zwar flexibler einsetzen können, deren Verwendung dafür jedoch auch etwas komplexer ist. Vermutlich werden Sie dann die Einfachheit der hier vorgestellten Komponente zu schätzen wissen.