偶爾會逛逛PTT的Visual_Basic 版
最近看到一篇"[VBA] 如何用VBA開啟PDF並列印?"
結果沒有人回應
我用其中的關鍵字"用VBA開啟PDF並列印"搜尋
在搜尋的第2頁,有一篇reddit的文章"Printing external PDF-files using VBA"
備註:應該是AI所賜,這個網站會自動翻譯成中文,所以用中文都能夠搜尋到關鍵字內容
其中有人回應跟我的想法很類似,這應該要用windows命令列程式
才能夠在Excel用VBA Shell或者 WScript.Shell執行相關程序
貼文提供了一個能透過命令列執行的程式-PDFtoPrinter
我把這個網站的內容貼到gemini
請AI幫忙整理操作方式
因為這個程式是包裝PDF-XChange Viewer,而PDF-XChange Viewer可以設定自訂列印選項
在說明內容也提到相關的設定可以參考PDF-XChange Viewer手冊
所以我再把手冊貼給 gemini
請AI幫我找出來設定的方式
接著,再問 gemini如果想要動態設定自訂檔應該如何處理
AI真的很厲害,能夠提出變通的方式來處理
也提供了power shell的程式碼
所以我再請AI改成VBA程式碼,並且用 WScript.Shell來執行命令串
最後我參考了AI的程式碼,用我習慣的方式來串這些流程
首先,以工作表作為資料庫
介面如下
設定了2個按鈕,分別執行選取PDF、列印等功能
因為我不想在測試的時候印出一堆東西
所以印表機設定成"Microsoft Print to PDF"
以下分別呈現程式碼
1.選取PDF的程式碼
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
' 選取PDF檔案 Sub selePDF4() r = Sheets(1).Range("B1").End(xlDown).Row If r = 1048576 Then r = 2 Else r = r + 1 End If Dim fd As FileDialog Set fd = Application.FileDialog(msoFileDialogFilePicker) Dim filePath As Variant With fd .AllowMultiSelect = False .Filters.Clear .Filters.Add "pdf", "*.pdf" .Title = "選取pdf檔" End With If fd.Show = -1 Then filePath = fd.SelectedItems(1) Debug.Print filePath Sheets(1).Range("B" & r).Value = filePath End If Set fd = Nothing End Sub |
2.列印功能
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
' 列印 Sub printByComandLine4() r = Sheets(1).Range("B1").End(xlDown).Row If r = 1048576 Then Exit Sub End If For i = 2 To r If Range("A" & i) <> "◎" Then Dim wsh As Object Set wsh = VBA.CreateObject("WScript.Shell") Dim waitOnReturn As Boolean: waitOnReturn = True Dim windowStyle As Integer: windowStyle = 0 ' 如果用環境參數在WScript.Shell會無法執行 ' PDFtoPrinter.exe Dim PrinterExe As String PrinterExe = Chr(34) & ThisWorkbook.Path & "\pdftoprinter-main\PDFtoPrinter.exe" & Chr(34) ' 列印的PDF檔案 Dim PrintFile As String ' PrintFile = ThisWorkbook.Path & "\PDFVManual.pdf" PrintFile = Range("B" & i).Value ' 印表機名稱 Dim PrinterName As String ' PrinterName = "Microsoft Print to PDF" PrinterName = Range("D" & i).Value If PrinterName = "" Then PrinterName = "Microsoft Print to PDF" End If ' 複製設定檔 Dim SETTINGS_DIR As String Dim SourceSettingFile As String Dim DestinationSettingFile As String Dim SettingFile As String SETTINGS_DIR = ThisWorkbook.Path & "\pdftoprinter-main\setting\" Dim cc As String c = Range("C" & i).Value Select Case c Case "單面" SettingFile = "Settings_1.dat" Case "四合一" SettingFile = "Settings_4up.dat" Case Else: SettingFile = "Settings_ori.dat" End Select SourceSettingFile = Chr(34) & SETTINGS_DIR & SettingFile & Chr(34) DestinationSettingFile = Chr(34) & ThisWorkbook.Path & "\pdftoprinter-main\PDF-XChange Viewer Settings.dat" & Chr(34) Dim CmdString As String CmdString = "cmd.exe /c copy /Y " & SourceSettingFile & " " & DestinationSettingFile Debug.Print CmdString Dim ExitCode As Long ExitCode = wsh.Run(CmdString, windowStyle, waitOnReturn) If ExitCode <> 0 Then MsgBox "錯誤: 複製設定檔失敗,退出碼: " & ExitCode, vbCritical Set wsh = Nothing Exit Sub End If ' 等待3秒鐘 Application.Wait (Now + TimeValue("0:00:03")) ' 列印範圍 Dim ce As String ce = Range("E" & i).Value Dim pageString As String ' 列印命令串 Dim s As String Select Case ce Case Is <> "" pageString = "pages=" & ce s = PrinterExe & " " & Chr(34) & PrintFile & Chr(34) & Chr(32) & Chr(34) & PrinterName & Chr(34) & Chr(32) & pageString Debug.Print s Case Else: s = PrinterExe & " " & Chr(34) & PrintFile & Chr(34) & Chr(32) & Chr(34) & PrinterName & Chr(34) Debug.Print s End Select ' WScript.Shell Dim errorCode As Long errorCode = wsh.Run(s, windowStyle, waitOnReturn) If errorCode = 0 Then ' MsgBox "Done! No error to report." Debug.Print "列印完成" Else MsgBox "Program exited with error code " & errorCode End If ' 寫回預設的設定檔 Dim OriSettingFile As String OriSettingFile = Chr(34) & SETTINGS_DIR & "Settings_ori.dat" & Chr(34) Dim CmdString2 As String CmdString2 = "cmd.exe /c copy /Y " & OriSettingFile & Chr(32) & DestinationSettingFile Debug.Print CmdString2 Dim ExitCode2 As Long ExitCode2 = wsh.Run(CmdString2, windowStyle, waitOnReturn) If ExitCode2 <> 0 Then MsgBox "錯誤: 複製設定檔失敗,退出碼: " & ExitCode2, vbCritical Set wsh = Nothing Exit Sub End If ' 等待1秒鐘 Application.Wait (Now + TimeValue("0:00:01")) Set wsh = Nothing Range("A" & i).Value = "◎" End If Next End Sub |
主要流程就是依據需求串接命令
命令列的架構如下
PDFtoPrinter.exe "列印的檔案" "印表機名稱"
如果要指定範圍就加上 pages參數
範例: 2-4,7,12 ,列印第2到4頁、第7頁、第12頁;空白預設為全部
這個程式碼最大的關隘就是找到能夠在命令列執行的PDF程式
接著就是處理動態設定列印選項的方法
之後就簡單多了,都是VBA的語法問題而已
把相關的參數串接起來讓WScript.Shell執行PDFtoPrinter.exe