Excel / 使用VBA執行Ghostscript的windows命令列程式-壓縮、拆分PDF檔案 2

接續說明壓縮PDF檔案的程式碼

會分成兩個部分

第1個是主程序,設定相關的參數

這是因為壓縮PDF的參數比較多

但我這邊是用預設的參數設定PDFSetting:/ebook 、/screen

如果沒有指定就預設為/ebook

第2個部分則是Ghostscript PDF 壓縮的function

接收主程序傳來的參數

當然這兩個部分的程式碼可以合併

不過這樣就顯得冗長,不符合現在程式設計的原則-模組化

操作介面如下

 

第1部分的程式碼

 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
Sub RunPDFCompression_WS2()

    Dim InputPDF As String
    Dim OutputPDF_Default As String
    Dim OutputPDF_Targeted As String
    
    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
    
            'PDF 檔案路徑
            InputPDF = Range("B" & i).Value
            
            InputPDFSetting = Range("C" & i).Value
            
            If Dir(InputPDF) = "" Then
                MsgBox "輸入檔案不存在: " & InputPDF, vbCritical
                Exit Sub
            End If
            
            ' ----------------------------------------------------------------------------------
            ' select case
            ' ----------------------------------------------------------------------------------
            
            Select Case InputPDFSetting
            
            Case Is = "/ebook"
                OutputPDF_Default = Replace(InputPDF, ".pdf", "_Ebook.pdf")
                
                If CompressPDF_GS_WScript2(InputPDF, OutputPDF_Default, "/ebook") Then
                    Debug.Print "Ebook 壓縮完成: " & OutputPDF_Default
                    Range("E" & i).Value = OutputPDF_Default
                    Range("A" & i).Value = "◎"
                    Range("D" & i).Value = "壓縮完成"
                    MsgBox "Ebook 壓縮完成: " & OutputPDF_Default, vbInformation
                Else
                    Debug.Print "Ebook 壓縮失敗。"
                    Range("D" & i).Value = "壓縮失敗"
                End If
            Case Is = "/screen"
                OutputPDF_Default = Replace(InputPDF, ".pdf", "_Screen.pdf")
                If CompressPDF_GS_WScript2(InputPDF, OutputPDF_Default, "/screen", 50, 72) Then
                    Debug.Print "Ebook 壓縮完成: " & OutputPDF_Default
                    Range("G" & i).Value = OutputPDF_Default
                    Range("A" & i).Value = "◎"
                    Range("D" & i).Value = "壓縮完成"
                    MsgBox "Screen 壓縮完成: " & OutputPDF_Default, vbInformation
                Else
                    Debug.Print "Screen 壓縮失敗。"
                    Range("D" & i).Value = "壓縮失敗"
                End If
            Case Else
                OutputPDF_Default = Replace(InputPDF, ".pdf", "_Default.pdf")
                
                If CompressPDF_GS_WScript2(InputPDF, OutputPDF_Default) Then
                    Debug.Print "Ebook 壓縮完成: " & OutputPDF_Default
                    Range("E" & i).Value = OutputPDF_Default
                    Range("A" & i).Value = "◎"
                    Range("D" & i).Value = "壓縮完成"
                    MsgBox "Default 壓縮完成: " & OutputPDF_Default, vbInformation
                Else
                    Debug.Print "Default 壓縮失敗。"
                    Range("D" & i).Value = "壓縮失敗"
                End If
            End Select
        End If
    Next
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
' Ghostscript PDF 壓縮函數 (VBA - 使用 WScript.Shell.Run)
' --------------------------------------------------------------------------------------------------------
' WScript.Shell 的 Run 方法 (WaitOnReturn:=True) 能確保程式碼等待 Ghostscript 完成後才繼續執行。
'========================================================================================================

Function CompressPDF_GS_WScript2( _
    ByVal InputFilePath As String, _
    ByVal OutputFilePath As String, _
    Optional ByVal PDFSetting As String = "/ebook", _
    Optional ByVal JPEGQuality As Long = 80, _
    Optional ByVal DPI As Long = 150 _
) As Boolean
    
    Dim CmdLine As String
    Dim WshShell As Object
    Dim ErrorCode As Long  ' WshShell.Run 的返回值 (通常 0 表示成功)
    Dim GHOSTSCRIPT_EXE As String
    
    ' ----------------------------------------------------------------------------------
    ' 1. 指定 Ghostscript 執行檔名稱或路徑
    '    * 如果 PATH 已設定 (推薦),使用 gswin64c。
    '    * 如果 PATH 未設定,請使用完整的路徑並加上雙引號,例如:
    '      GHOSTSCRIPT_EXE = "C:\Program Files\gs\gs10.06.0\bin\gswin64c.exe"
    ' ----------------------------------------------------------------------------------
    GHOSTSCRIPT_EXE = "gswin64c"
    
    ' ----------------------------------------------------------------------------------
    ' 2. 建構 Ghostscript 命令字串
    '    - 必須用雙引號 (Chr(34)) 將路徑包起來,以處理路徑中的空格。
    ' ----------------------------------------------------------------------------------
    
    ' WScript.Shell.Run 的命令字串不允許直接使用 gswin64c.exe,如果它不在 PATH 中,
    ' 因此我們需要將執行檔也包在雙引號中 (如果有空格的話)。
    If InStr(GHOSTSCRIPT_EXE, " ") > 0 Then
        GHOSTSCRIPT_EXE = Chr(34) & GHOSTSCRIPT_EXE & Chr(34)
    End If
    
    CmdLine = GHOSTSCRIPT_EXE & " " & _
              "-sDEVICE=pdfwrite " & _
              "-dCompatibilityLevel=1.4 " & _
              "-dNOPAUSE -dQUIET -dBATCH "
              
    If Not IsEmpty(PDFSetting) Then
        CmdLine = CmdLine & "-dPDFSETTINGS=" & PDFSetting & " "
    End If
    
    If DPI > 0 Then
        CmdLine = CmdLine & "-dDownsampleColorImages=true " & _
                            "-dDownsampleGrayImages=true " & _
                            "-dColorImageResolution=" & DPI & " " & _
                            "-dGrayImageResolution=" & DPI & " "
    End If
    
    If JPEGQuality >= 0 And JPEGQuality <= 100 Then
        CmdLine = CmdLine & "-dJPEGQ=" & JPEGQuality & " "
    End If
    
    ' 輸出與輸入檔案 (路徑務必使用 Chr(34) 包起來):
    CmdLine = CmdLine & "-sOutputFile=" & Chr(34) & OutputFilePath & Chr(34) & " " & _
              Chr(34) & InputFilePath & Chr(34)
              
    ' ----------------------------------------------------------------------------------
    ' 3. 執行命令並等待完成
    ' ----------------------------------------------------------------------------------
    
    On Error GoTo ErrorHandler
    
    Debug.Print "壓縮中"
    
    ' 創建 WScript.Shell 物件
    Set WshShell = CreateObject("WScript.Shell")
    
    ' 執行 Run 方法:
    ' 第二個參數 (0):隱藏命令視窗 (vbHide)
    ' 第三個參數 (True):等待外部程式執行完畢才返回
    ErrorCode = WshShell.Run(CmdLine, 0, True)

    ' 清理物件
    Set WshShell = Nothing
    
    ' ----------------------------------------------------------------------------------
    ' 4. 檢查執行結果
    '    - Ghostscript 通常成功會返回 0。
    ' ----------------------------------------------------------------------------------
    
    If ErrorCode = 0 Then
        ' 額外檢查輸出檔案是否存在 (增強檢查)
        If Len(Dir(OutputFilePath)) > 0 Then
            CompressPDF_GS_WScript2 = True
        Else
            MsgBox "Ghostscript 執行成功,但輸出檔案不存在。請檢查輸入檔案和權限。", vbExclamation
            CompressPDF_GS_WScript2 = False
        End If
    Else
        MsgBox "Ghostscript 執行失敗。錯誤代碼: " & ErrorCode & vbCrLf & "完整命令: " & CmdLine, vbCritical
        CompressPDF_GS_WScript2 = False
    End If
    
    Exit Function

ErrorHandler:
    ' 如果 CreateObject 失敗或其他 VBA 錯誤
    If Not WshShell Is Nothing Then Set WshShell = Nothing
    MsgBox "VBA 或 WScript.Shell 錯誤:" & Err.Description, vbCritical
    CompressPDF_GS_WScript2 = False
    
End Function