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
流程大致如下
透過迴圈,使用工作簿功能ExportAsFixedForma逐一將工作表轉成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資料夾的PDF 如果存在 回傳檔案名稱.副檔名
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
|
參考資料
如何用pyinstaller将需要传参数的Python文件生成exe文件
Python:批次加密PDF文件
别再问我怎么Python打包成exe了!