Viele Wege führen nach Rom. Dies gilt auch hinsichtlich der Erzeugung von PDF- und Worddokumente.
Eine Lösung konntest Du mit folgenden Tools realisieren:
- PDFCreator (Freeware)
- JazzAge ActiveX/COM (Freeware)
Erzeugung Word-Dokument
Bestehen die Rechungen nur aus einer Seite, würde es sich anbieten, ein Rechungsformular mit Word anzulegen. Innerhalb des Formulars müssen Platzhalter z.B. „#F_100#“, angegeben werden, in denen dann beim Druck die entsprechenden Werten eingesetzt werden. Dieses Formular wird dann im RTF-Format abgespeichert.
Im Prinzip lässt sich dieser Lösungsansatz auch für mehrseitige Formulare anwenden, indem Du mehrer Formularsätze erstellst, und Deine Anwendung auf Basis der Anzahl Artikelpositionen prüft, welcher Formularsatz herangezogen wird.
Im Zuge des Ausdrucks wird das das Formular eingelesen und die Platzhalter durch die entsprechenden Werte ersetzt.
PDF-Dokument erzeugen
Der PDFCreator kann ein gedrucktes Dokument automatisch abspeichern. Dazu sind die entsprechenden Einstellungen vorzunehmen. Im Netzwerkumfeld kann der Benutzername des Users berücksichtigt werden, so das ggf. Druckjobs anderer Stationen, die ebenfalls den PDFCreator zur Erzeugung von PDF-Dokumenten nutzen, nicht überschrieben werden.
Der programmtechnische Ablauf zur Erzeugung einer Rechnung ist dann wie folgt:
- Formularvorlage in einen String einlesen
- Platzhalter mit Werten ersetzen
- String in eine temporäre Datei speichern
- Word aufrufen und die temporäre Datei auf PDfCreator ausgeben
- Die erzeugte PDF-Datei weiter verarbeiten (Mailen, Anzeigen, drucken, etc)
Das nachfolge Codebeispiel soll dies unter der Nutzung von JazzAge veranschaulichen.
Code: Alles auswählen
********************************************************************************************************
Func BuiltRgFormular( oDb)
Local aWerte := { {„#F_100#“, ltrim( Str( oDb:RGNR(1),8,0 ) } ,; // Hier das Array mit Paltzhaltern und Werten
{“#F_200#”, Dtoc( oDb:RGDATUM) } ;
}
Local cFormFile := c:\anwendung\Form\RGForm.rtf“ // Formularvorlage
Local cTempFile := “c:\tmp\RGTemp.rtf” // temporäre RTF-Datei
Local cFileStr
cFileStr := ReadFile( cFormFile )
if empty( cFileStr )
Return ( NIL )
Endif
FOR i := 1 TO len( aWerte)
aItem[i,2] := ConvToAnsiCP( aitem[i,2] ) // Datenbankwerte in das ASN-Format konvertieren
cFileStr := StrTran( cFileStr, aWerte[i,1], aWerte[i,2] , 1, 1) // Platzhalter durch Werte ersetzen
NEXT
If ! WriteFile( cTempFile , cFileStr) // neuen String in eine temporäre RTF-Datei schreiben
Return ( .F.
endif
PrintFile( cTempFile ) // temporäre Datei über Word in eine PDF-Datei ausgeben
PdfFileAction() // Erzeugte PDF-Datei weiter verarbeiten
Return ( NIL )
// Liest Datei in einen String ein
Function ReadFile( cDatei )
Local cStr := ""
Local nSize
Local nHandle
IF ( !file( cDatei ) )
MsgBox("Die Datei: " + cDatei + " wurde nicht gefunden")
Return ( cStr )
ENDIF
nHandle := fopen( cDatei, FO_READ)
IF ( nHandle == -1 )
MsgBox("Fehler beim Öffnen der Datei:" + str( FError() ) )
Return ( cStr )
else
nSize := FSize( nHandle )
cStr := Space( nSize )
fRead( nHandle, @cStr, nSize )
fclose( nHandle )
endif
Return ( cStr )
// Speichert "cStr) in die Datei "cDatei"
Function WriteFile( cDatei, cStr )
Local nHandle
Local lRet := .T.
nHandle := fcreate( cDatei, FC_NORMAL )
IF ( nHandle == -1 )
lRet := .F.
ELSE
FWrite( nHandle, cStr )
FClose( nHandle )
ENDIF
Return ( lRet)
/**************************************************************************
* Drucken einer RTF-Datei "cDocFile" mit Word um eine PDF-Datei zu erzeugen
**************************************************************************/
Function Printfile( cDocFile )
Local aActivePrinter
oWord:=JAObject():New() // Word-Objekt erzeugen
oWord:Connect(JAXPPCREATEACTIVEXOBJECT("ProgID:Word.Application")) // Word-Objekt mit Word-Applikations verbinden
cActivePrinter := <oWord:Activeprinter> // Namen des aktuellen Standardprinter sichern
<oWord:Visible:=.F.> // Word nicht sichtbar
oDoc:= JAObject():new() // Dokumenten-Object erzeugen
<oWord:Activeprinter := “PdfCreator”> // Durckausgabe auf den Durcker "PDFCreator" setzen
oDoc:Connect(<oWord:Documents:Open( cDocFile )>) // Dokumenten-Objekt mit Dokument verbinden
<oDoc:PrintOut("Background",.F., )> // Druckt Dokument im Hintergrund
<oWord:Activeprinter := cActivePrinter> // Windows wieder auf den Standarddrucker setzten
oDoc:Disconnect() // Dokument von Objekt trennen
<oWord:Quit(0)> // Word beeenden
oWord:Disconnect() // Word-Object freigeben
FErase( cDocFile ) // temporäre RTF-löschen (optional)
Return ( .T. )
// Hier erfolgt die Weiterverarbeitung des erzeugten PDF-Dokumentes
Func PdfFileAction()
If ! File( “c:\BENUTZERNAME\Print.pdf” ) // Entspricht der Einstellung für die automatische Speicherung des PDFCreators
Return ( .F.)
endif
..... Do something
Return ( .T.)
Das ganze würde sich auch auf Basis von HTML-Dokumenten realisieren lassen.
Viele Grüße
Olaf