Excel / 使用VBA執行windows命令列程式-PDFtoPrinter列印PDF檔案

偶爾會逛逛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