![]() |
PDF-Dateien drucken (viele)
Moin,
wir müssen zwei mal am Tag, Morgens und Mittags, PDF-Dateien drucken, die von unserem ERP System erstellt werden. Die PDF-Dateien liegen als einzelne Dateien in einer Netzwerkfreigabe auf einem Windows Server. In der Regel hat jedes Dokument eine DinA4 Seite Inhalt. Manchmal 2 Seiten. Der Inhalt ist Text und 2 Barcodes. Es handelt sich um jeweils ca. 500 Seiten - die in einer definierten Reihenfolge ausgegeben werden müssen. Die Reihenfolge definiert ein SQL Statement, dass die gewünschte Sortierung erstellt und dann im Datensatz Informationen für den Speicherort und den Dateinamen bereitstellt. Gedruckt wird das ganze auf einem Kyocera TASKalfa 4002i. Gedruckt wird mit Foxit Reader, da der Adobe Acrobat Reader garnicht zum laufen zu bringen war. Dazu haben wir einen Druckjob geschrieben, der in einer Schleife die Datenbank durchläuft und für jede Datei diese Prozedur aufruft:
Delphi-Quellcode:
Der SchellExecAndWait wird verwendet, weil sonst die Dokumente immer wieder durcheinander gedruckt wurden.
procedure TfrmMain.p_PrintAndUpdate(cFileName, cDruckWeg : String);
// Neues Dateiprinten const DprPath = ''; OutPutPath = ''; var Parameters : String; Dcc32Path : String; // 'C:\Program Files (x86)\Foxit Software\Foxit Reader\Foxit Reader.exe'; begin Dcc32Path := FoxitReader; Parameters := '/p ' + cFileName; ShellExecAndWait(Dcc32Path , OutPutPath , Parameters ,'open', 1); end; Seid ein paar Tagen haben wir das Problem, dass zwischendurch einseitige PDF-Dokumente zerstückelt werden, nur zur Hälfte gedruckt werden oder auch leere Blätter ausgegeben werden. Habt Ihr ähnliche Anforderungen, so viel Dokumente auf einmal auszudrucken? Wie habt Ihr das gelöst? Wäre das zusammen-mergen von z. B. jeweils 100 PDF-Dokumenten zu einem einzigen neuen PDF-Dokument eine Option? Dann gäbe es nur noch 5 Druckerwarteschlagen-Einträge. Danke für Tipps. |
AW: PDF-Dateien drucken (viele)
Zitat:
Da kann dann auch grundsätzlich weniger schief gehen. Du hast die Files, kannst die mit entsprechenden Tools zu einem großen PDF zusammen packen, und das dann drucken. Ich würde allerdings ein wenig experimentieren. PDFs zu handhaben ist immer etwas tricky, und kann je nach verwendetem Tooling gerne mal extrem auf den Arbeitsspeicher gehen. Ggf. ist es schneller oder praktikabler, 50x 10 zu machen als 5x 100 (oder irgendwas in der Mitte, wie gesagt, am besten etwas experimentieren). |
AW: PDF-Dateien drucken (viele)
Wenn die PDF Dateien eh von eurem ERP erstellt werden, gibt es dann nicht eine Möglichkeit zweimal zu drucken? Zum Beispiel in ein leichter druckbares Format und in PDF?
Wir verwenden List & Label. Da gibt es ein Export/Vorschauformat als Datei was man sehr einfach später drucken kann. Schön ist dort auch das alle Drucke in einer Datei stecken können und man trotzdem noch jeden einzelnen Druck auswählen kann. |
AW: PDF-Dateien drucken (viele)
Bei meinem letzten Arbeitgeber hatten wir ein ähnlich gelagertes Problem. Mein dortiger Vorgänger hatte es auch über Adobe gelöst. Allerdings wurde dann die API mal geändert, was zu Problemen führte. Ohne API gab es dann Sortierungsprobleme (wie auch bei euch). Foxit haben wir ebenfalls versucht und sind am Ende bei einer Komponente für Delphi gelandet (WPViewPDF-Plus). Damit hatten wir dann volle Kontrolle über den gesamten Druckvorgang und konnten die Dokumente sogar vorher noch für unsere Bedürfnisse anpassen. Es gibt sicher auch andere Komponenten, mit denen man das hinbekommt.
Fazit: Man kann sich nicht auf Drittanbieter verlassen, die ihre API oder Aufrufparameter ändern könnten. Mit der Komponente war dann sogar mehr möglich, als ursprünglich geplant. Auch wenn es nicht ganz billig ist, rechnet es sich, wenn man die eingesparte Zeit, für die ganzen Versuche dagegen rechnet. |
AW: PDF-Dateien drucken (viele)
Hallo rokli,
falls du dich entscheiden solltest die PDF-Dateien zu kombinieren kannst du das relativ einfach mit meinem Ghostscript-Wrapper machen oder Ghostscript direct über die Konsole aufrufen. Example:
Code:
Der code ist ungetestet sollte aber für dich ausreichen.
var
AConverter: TGS_PdfConverter; AFiles: array of string; begin // vorher noch das array mit deinen Dateien füllen AConverter := TGS_PdfConverter.Create('pfad zur dll'); AConverter.ToPdf(AFiles, 'meinekombinierte.pdf', false); FreeAndNil(AConverter); end; Die Bibliothek findest du auf Github ![]() |
AW: PDF-Dateien drucken (viele)
Ihr könntet auch die PDF selber zeichnen/drucken.
Also, wenn ihr die PDFs irgendwie auf ein Canvas oder in eine Datei (Bitmap/PNG/TIFF/......) bekommt, mit PDF-Komponenten oder Programmen (Console mit Parameter, ActiveX, sonstige API) dann könnt ihr das in der gewünschten Reihenfolge in einen oder mehrere Durckaufträge (TPrinter) gezielter rein- und ausgeben. DevExpress, SynPDF oder andere PDF-Komponenten oder direkt aus Reportingtools (ala Fast-Report) Oder auch mal ganz anders gefragt: Warum müsst ihr überhaupt so viel und so "fehleranfällig" organisiert drucken?
|
AW: PDF-Dateien drucken (viele)
Ein weiters Tool, das man selber mitgeben kann/muss wäre
![]() Das ist kostenlos und wurde hier mal von Holger Klemt (IBExperts) empfohlen. |
AW: PDF-Dateien drucken (viele)
Moin,
als erstes mal herzlichen Dank an alle, die sich Gedanken gemacht haben! Dann zu den Fragen, ob das wirklich gedruckt werden muss: Es handelt sich um Kundenbelege, mit denen als erstes Waren im Lager kommissioniert werden und die dann den Waren als Begleitpapiere beigelegt werden. Das Mergen von PDF Dokumenten erscheint mir hier im Moment auch die beste Lösung zu werden. Ich teste mal noch ein bisschen und stelle meine Lösung dann hier ein. Danke. |
AW: PDF-Dateien drucken (viele)
Auch wenn der initiale Overhead relativ hoch ist:
![]() Kann Mergen und Drucken (über Kommandozeile) |
AW: PDF-Dateien drucken (viele)
Ich nutze DevExpress und den TdxComponentPrinter, wenn es vom SPeicher her überschaubar ist, tausende PDFs gehen da in einem 32-bit Programm nicht.
Wenn es unbekannt viele sind, dann lasse ich mir die Seiten als Bilder geben und male sie selbst auf den Printer.Canvas. Ich brauche die allerdings auch als einen grossen Druckjob. |
AW: PDF-Dateien drucken (viele)
Hi ItBlumi,
habe mir Deine Lösung angesehen und heruntergeladen. Dein beigefügte Testprogramm läuft auch. Dann habe ich, als ersten Test, das folgende Programm geschrieben:
Delphi-Quellcode:
Es läuft komplett, ohne Fehlermeldungen durch, tut aber leider nicht was es soll.
procedure TfrmMain.Button2Click(Sender: TObject);
var AConverter : TGS_Pdfconverter; aFiles : Array[0..9] of String; sQuellPfad : String; sZielPfad : String; begin sQuellPfad := 'C:\Temp\pdffen\quell\'; sZielPfad := 'C:\Temp\pdffen\'; aFiles[1] := sQuellPfad + '0174163013.pdf'; aFiles[2] := sQuellPfad + '0174163020.pdf'; aFiles[3] := sQuellPfad + '0174164010.pdf'; aFiles[4] := sQuellPfad + '0174164027.pdf'; aFiles[5] := sQuellPfad + '0174164034.pdf'; aFiles[6] := sQuellPfad + '0174164041.pdf'; aFiles[7] := sQuellPfad + '0174164065.pdf'; aFiles[8] := sQuellPfad + '0174164072.pdf'; aFiles[9] := sQuellPfad + '0174164089.pdf'; AConverter := TGS_PdfConverter.Create(sZielPfad); Aconverter.ToPdf(aFiles, sZielPfad + 'new.pdf', false); FreeAndNil(AConverter); ShowMessage('fertig'); end; Ich habe versucht in der GS_Converter nachzusehen, was da gemacht wird, verstehe aber nicht alles und komme daher nicht wirklich weiter. Würdest Du da einmal draufschauen? Danke. |
AW: PDF-Dateien drucken (viele)
Statt PDF als PostScript speichern?
"Gute" Drucker verstehen das direkt.
Delphi-Quellcode:
aber sollte wohl auch im Delphi über CopyFile oder TStream funktionieren, ohne ein Zusatzprogramm dazwischen.
COPY abc.ps \\servername\printername
Vielleicht sogar
Delphi-Quellcode:
oder eben \\localhost\printername
COPY abc.ps LPT1
|
AW: PDF-Dateien drucken (viele)
Hi rokli,
schau mal in den folgenden Eigenschaften was er dir dort ausgibt, wenn keine Datei erstellt wird dann dürfte ein Fehler aufgetreten sein.
Delphi-Quellcode:
AConverter.Debug := True;
// string liste mit dem was er macht AConverter.StdOut // errors als strings sollte eigentlich leer sein AConverter.LastErrors // error code -> dieser sollte 0 sein falls alles funktioniert hat AConverter.LastErrorCode |
AW: PDF-Dateien drucken (viele)
AConverter.ToPdf gibt dir auch eine Boolean Ausdruck zurück dieser sollte den Fehlercode (LastErrorCode) vor dem beenden der Prozedur prüfen.
Habe Dir das Ganze etwas anschaulicher zusammen gestellt.
Delphi-Quellcode:
Edit: Es kann auch sein das Ghostscript versucht zu ermitteln ob er Schreibrechte in dem Verzeichnis besitzt, dass kann mit unter schief gehen. Dies kannst du mit NOSAVER unterdrücken. Ich habe das noch zusätzlich hinzugefügt im obigen Code.
procedure TfrmMain.Button2Click(Sender: TObject);
var AConverter : TGS_Pdfconverter; aFiles : Array[0..9] of String; sQuellPfad : String; sZielPfad : String; begin sQuellPfad := 'C:\Temp\pdffen\quell\'; sZielPfad := 'C:\Temp\pdffen\'; aFiles[1] := sQuellPfad + '0174163013.pdf'; aFiles[2] := sQuellPfad + '0174163020.pdf'; aFiles[3] := sQuellPfad + '0174164010.pdf'; aFiles[4] := sQuellPfad + '0174164027.pdf'; aFiles[5] := sQuellPfad + '0174164034.pdf'; aFiles[6] := sQuellPfad + '0174164041.pdf'; aFiles[7] := sQuellPfad + '0174164065.pdf'; aFiles[8] := sQuellPfad + '0174164072.pdf'; aFiles[9] := sQuellPfad + '0174164089.pdf'; AConverter := TGS_PdfConverter.Create(sZielPfad); AConverter.Params.NoSaver := True; AConverter.Debug := True; // debug Ausgabe der Bibliothek aktivieren if (AConverter.ToPdf(aFiles, sZielPfad + 'new.pdf', false)) then ShowMessage('fertig') else begin ShowMessage('Fehler: ' + AConverter.LastErrors); AConverter.StdOut.SaveToFile(sZielPfad + 'output.log'); // Die Prozess Ausgabe speichern end; FreeAndNil(AConverter); |
AW: PDF-Dateien drucken (viele)
Zitat:
|
AW: PDF-Dateien drucken (viele)
Zitat:
![]()
Code:
(und vieles vieles mehr...)
pdftk datei1.pdf datei2.pdf ... dateix.pdf cat output gesamt.pdf
|
AW: PDF-Dateien drucken (viele)
Liste der Anhänge anzeigen (Anzahl: 1)
Habe Dir nochmal ein kleines Test Projekt zusammen gestellt und dies mit der Version die im Github ist getestet.
Am Anfang hatte ich das gleiche Problem mit einer älteren Version. Habe Dir hier nochmal eine Liste mit möglichen Fehlerquellen und Lösungsmöglichkeiten zusammen gestellt. Diese ist auch in dem kleinen Testprojekt vorhanden.
Viele Grüße Jan |
AW: PDF-Dateien drucken (viele)
Wir haben so eine ähnliche Situation.
Bekommen viele PDF-Belege per email-Anhang die wir dann im Stapel ausdrucken. Wir können da auch sumatra empfehlen, was wir auch auf Empfehlung von Holger Klemt schon länger einsetzen. das ganze findet man auf sumatrapdfreader.org. Da gibt es auch eine Doku zu der Commandline. Bei uns sieht es dann ungefähr so aus:
Delphi-Quellcode:
procedure TF1.belege_drucken;
var adrucker: string sumatra_pfad : string; commandline : string; adateiname: string; begin adrucker := (dein Drucker); adateinmae := (deine PDF-Datei); sumatra_pfad := 'C:\Sumatra\SumatraPdf.exe'; commandline := '-print-to ' + '"' + adrucker + '" "' + adateiname + '"'; ShellExecute(0,'open',pchar(sumatra_pfad),pchar(commandline),nil,SW_ShowNormal); |
AW: PDF-Dateien drucken (viele)
Zitat:
Wir setzen pdfbox ein und sind hier sehr zufrieden (verglichen mit der Delphi-Native Komponente die wir vor Jahren hatten). Deshalb kann ich nur davon sprechen, das diese eine Lösungsmöglichkeit wäre. |
AW: PDF-Dateien drucken (viele)
Die Frage war bei uns dann eine andere..
Müssen wir die Dateien eigentlich alle drucken? Wir speichern PDF-Belege mittlerweile alle in der firebird-Datenbank als Blob.. Man hat dann u.a. auch nicht mehr so viele Dateien, sondern insgesamt nur noch eine. Kommt halt auf die Bedürfnisse des Anwenders an ;-) |
AW: PDF-Dateien drucken (viele)
Zitat:
OK, man könnte die Datenbank auf viele USB-Sticks, SD-Cards oder große RFDI-Chips kopieren. Oder in übergroße QR-Codes und die dann ausdrucken. :lol: Zitat:
Die Begleitpapiere müssen also so oder so. Eventuell könne man sowas auch direkt auf die Verpackung drucken. (innen und außen) ![]() ![]() ![]() ![]() Und wenn Unterlagen für Kommissionierung und Begleitung nicht die Selben sind, jene als digitale Medien, ala ESL/RFID/... Einige der ESL-Tags, welche wir demnächst einführen, haben RFID direkt integiert, welches ber Funk umgeschrieben werden kann. Aktuell nutzen wir Barcodes auf dem ePaper, aber RFID hätte zum elektronischen Lesen einige Vorteile. (kein optischer Platzbedarf und einfacher/schneller/sicherer lesbar) Zitat:
BLOB als Datei, aber natürlich der restliche Verwaltungs-Datensatz in der DB. Und teilweise so, dass bestimmte Dateien auf WORM-Laufwerke können. Wegen besserem Backup und Datensicherheit und z.B. WORM (Write Once Read Many) wegen Datenschutz- und steuerrechtlichen Verordnungen. Gut, noch besser wäre es, wenn man auch einige Zusatzinfos noch bei den Dateien mit ablegt ... falls mal die Software/DB kaputt ist und es dort kein Funktionierendes Backup gibt, dann Zuordnungsinfos zu/bei/an/in der jeweiligen Datei. ALLES in einer DB, dann vieleicht besser noch eine Partitionierung der DB vornehmen. z.B. jährliche BLOBs je in einer DB-Datei, welche nach dem JAHR nicht/kaum noch verändert wird. Ein Backup der Festplatte wird sich freuen, wenn sich nicht ständig überall immer wieder alles im Dateisystem ändert. |
AW: PDF-Dateien drucken (viele)
Ja dann würde ich es wohl mit sumatra machen.
|
AW: PDF-Dateien drucken (viele)
Herzlichen Dank für das große Interesse!
@Jan 1. Habe Deine Vorgaben eingebaut und bekomme die Fehlermeldung [Content] Fehler: The File: does not exist Daraufhin hab ich mal eine bestehende PDF Datei ins Zielverzeichnis kopiert und NEW.PDF genannt. 2. Das Log lässt sich leider nicht kompilieren. Da meldet der Kompiler: [dcc32 Fehler] FMain.pas(413): E2362 Auf protected-Symbol TGS_Api.StdOut kann nicht zugegriffen werden 3. Dein Test-Programm habe ich erfolgreich nutzen können. Als nächstes werde ich die Logiken mal in mein Testprogramm übernehmen. Bis dann. |
AW: PDF-Dateien drucken (viele)
zu 2. Entschuldige bitte das hatte ich nur im Forum geschrieben und nicht kompiliert, es muss natürlich StdOutLog heißen.
Ich habe auch noch eine neue Version fertig gemacht in der du mit
Delphi-Quellcode:
oder
if (AConverter.Print('Dateien mit ; getrennt einfügen', 'Windows Drucker Name', False)) then ...
Delphi-Quellcode:
die zusammen gefügte Datei direkt Drucken kannst. Falls der Drucker nicht gefunden werden kann, dann zeigt Ghostscript den Windows Druck Dialog an in dem man einen Drucker auswählen kann. Falls er ihn findet schickt er sofort den Druckauftrag zum Drucker.
if (AConverter.Print(aFiles, 'Windows Drucker Name', False)) then ...
|
AW: PDF-Dateien drucken (viele)
Hi Jan,
aus deinem Test-Coding: 1. Bitte passe vorher den Suchpfad in den Projekt optionen an damit er die Lib findet ... ich habe die *.libs immer dem Projekt hinzugefügt. in welchen Parameter kann ich das denn eintragen? |
AW: PDF-Dateien drucken (viele)
So ist es bei mir im XE6, ich hoffe das es sich nicht geändert hat.
Projekt -> Optionen -> Delphi-Compiler Dann das Ziel: Alle Konfigurationen - Alle Plattformen Da dürfte dann eine Zeile mit dem "Suchpfad" stehen und dort den Pfad zur Lib eingeben. Du kannst natürlich auch die Dateien direkt einbinden, dass sollte keinen Unterschied machen. |
AW: PDF-Dateien drucken (viele)
Hallo alle zusammen!
Die Software von Jan läuft sehr gut. Mein Fehler in der ersten Version wahr wohl tastächlich, dass ich die Dateinamen in einerm Array zur Verfügung gestellt habe. Es hätte aber wohl eine Semikolon separierte CSV Datei sein sollen, die dann als Input Liste dem
Delphi-Quellcode:
zur Verfügung gestellt werden muss.
AConverter.ToPdf
Zum Nachvollziehen die beiden wesentlichen Proceduren:
Delphi-Quellcode:
Meinen besondereren Dank and Jan, der sich viel Mühe mit mir gegeben hat.
procedure TfrmGsTst.Button1Click(Sender: TObject);
var AConverter: TGS_PdfConverter; AFiles: string; begin M_Output.Clear; sQuelle := 'C:\Temp\pdffen\quell\'; sZiel := 'C:\Temp\pdffen\'; sDll := 'C:\Temp\pdffen\'; AConverter := TGS_PdfConverter.Create(sDll); FLogFile := TStringList.Create; try try AConverter.OnStdOut := Log; // komplette Debug Ausgabe AConverter.OnStdError := Log; {$IFDEF DEBUG} AConverter.Debug := True; // Das kannst du später entfernen {$ENDIF} AFiles := sQuelle + '0174163013.pdf;' + sQuelle + '0174163020.pdf;' + sQuelle + '0174164010.pdf;' + sQuelle + '0174164027.pdf;' + sQuelle + '0174164034.pdf;' + sQuelle + '0174164041.pdf;' + sQuelle + '0174164065.pdf;' + sQuelle + '0174164072.pdf;' + sQuelle + '0174164089.pdf;' + sQuelle + '0174164096.pdf;' + sQuelle + '0174164119.pdf;' + sQuelle + '0174165024.pdf;' + sQuelle + '0174165031.pdf;' + sQuelle + '0174165048.pdf;' + sQuelle + '0174165055.pdf;' + sQuelle + '0174165062.pdf;' + sQuelle + '0174166014.pdf;' + sQuelle + '0174167011.pdf;' + sQuelle + '0174167028.pdf;' + sQuelle + '0174167035.pdf;' + sQuelle + '0174167042.pdf;' + sQuelle + '0174167059.pdf;' + sQuelle + '0174167066.pdf;' + sQuelle + '0174167073.pdf;' + sQuelle + '0174167080.pdf;' + sQuelle + '0174167097.pdf;' + sQuelle + '0174167103.pdf;' + sQuelle + '0174167110.pdf;' + sQuelle + '0174167127.pdf;' + sQuelle + '0174167134.pdf;' + sQuelle + '0174167141.pdf;' + sQuelle + '0174167158.pdf;' + sQuelle + '0174168018.pdf;' + sQuelle + '0174168025.pdf;' + sQuelle + '0174168032.pdf;' + sQuelle + '0174169015.pdf;' + sQuelle + '0174170011.pdf'; if (not AConverter.ToPdf(AFiles.Split([';']), sZiel + 'New01.pdf', False)) then begin ShowMessage('Fehler: ' + AConverter.LastErrors); FLogFile.SaveToFile(sZiel + 'output.log'); end else ShowMessage('Convertierung abgeschlossen!'); except on E: Exception do ShowMessage('Fehler: ' + E.Message); end; finally FreeAndNil(AConverter); FreeAndNil(FLogFile); end; end; procedure TfrmGsTst.Log(const AStr: string); begin (* hier bekommst du die gefilterten informationen + debug information *) // als output in einem Memo M_Output.Lines.Text := M_Output.Lines.Text + AStr; // als output in eine Datei FLogFile.Text := FLogFile.Text + AStr; // scroll down M_Output.SelStart := Length(M_Output.Lines.Text); M_Output.SelLength := 0; end; Allen ein schönes Wochenende Beste Grüße |
AW: PDF-Dateien drucken (viele)
Statt der vielen sQuelle hätte ich ein Zeichen (z.B. *) und dann Replace gemacht,
aber wozu erst zusammen und dann split, wenn man es auch gleich fertig haben kann. :wink:
Delphi-Quellcode:
oder falls später stückchenweise, via Schleife und so.
AFiles: TArray<string>;
begin AFiles := [sQuelle + '0174163013.pdf', sQuelle + '0174163020.pdf', sQuelle + '0174164010.pdf', sQuelle + '0174164027.pdf', sQuelle + '0174164034.pdf', ... ];
Delphi-Quellcode:
AFiles := AFiles + [sQuelle + '0174163013.pdf'];
... AFiles := AFiles + [sQuelle + '0174163020.pdf', sQuelle + '0174164010.pdf']; ...
Delphi-Quellcode:
M_Output.Lines.Add(AStr); // geht auch mit Zeilenumbrüchen drin (und auch unnötig erst ALLEN Text rauszuholen und wieder neu reinzuzun)
// und SelStart ist auch nicht nötig, weil macht Add schon |
AW: PDF-Dateien drucken (viele)
Zitat:
Deswegen ist das Ganze über die Text property gelöst. Edit: Das einzige was ich noch dagegen machen könnte um dies benutzerfreundlich zu gestalten, wäre einen internen Text Puffer zu verwenden und nur ganze Zeilen auszugeben. Das werde ich mir gleich mal auf meine ToDo Liste schreiben. |
AW: PDF-Dateien drucken (viele)
Hallo Zusammen!
Die Lösung von itblumi läuft sehr gut! Was nicht funktionierte, war die Angabe eines UNC-Pfades für den Quell-Ort der zusammen zu fassenden PDF-Dokumente. Aber über ein gemapptes Laufwerk kein Problem. Insgesamt ist das eine gute, auch sehr perfomante Lösung für unser Druckproblem. Beste Grüße |
Alle Zeitangaben in WEZ +1. Es ist jetzt 23:41 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz