VBA能否將excel轉成加密的PDF?
這個是在Line的excel社團看到的提問
其中的管理員提供了一個網路教學
這個教學是使用 Adobe Acrobat 物件
但是前提是必須先安裝付費版的 Adobe Acrobat
我後來想起之前彰化一整天有分享某個客製程式
其中有PDF加密功能,這個功能是在VBA執行他自己寫的python程式
經過自己土炮測試之後
我的構想,整體流程可以分成三部分
第一部分是在Excel透過VBA將工作表另存成PDF
第二部分是透過python程式加密PDF
第三部分是在Excel VBA執行 python程式
1.在Excel透過VBA將工作表另存成PDF
這是透過Excel的內建功能將工作表複製到新的工作簿
然後再存成PDF
流程大致如下
透過迴圈,使用工作簿功能ExportAsFixedFormat逐一將工作表轉成PDF
1 2 3 4 5 6 |
For i = 2 To Sheets.Count nName = Sheets(i).Name Sheets(i).Copy ActiveWorkbook.ExportAsFixedFormat Type:=xlTypePDF, Filename:=outputFolderPath & nName & ".pdf" ActiveWorkbook.Close False Next |
2.透過python程式加密PDF
這裡的知識點是如何讓python接收外部參數
最簡單的方式 透過sys.argv來接收從cmd傳入的參數
1 2 3 4 5 6 7 8 9 |
import sys def getArg(ar1, ar2): print() print('接收參數:', ar1,ar2) print() getArg(sys.argv[1], sys.argv[2]) |
將以上的程式碼存成xx.py (xx是指隨意名稱)
然後在cmd執行 python xx.py 1 2
就會輸出
接收參數:1 2
另一個知識點是如何加密PDF
可以利用套件 PyPDF2來處理
流程如下
#6~43 自訂一個函數
#8 第一個參數為檔案路徑
#9 第二個參數為密碼
#12 取出不含副檔名的檔案名稱
os.path.basename(pdf_path) 可以取出檔案路徑中最後一層,也就是檔案名稱.副檔名
#15 設定暫存檔的完整路徑
#17 設定用來寫入的檔案路徑
os.path.dirname(pdf_path) 可以取出最後一層之外的路徑,也就是檔案所在的目錄
因為加密後的檔案無法寫回原檔案,所以寫入另一個pdf
#21-23 使用套件 shutil複製原檔案產生新檔案
#25-27 使用PyPDF2的PdfReader物件來讀取PDF
要先用open讀取檔案,再用PdfReader讀取PDF
#29-32 加密PDF
使用PyPDF2的PdfWriter物件的append_pages_from_reader獲取從PdfReader讀取的PDF
再用encrypt來加密
#34-36 將加密後的檔案寫入到用來輸出的檔案
因為產生一個空白的PDF還需要用別的套件生成
感覺太麻煩…
所以直接複製原本的檔案
#38-39 關閉利用open開啟的檔案
#41 刪除暫存檔
#42 關閉 PyPDF2的PdfReader、PdfReader物件
#43 如果之後封裝的程式要在背景執行,就不能有任何的print寫出
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 |
import os, sys import shutil from PyPDF2 import PdfReader from PyPDF2 import PdfWriter def addPw(ar1, ar2): #print(ar1,ar2) pdf_path =ar1 pswd=ar2 #不含副檔名的檔案名稱 fileName = os.path.basename(pdf_path).replace(".pdf", "") #print(fileName) #暫存檔 用來加密 tempFile =os.path.dirname(pdf_path)+"\\"+ fileName + "_temp.pdf" #print(tempFile) #最後輸出的檔案 因為檔案加密之後 不能寫回原本的檔案 newFile = os.path.dirname(pdf_path)+"\\"+ fileName +"_pw.pdf" #print(newFile) #複製產生檔案 shutil.copyfile(pdf_path, tempFile) shutil.copyfile(pdf_path, newFile) #讀取暫存檔案 in_file = open(tempFile, "r+b") in_pdf = PdfReader(in_file) #加密檔案 out_pdf = PdfWriter() out_pdf.append_pages_from_reader(in_pdf) out_pdf.encrypt(pswd) #讀取用來存儲的檔案 out_file = open(newFile, "wb") #寫出檔案 out_pdf.write(out_file) #關閉open()開啟的檔案 in_file.close() out_file.close() #刪除暫存檔 os.remove(tempFile) #刪除PdfReader() PdfWriter() del in_pdf, out_pdf print("檔案加密完成") addPw(sys.argv[1], sys.argv[2]) #addPw(r"C:\Users\edu\Desktop\PDF 轉檔 加密\output\臺北市.pdf","123456") |
之後再用pyinstaller封裝成執行檔
3.在Excel VBA執行 python程式
#6-37 將工作表轉存成PDF
#39-51 讀取輸出資料夾內的所有PDF,將完整的檔案路徑寫入陣列中
#55-66 利用陣列進行迴圈
#59 是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 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 |
Public Sub export_encrypt_PDF() Application.DisplayAlerts = False Application.ScreenUpdating = False Dim fso As Object Set fso = CreateObject("Scripting.FileSystemObject") ActiveWorkbook.Sheets(1).Activate '目前檔案路徑 nPath = ActiveWorkbook.Path '輸出資料夾名稱 strFolderName = "output" '完整的輸出資料夾路徑 outputFolderPath = nPath & Application.PathSeparator & strFolderName & Application.PathSeparator '判斷輸出資料夾是否存在 strFolderExists = Dir(nPath & Application.PathSeparator & strFolderName, vbDirectory) If strFolderExists = "" Then '不存在則新增 fso.CreateFolder nPath & Application.PathSeparator & strFolderName Else '存在則移除 再新增 fso.DeleteFolder nPath & Application.PathSeparator & strFolderName, True 'True 強制刪除 fso.CreateFolder nPath & Application.PathSeparator & strFolderName End If '將工作表轉存為PDF檔 For i = 2 To Sheets.Count nName = Sheets(i).Name Sheets(i).Copy ActiveWorkbook.ExportAsFixedFormat Type:=xlTypePDF, Filename:=outputFolderPath & nName & ".pdf" ActiveWorkbook.Close False Next '讀取output資料夾的 pdfFile = Dir(outputFolderPath & "*.pdf") Dim fileArr() As String i = 0 Do While pdfFile <> "" ReDim Preserve fileArr(i) fileArr(i) = outputFolderPath & pdfFile 'Debug.Print outputFolderPath & pdfFile i = i + 1 pdfFile = Dir() Loop 'Debug.Print fileArr(0) '陣列上限(序位值) num = UBound(fileArr) For i = 0 To num sourceFilename = fileArr(i) setPassword = "123456" '透過cmd 執行pdf加密程式 s = Chr(34) & Excel.ActiveWorkbook.Path & "\" & "0426_3.exe" & Chr(34) & Chr(32) & Chr(34) & sourceFilename & Chr(34) & Chr(32) & Chr(34) & setPassword & Chr(34) 'Debug.Print s Shell s Next Application.DisplayAlerts = True Application.ScreenUpdating = True End Sub |