Anzeige
Anzeige
HERBERS
Excel-Forum (Archiv)
20+ Jahre Excel-Kompetenz: Von Anwendern, für Anwender
Anzeige
Inhaltsverzeichnis

PDF-Dateien in Ordner über Microsoft Print to PDF speichern

Forumthread: PDF-Dateien in Ordner über Microsoft Print to PDF speichern

PDF-Dateien in Ordner über Microsoft Print to PDF speichern
24.12.2025 09:06:34
Bernd_CH
Hallo VBA-Profis

Ich habe inzwischen viel gelesen und versucht, aber ich scheitere offensichtlich bereits an den Basics, daher hoffe ich, dass mir hier jemand helfen kann.

In einem Ordner sind beliebig viele PDFs abgelegt, welche teilweise signiert, schreibgeschützt oder Konformität mit PDF/A-Standard verlangen. Für eine "idiotensichere" Archivierung dieser PDFs sollen diese ganzen "technischen Dinge" vom PDF entfernt werden. Dies funktioniert super, wenn ich im Adobe Acrobat die Dateien öffne und über den Microsoft Print to PDF wieder als PDF "drucke" bzw. speichere.
Leider ist dies recht aufwändig, wenn ich das manuell bei jeder einzelnen PDF-Datei machen muss. Daher dachte ich, dies könnte über ein VBA-Makro gelöst werden. Und da ich früher in Excel schon mit Makros in Kontakt war, dachte ich, ich könnte dieses Makro ganz einfach über eine Schaltfläche in einem Excel starten.

Leider hört es dann schon mit meinem Kenntnissen auf. Hätte jemand von Euch brauchbare Vorschläge? Die KI hat mir zwar unmengen an Code geliefert, aber es war immer wieder ein Fehler drin und nachvollziehen konnte ich den Code leider nie.

Herzlichen Dank für Eure Unterstützung.

VG
Bernd
Anzeige

18
Beiträge zum Forumthread
Beiträge zu diesem Forumthread

Betreff
Datum
Anwender
Anzeige
AW: PDF-Dateien in Ordner über Microsoft Print to PDF speichern
24.12.2025 11:38:01
Ulf
Hi,
von: https://stackoverflow.com/questions/77289258/vba-code-shellexecute-not-sending-pdf-doc-to-printer
sollte das deine Wünsche erfüllen:
#If VBA7 Then

Declare PtrSafe Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _
ByVal hWnd As LongPtr, ByVal lpOperation As String, ByVal lpFile As String, _
ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongPtr
#Else
Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" ( _
ByVal hWnd As Long, ByVal lpOperation As String, ByVal lpFile As String, _
ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
#End If

Sub PrintPDFFiles()
Dim FolderPath As String, FileName As String, PDFPath As String
Dim hWnd As LongPtr, Result As LongPtr

'Your PDF files are located
FolderPath = ThisWorkbook.Path & "\"

hWnd = Application.hWnd

' Loop All files in the folder
FileName = Dir(FolderPath & "*" & ".pdf")
Do While FileName > ""
PDFPath = FolderPath & FileName
Result = ShellExecute(hWnd, "Print", PDFPath, vbNullString, vbNullString, 3)

If Result = 32 Then
MsgBox "Failed to print " & PDFPath
Else
' Adjust the duration as needed
Application.Wait Now + TimeValue("00:00:05")
Call Shell("taskkill /f /im AcroRd32.exe", vbHide)
End If
FileName = Dir
Loop

Ggf. den Standard-Drucker auf MS um-und zurückstellen
hth
Ulf
Anzeige
Folgend ein...
26.12.2025 13:01:49
Case
Moin Bernd, :-)

... VBA Code mit GhostScript. Das ist IMHO die einfachste Möglichkeit um den ganzen Problemen mit Dialogen usw. aus dem Weg zu gehen. ;-)

Dazu musst du aber GhostScript (für die richtige Windowsversion) installieren (man kann GhostScript aber auch Portable machen, wenn man nichts installieren darf/kann): ;-)
https://www.ghostscript.com/
https://www.ghostscript.com/releases/gsdnld.html
https://artifex.com/licensing

Man(n) könnte auch noch diverse mögliche Fehler abfedern (Fehlerprotokoll wenn Datei nicht klappt, letzte leere Zeile im Array abfangen, usw....). ;-)
Ich habe es an "einem Sack voll" PDF-Dateien getestet. ;-)
Option Explicit

Private Declare PtrSafe Function OemToCharA Lib "user32.dll" (ByVal lpszSrc As String, ByVal lpszDst As String) As Long
Public Function fncFromDuskTillDawn(ByVal strTMP As String) As String
Call OemToCharA(strTMP, strTMP)
fncFromDuskTillDawn = strTMP
End Function
Public Sub Main()
' Die drei Const ANPASSEN!!!!!!
Const GS_PATH As String = "C:\Program Files\gs\gs10.06.0\bin\gswin64c.exe"
Const SRC_FOLDER As String = "C:\Temp\Input\"
Const DST_FOLDER As String = "C:\Temp\Output\"
Dim varArr As Variant
Dim strTMP As String
Dim strCMD As String
Dim lngFile As Long
strTMP = fncFromDuskTillDawn(CreateObject("WScript.Shell").Exec("cmd /c dir " & SRC_FOLDER & "*.pdf /S/B").StdOut.ReadAll)
varArr = Split(strTMP, vbCrLf)
For lngFile = LBound(varArr) To UBound(varArr)
strCMD = """" & GS_PATH & """ " & "-dSAFER -dBATCH -dNOPAUSE -sDEVICE=pdfwrite " & _
"-dPDFSETTINGS=/prepress " & "-sOutputFile=""" & DST_FOLDER & Mid(varArr(lngFile), _
InStrRev(varArr(lngFile), "\") + 1) & """ " & """" & varArr(lngFile) & """"
CreateObject("WScript.Shell").Run strCMD, 0, True
Next lngFile
End Sub

Servus
Case
Anzeige
AW: Folgend ein...
26.12.2025 14:12:54
JoWE
Hallo Case,
schöne Lösung, schnell und zuverlässig!!
Wo im Code müsste zur Abgrenzung zw. Original und Kopie z.B. noch ein "GSNeu-" vor den eigentlichen Dateinamen im Output-Ordner eingebaut werden?
Grüße und Fröhliche Weihnachten
Jochen
AW: Folgend ein...
27.12.2025 09:14:56
Bernd_CH
Hallo Case
klingt sehr spannend, ich hoffe die "portablen Geister" krieg ich auch noch in den Griff, dies ist alles völliges Neuland für mich und ich "darf" nicht alles machen.
Ich muss mir erst noch eine Lösung hierfür einfallen lassen, aber ich habe aktuell kein anderes Speichermedium zur Hand.
Vielen Dank dennoch schon mal für diese Lösung.
Ich melde mich, wenn ich sie zum Fliegen gebracht habe :-).
VG
Bernd
Anzeige
Um es...
27.12.2025 11:32:35
Case
Moin Bernd, :-)

portabel zu machen (also ohne Installation), musst du folgendes tun: ;-)

In meinem Beispiel habe ich es in "C:\Temp\GhostscriptPortable\" probiert (also getestet - und es klappt). ;-)

Die Exe-Datei (die aus dem Download) mit 7-Zip (oder einem anderen geeigneten Programm) öffnen. ;-)
Nur die beiden Ordner bin und lib nach C:\Temp\GhostscriptPortable\ (oder einem Ordner deiner Wahl) entpacken. ;-)
Dann kannst du es in VBA so verwenden: ;-)
Const GS_PATH As String = "C:\Temp\GhostscriptPortable\bin\gswin64c.exe"

Du brauchst wahrscheinlich nicht alle Dateien aus bin und lib - aber sie stören auch nicht. Wichtig ist nur die Verzeichnisstruktur ;-)

Es kann dann auch von einem USB-Datenträger genutzt werden. ;-)

Servus
Case
Anzeige
AW: Um es...
05.01.2026 13:27:33
Bernd_CH
Hallo Case

Ich wünsche Dich erstmals noch ein gesundes neues Jahr!

Vielen Dank nochmals für Deine Hilfe.

Ich habe jetzt nochmals länger daran probiert, aber es kommt mir immer eine Fehlermeldung. (Laufzeitfehler 2147023636 (800704ec): Die Methode "Run" für das Objekt "IWishShell3" ist fehlgeschlagen.
Es wird dann die Zeile "CreateObject("WScript.Shell").Run strCMD, 0, True" angezeigt als Fehler.
Zuvor erscheint immer kurz ein schwarzes Fenster, das aber wieder verschwindet.

Das mit dem portable machen hat m.E. funktioniert, zumindest habe ich die beiden Ordner bin / lib und im bin Ordner ist auch die von Dir genannte exe-Datei drin.

Hier meine erstellte Datei https://www.herber.de/bbs/user/179951.xlsm

Der ganze Code ist für mich nicht nachvollziehbar, da verstehe ich leider zu wenig, daher tue ich mich bei der Fehlersuche so schwer.

Vielleicht könntest Du ja nochmals einen kurzen Blick darauf werfen, was ich falsch mache.

Vielen Dank im Voraus.
VG
Bernd


Anzeige
Ist das ein...
05.01.2026 17:38:03
Case
Moin Bernd, :-)

... Firmen-PC? Der Fehlercode ist ein Windows-Fehler, der darauf hinweist, dass ein Programm durch eine Gruppenrichtlinie blockiert wird. Dann hast du schlechte Karten - das geht dann nur über die IT-Abteilung. ;-)

Servus
Case
Dann muss man aber...
26.12.2025 14:58:00
Case
Moin Jochen, :-)

... auch die leere Zeile im Array berücksichtigen (einer von mehreren Wegen): ;-)

Option Explicit

Private Declare PtrSafe Function OemToCharA Lib "user32.dll" (ByVal lpszSrc As String, ByVal lpszDst As String) As Long
Public Function fncFromDuskTillDawn(ByVal strTMP As String) As String
Call OemToCharA(strTMP, strTMP)
fncFromDuskTillDawn = strTMP
End Function
Public Sub Main()
' Die drei Const ANPASSEN!!!!!!
Const GS_PATH As String = "C:\Program Files\gs\gs10.06.0\bin\gswin64c.exe"
Const SRC_FOLDER As String = "C:\Temp\Input\"
Const DST_FOLDER As String = "C:\Temp\Output\"
Dim varArr As Variant
Dim strTMP As String
Dim strCMD As String
Dim lngFile As Long
strTMP = fncFromDuskTillDawn(CreateObject("WScript.Shell").Exec("cmd /c dir " & SRC_FOLDER & "*.pdf /S/B").StdOut.ReadAll)
varArr = Split(strTMP, vbCrLf)
For lngFile = LBound(varArr) To UBound(varArr)
If Trim(varArr(lngFile)) > "" Then
strCMD = """" & GS_PATH & """ " & "-dSAFER -dBATCH -dNOPAUSE -sDEVICE=pdfwrite " & _
"-dPDFSETTINGS=/prepress " & "-sOutputFile=""" & DST_FOLDER & "Archiv_" & Mid(varArr(lngFile), _
InStrRev(varArr(lngFile), "\") + 1) & """ " & """" & varArr(lngFile) & """"
CreateObject("WScript.Shell").Run strCMD, 0, True
End If
Next lngFile
End Sub

Habe es bei mir "Archiv_" genannt. ;-)

Servus
Case
Anzeige
AW: Dann muss man aber...
26.12.2025 15:22:18
JoWE
Daumen hoch!
Klappt super, danke dafür
Gruß
Jochen
AW: Dann muss man aber...
26.12.2025 22:20:01
JoWE
Hi Case,
die letzte leere Zelle schliesse ich jetzt in diesem speziellen Fall über 'Ubound -1' oder über 'Len(strCMD) > nnn' aus, aber ist das auch eindeutig?
Oder gibt's da eine richtigere
Lösung?
LG
Jochen
Mit dem...
27.12.2025 06:25:53
Case
Moin Jochen, :-)

... -1 veränderst du die Ausgabe des Array. Bei einem leeren Ordner ist Ubound 0 und -1 ergibt dann einen Fehler. ;-)
Dir gibt immer ein abschließendes CRLF aus, also ein Chr(13) = Carriage Return und ein Chr(10) = Line Feed. ;-)

Man könnte also auch das CRLF am Ende des Strings - vor dem Spilt - entfernen. ;-)

Ich prüfe gerne mit Len oder > "", ob da was ist. Es ist IMHO weniger Fehleranfällig. ;-)

Servus
Case
Anzeige
AW: PDF-Dateien in Ordner über Microsoft Print to PDF speichern
24.12.2025 13:36:58
JoWE
Hallo,
warum so ? Dafür braucht's kein VBA!
1. Microsoft Print to PDF zum Standarddrucker machen
2. Im Explorer alle zu druckenden pdf-Files markieren
3. rechte Maustaste auf die markierten Files und
4. im Kontextmenü "rechte Maustaste" 'weitere Optionen anzeigen'
5. und dann Drucken anklicken
das war's schon !!!
zum guten Schluss noch
den Standarddrucker wieder zurückstellen.
Gruß
Jochen
Anzeige
AW: PDF-Dateien in Ordner über Microsoft Print to PDF speichern
25.12.2025 08:32:10
Bernd_CH
Hallo Ulf
vielen Dank für Deine Hilfe. Ich habe diesen Code mal in mein Excel reinkopiert und auch habe ich den Pfad, wo die PDFs liegen anpassen können. ('Your PDF files are located
FolderPath = "H:\PDF_TEST\"). Das klappt schon mal.
Jetzt kommt bei jedem geöffneten File die Frage nach dem Dateinamen und den Speicherort. Könnte dies auch automatisiert werden?
D.h. ich könnte im Makro einen vorgegebenen Pfad angeben, wo alle PDFs gespeichert werden sollen. Ähnlich so, wie ich oben den Pfad angebe, wo die Quelldaten sind? (z.B. "H:\PDF_TEST\NEU\")
Der Dateiname sollte immer der Name der geöffneten Datei mit dem Vorsatz "NEUPDF_" sein, d.h. das PDF "Rechnungabc" würde neu "NEUPDF_Rechnungabc" heissen.
Wenn dies nicht geht, oder zu aufwändig wäre, könnten die neuen PDFs auch einfach "PDF-1", "PDF-2", "PDF-3", usw. (die Zahl wäre die Variable) heissen.
Nochmals vielen Dank für Deine Hilfe.
VG
Bernd

Anzeige
AW: PDF-Dateien in Ordner über Microsoft Print to PDF speichern
25.12.2025 13:01:52
volti
Hallo Bernd,

grundsätzlich ist es oft möglich, einer Textbox in einem externen Dialog ("Druckausgabe speichern unter") einen Text vorzugeben und anschließend einen Button, z.B. Speichern anzuklicken.
Hierzu benötigt man spezielle API-Funktionen. Wegen des komplizierten zeitlichen Ablaufs ist das aber etwas heikel.
Es erscheint z.B. ein weiterer Dialog, wenn es die Datei schon gibt, usw..

Hier mal eine Idee, aufgesetzt auf Deinen bisherigen code. Probiere es einfach mal aus, vielleicht klappt es ja. Ist aber nur wenig getestet.
Bei mir wird übrigens die Adobe.Exe nicht wieder geschlossen (taskkill)

Private Declare PtrSafe Function ShellExecuteA Lib "shell32.dll" ( _

ByVal hWnd As LongPtr, ByVal lpOperation As String, ByVal lpFile As String, _
ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As LongPtr
Private Declare PtrSafe Function SetTimer Lib "user32" ( _
ByVal hWnd As LongPtr, ByVal nIDEvent As LongPtr, _
ByVal uElapse As Long, ByVal lpTimerFunc As LongPtr) As LongPtr
Private Declare PtrSafe Function KillTimer Lib "user32" ( _
ByVal hWnd As LongPtr, ByVal nIDEvent As LongPtr) As Long
Private Declare PtrSafe Function FindWindowA Lib "user32" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As LongPtr
Private Declare PtrSafe Function SendDlgItemMessageA Lib "user32" ( _
ByVal hDlg As LongPtr, ByVal nIDDlgItem As Long, _
ByVal wMsg As Long, ByVal wParam As LongPtr, _
ByVal lParam As LongPtr) As LongPtr
Private Declare PtrSafe Function EnumChildWindows Lib "user32" ( _
ByVal hWndParent As LongPtr, ByVal lpEnumFunc As LongPtr, _
ByVal lParam As LongPtr) As Long
Private Declare PtrSafe Function SendMessageA Lib "user32" ( _
ByVal hWnd As LongPtr, ByVal wMsg As Long, _
ByVal wParam As LongPtr, lParam As Any) As LongPtr
Private Declare PtrSafe Function GetDlgCtrlID Lib "user32" ( _
ByVal hWnd As LongPtr) As Long
Private Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Const BM_CLICK As Long = &HF5
Private Const WM_SETTEXT As Long = &HC
Dim mhTimer As LongPtr, mi As Long
Dim msDateiPfadNeu As String

Sub PrintPDFFiles()
Dim FolderPath As String, FileName As String, PDFPath As String, Speicherpfad As String

'Your PDF files are located
FolderPath = ThisWorkbook.Path & "\"
' Loop All files in the folder
FileName = Dir(FolderPath & "*" & ".pdf")
Do While FileName > ""
PDFPath = FolderPath & FileName

' Speichern-Dialog füllen
mi = 0
Speicherpfad = "D:\Test\" ' ggf. anpassen >>>
msDateiPfadNeu = Speicherpfad & "NEUPDF_" & FileName

If Dir(msDateiPfadNeu) > "" Then Kill msDateiPfadNeu ' vorhandene Datei löschen
mhTimer = SetTimer(0&, 0&, 100, AddressOf PrintPDF_CallbackProc)
If ShellExecuteA(Application.hWnd, "Print", PDFPath, vbNullString, vbNullString, 3) = 32 Then
KillTimer 0&, mhTimer: mhTimer = 0
MsgBox "Failed to print " & PDFPath
Else
' Adjust the duration as needed
Application.Wait Now + TimeValue("00:00:05")
Call Shell("taskkill /f /im AcroRd32.exe", vbHide)
End If
FileName = Dir
Loop
End Sub


Sub PrintPDF_CallbackProc()
Dim hDlg As LongPtr, sTxt As String * 10

mi = mi + 1
hDlg = FindWindowA(vbNullString, "Druckausgabe speichern unter")
If mi > 50 Or hDlg > 0 Then KillTimer 0&, mhTimer: mhTimer = 0 ' Timer löschen, wenn Dlg gefunden
If hDlg > 0 Then
Sleep 500
EnumChildWindows hDlg, AddressOf EnumControls, 0
DoEvents
SendDlgItemMessageA hDlg, 1, BM_CLICK, ByVal 0, ByVal 0 ' Speicher-Button ID=1 klicken
End If
End Sub

Private Function EnumControls(ByVal hChild As LongPtr, ByVal lParam As LongPtr) As Long
' Function ermittelt anhand der ID die richtige Textbox (Edit) und setzt den Text ein
EnumControls = True
If GetDlgCtrlID(hChild) = 1001 Then ' 1001=ID der Editbox
SendMessageA hChild, WM_SETTEXT, 0, ByVal msDateiPfadNeu ' Text einsetzen
EnumControls = False
End If
End Function


Gruß
Karl-Heinz
Anzeige
AW: PDF-Dateien in Ordner über Microsoft Print to PDF speichern
25.12.2025 16:19:11
Bernd_CH
Hallo Karl Heinz

Danke für Deine Unterstützung. Leider ist mir nicht genau klar, wie genau Dein Code integriert werden muss? Ich habe Deinen ganzen Code mit dem bestehenden ersetzt. Doch dann wird immer nur das erste PDF genommen und kopiert, aber den speichern Button muss ich dennoch noch klicken.
Ich habe nun die folgende Datei zusammengebastelt.
https://www.herber.de/bbs/user/179912.xlsm

Vielleicht kann jemand einem absoluten Anfänger hier nochmals helfen?

VG
Bernd
Anzeige
AW: PDF-Dateien in Ordner über Microsoft Print to PDF speichern
25.12.2025 19:53:11
volti
Hallo Bernd,

hier noch ein Versuch in der anliegenden Datei, die Dateispeicherung zu automatisieren.

Funktioniert teilweise. Wegen unterschiedlicher Ladezeiten der PDF-Dateien kommt es ab und zu bei mir zum Stopp. Das in den Griff zu kriegen wäre dann sehr aufwändig.

Probiere es noch mal aus. Wenn es nicht funktionieren sollte, ist dieser Weg nicht brauchbar.

https://www.herber.de/bbs/user/179914.xlsm

Gruß
Karl-Heinz
Anzeige
AW: besser doch Ulfs Lösung!!
24.12.2025 15:02:38
JoWE
AW: besser doch Ulfs Lösung!!
25.12.2025 08:35:13
Bernd_CH
Hallo Jochen
vielen Dank für Deinen Hinweis, den ich absolut nachvollziehen kann. Ich habe dummerweise nicht die ganze Anforderung geschrieben, denn ich würde gerne die Eingabe von Pfad und Dateinamen auch automatisieren. Und dies geht m.E. nur über VBA.
VG
Bernd

Forumthreads zu verwandten Themen

Anzeige
Anzeige