批次轉換doc到pdf

🙌前言

  1. 交通部的部頒規範下載下來之後會變成很多細碎的檔案,包含PDF跟DOC,在進行檔案內容搜尋的時候時常需要跨檔案比對,無法在同個檔案中一次到位。

  2. 有些規範有進行修改的內容需要先修改doc後再輸出PDF,乾脆將所有PDF都先進行刪除,後續再針對資料夾批次轉檔成PDF後再做合併。

解決目標:將doc修改完畢後輸出為pdf,丟到pdf_merge中進行合併,這實在是很麻煩。

本篇介紹如何撰寫程式碼來簡化製作公路橋梁設計規範的流程,有興趣請繼續閱讀


檔案來源

  • 原始檔案下載連結 Fig1.規範下載處

  • 原始檔案下載內容 Fig2.規範下載內容-PDF與DOC

  • 預先處理內容 Fig3.預先刪除所有PDF


👉Python的解決方案

預計使用工具為docx2pdf進行轉檔

docx2pdf

使用時所輸出的內容一直出現空白頁,而且可以接受的內容也只有docx 可能是我還沒研究透徹...?

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

from docx2pdf import convert
import os

def convert_docx_to_pdf(input_folder, output_folder):
# 確保輸入文件夾存在
if not os.path.exists(input_folder):
print("輸入文件夾不存在!")
return

# 確保輸出文件夾存在
os.makedirs(output_folder, exist_ok=True)

# 遍歷輸入文件夾中的所有文件
for filename in os.listdir(input_folder):
if filename.endswith(".docx") :#or filename.endswith(".doc"):
print(f"{filename} found")

input_path = os.path.join(input_folder, filename)
output_filename = filename.replace(".docx", ".pdf")
output_path = os.path.join(output_folder, output_filename)
# 將 Word 文件轉換為 PDF

convert(input_path, output_path)
print(f"{filename} 轉換完成")

if __name__ == "__main__":
input_folder = r"D:\GoogleDrive-參考手冊\公路橋梁設計規範" # 輸入文件夾的路徑
output_folder = r"D:\Python\pdf_output" # 輸出文件夾的路徑
convert_docx_to_pdf(input_folder, output_folder)

後來還是想別的辦法去轉檔。


👍最終選擇

身為忠臣的VBA用戶,如果能夠用VBA處理會是比較得心應手的,突然想起 Excel VBA 本身可以呼叫 Word VBA 執行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

'以下內容來自與ChatGPT之間的對話+我自己稍微修改

Sub ConvertDocToPDF()
Dim WordApp As Object
Dim WordDoc As Object
Dim FolderPath As String
Dim FileName As String
Dim PDFFileName As String

' ?置 Word ?用?象
On Error Resume Next
Set WordApp = GetObject(, "Word.Application")
If WordApp Is Nothing Then
Set WordApp = CreateObject("Word.Application")
End If
On Error GoTo 0

' ?置 Word ?用?不可?
WordApp.Visible = False

' ?置文件?路?
FolderPath = "D:\GoogleDrive-參考手冊\公路橋梁設計規範" ' 更改?你的文件?路?

' 遍?文件?中的所有 Word 文件
FileName = Dir(FolderPath & "\*.doc*")
Do While FileName <> ""
' 打? Word 文?
Set WordDoc = WordApp.Documents.Open(FolderPath & "\" & FileName)

' 构建 PDF 文件名
PDFFileName = Replace(FolderPath & "\" & FileName, ".doc", ".pdf")

' 保存? PDF
WordDoc.ExportAsFixedFormat OutputFileName:=PDFFileName, ExportFormat:=17 ' 17 表示 PDF 格式

' ?? Word 文?
WordDoc.Close False

' ??下一?文件
FileName = Dir
Loop

' ?? Word ?用
WordApp.Quit

' ?放?象
Set WordDoc = Nothing
Set WordApp = Nothing

MsgBox "列印完成!"

End Sub


暫時結果

經過轉檔之後,原本是doc或docx的檔案都會依照原本名稱變成pdf的副檔名

下一步就是要進行pdf合併了!!

Fig4.暫時生成結果

列印順序

因為PDF文件的名稱不一定是我所需要的順序

希望能夠依循下列步驟

  1. 列出該檔案夾中的檔案名稱順序成為CSV檔案
  2. 根據我所指定的順序進行選取合併

生成CSV順序

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
import os
import csv

def list_pdf_files_to_csv(input_folder, output_csv):
# 打开 CSV 文件以写入模式
with open(output_csv, "w", newline='', encoding='utf-8-sig') as csv_file:
# 创建 CSV writer 对象
csv_writer = csv.writer(csv_file)
csv_writer.writerow(['順序','檔案名稱','檔案路徑'])
order=1
# 遍历输入文件夹中的所有文件
for filename in os.listdir(input_folder):
# 检查文件名是否以 ".pdf" 结尾
if filename.lower().endswith(".pdf"):
# 将文件信息写入 CSV 文件
file_path = os.path.join(input_folder, filename)
csv_writer.writerow([order,filename, file_path])
# 更新顺序号
order += 1

if __name__ == "__main__":
input_folder =r"D:\GoogleDrive-參考手冊\公路橋梁設計規範" # 输入文件夹的路径
output_csv = r"D:\Python\pdf_doc\pdf_files.csv" # 输出 CSV 文件的路径
list_pdf_files_to_csv(input_folder, output_csv)

生成之後可以藉由Excel的幫助進行順序排序,再另存為csv檔案的格式就可以備用。

根據CSV順序進行合併

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
import os
import csv
from PyPDF2 import PdfMerger

def read_csv_to_pdf_files(csv_file):
pdf_files = []

# 打开 CSV 文件并读取内容
#with open(csv_file, "r", newline='',errors='replace') as file:#有出現問題的話用這行
with open(csv_file, "r", newline='',encoding='utf-8-sig') as file:#全新虛擬環境用這行
reader = csv.reader(file)
next(reader) # 跳过标题行
for row in reader:
order = row[0]#第一列是顺序
filename = row[1] # 第二列是文件名
pdf_path = row[2] # 第三列是 PDF 文件的绝对路径
pdf_files.append((order, filename, pdf_path))

return pdf_files

def merge_pdfs_directly(pdf_files,output_folder):
# 创建一个 PdfMerger 对象
merger = PdfMerger()

# 遍历列表中的每个元素 這個不能亂改會報錯
for order, filename,pdf_path in pdf_files:
# 将 PDF 文件添加到合并器中
merger.append(pdf_path)

# 确保输出文件夹存在
os.makedirs(output_folder, exist_ok=True)

# 将合并后的 PDF 保存到文件
output_path = os.path.join(output_folder, "merged_pdf.pdf")
merger.write(output_path)

# 关闭合并器
merger.close()

if __name__ == "__main__":

csv_file = r"D:\Python\pdf_doc\pdf_files.csv" # CSV 文件的路径
pdf_files = read_csv_to_pdf_files(csv_file)
output_folder = r"D:\Python\pdf_doc" # 输出文件夹的路径
merge_pdfs_directly(pdf_files,output_folder)


最終成果

藉由vba的轉檔及python的合併處理成的檔案,總共有432頁的PDF 🔗 🔗完整版-公路橋梁設計規範成果下載


👻開發過程的問題

操作CSV的過程曾經出現一些奇怪的問題,記錄一下比較不會忘記

檔案名稱為中文,要收集匯入csv檔案的時會變成亂碼

需要將編碼由utf-8改為utf-8-sig

1
with open(output_csv, "w", newline='', encoding='utf-8-sig') as csv_file: 

CSDN參考

要將CSV的內容匯入到python進行後續運用時會出現'UnicodeDecodeError'

將原本的讀取內容中的encoding換成 errors='replace' 即可

1
2
3
4
with open('some.csv', newline='', encoding='utf-8') as f:
reader = csv.reader(f)
for row in reader:
print(row)
1
2
3
4
with open('some.csv', newline='', errors='replace') as f:
reader = csv.reader(f)
for row in reader:
print(row)

Stack overflow參考資料

開啟一個全新的環境,要將CSV的內容匯入到python進行後續運用時會出現

1
FileNotFoundError: [Errno 2] No such file or directory: 'D:\\GoogleDrive-������������\\��祈楝璈�璇�閮剛��閬� 蝭�\\蝚砌��蝡� 蝮賢��1090103.pdf

原本第二點可以解決編譯問題的程式碼調整 errors='replace' 已經無法作用,我把encoding='utf-8-sig'重新加上去,然後就好了(?)

猜測是新的環境中還沒有預設的encoding,所以中文還沒有辦法被知道要怎麼編譯。

1
2
3
4
with open('some.csv', newline='', encoding='utf-8-sig') as f:
reader = csv.reader(f)
for row in reader:
print(row)