從入門到實戰(zhàn)詳解Python如何將Excel工作表轉(zhuǎn)換為PDF
?一、為什么需要Excel轉(zhuǎn)PDF功能
在日常辦公中,Excel表格是數(shù)據(jù)記錄與分析的利器,但直接分享Excel文件可能存在以下問題:
- 接收方可能沒有安裝Excel軟件
- 不同版本Excel打開時格式錯亂
- 擔(dān)心數(shù)據(jù)被誤修改
- 需要打印時格式固定
PDF格式完美解決了這些問題:跨平臺兼容性強(qiáng)、格式固定、不可編輯(除非使用專業(yè)工具)。本文將介紹如何用Python實現(xiàn)自動化轉(zhuǎn)換,覆蓋從簡單表格到復(fù)雜報表的全場景。
二、技術(shù)選型與工具準(zhǔn)備
主流轉(zhuǎn)換方案對比
| 方案 | 優(yōu)點(diǎn) | 缺點(diǎn) | 適用場景 |
|---|---|---|---|
| win32com | 完美保留格式,支持所有Excel功能 | 僅限Windows,需安裝Excel | 企業(yè)級復(fù)雜報表 |
| openpyxl+reportlab | 純Python實現(xiàn),跨平臺 | 需手動處理樣式,復(fù)雜度較高 | 簡單表格轉(zhuǎn)換 |
| pandas+matplotlib | 數(shù)據(jù)可視化結(jié)合 | 樣式控制有限 | 數(shù)據(jù)報表生成 |
| xlwings | 支持宏和圖表操作 | 依賴Excel安裝 | 需要交互的場景 |
| comtypes | 類似win32com的替代方案 | 文檔較少,調(diào)試?yán)щy | Windows備用方案 |
推薦方案:
- Windows環(huán)境:
win32com(最高效) - 跨平臺需求:
pandas+matplotlib組合 - 簡單需求:
openpyxl直接導(dǎo)出
環(huán)境配置指南
安裝基礎(chǔ)庫:
pip install pandas openpyxl matplotlib win32com xlwings
Windows用戶需安裝:
- Microsoft Excel(win32com依賴)
- PyWin32:
pip install pywin32
三、基礎(chǔ)轉(zhuǎn)換方法實現(xiàn)
方法1:使用win32com(Windows最佳)
import win32com.client as win32
def excel_to_pdf_win32com(excel_path, pdf_path, sheet_name=None):
"""
使用win32com將Excel轉(zhuǎn)換為PDF
:param excel_path: Excel文件路徑
:param pdf_path: 輸出PDF路徑
:param sheet_name: 指定工作表名,None則轉(zhuǎn)換所有
"""
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = False # 不顯示Excel界面
try:
workbook = excel.Workbooks.Open(excel_path)
if sheet_name:
# 轉(zhuǎn)換單個工作表
sheets = workbook.Worksheets(sheet_name)
sheets.ExportAsFixedFormat(0, pdf_path) # 0=PDF格式
else:
# 轉(zhuǎn)換所有工作表
for sheet in workbook.Worksheets:
# 為每個工作表創(chuàng)建單獨(dú)PDF或合并(此處演示單獨(dú))
sheet_pdf_path = f"{pdf_path.rsplit('.', 1)[0]}_{sheet.Name}.pdf"
sheet.ExportAsFixedFormat(0, sheet_pdf_path)
except Exception as e:
print(f"轉(zhuǎn)換失敗: {e}")
finally:
workbook.Close(False)
excel.Quit()
# 使用示例
excel_to_pdf_win32com('data.xlsx', 'output.pdf', 'Sheet1')
方法2:純Python方案(跨平臺)
import pandas as pd
from matplotlib.backends.backend_pdf import PdfPages
import matplotlib.pyplot as plt
def excel_to_pdf_pandas(excel_path, pdf_path, sheet_name=0):
"""
使用pandas+matplotlib將Excel轉(zhuǎn)換為PDF
:param sheet_name: 工作表名或索引,默認(rèn)第一個
"""
df = pd.read_excel(excel_path, sheet_name=sheet_name)
with PdfPages(pdf_path) as pdf:
fig, ax = plt.subplots(figsize=(12, 6))
ax.axis('tight')
ax.axis('off')
# 創(chuàng)建表格
table = ax.table(
cellText=df.values,
colLabels=df.columns,
loc='center',
cellLoc='center'
)
# 調(diào)整樣式
table.auto_set_font_size(False)
table.set_fontsize(10)
table.scale(1.2, 1.2)
pdf.savefig(fig, bbox_inches='tight')
plt.close()
# 使用示例(適合簡單表格)
excel_to_pdf_pandas('data.xlsx', 'simple_output.pdf')
方法3:openpyxl直接處理(適合簡單需求)
from openpyxl import load_workbook
from reportlab.lib.pagesizes import letter
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle
def excel_to_pdf_openpyxl(excel_path, pdf_path, sheet_name=0):
"""
使用openpyxl+reportlab轉(zhuǎn)換
"""
wb = load_workbook(excel_path)
sheet = wb.worksheets[sheet_name]
# 提取數(shù)據(jù)
data = []
for row in sheet.iter_rows(values_only=True):
data.append(list(row))
# 創(chuàng)建PDF
doc = SimpleDocTemplate(pdf_path, pagesize=letter)
table = Table(data)
# 添加樣式
style = TableStyle([
('BACKGROUND', (0, 0), (-1, 0), '#4472C4'), # 表頭背景
('TEXTCOLOR', (0, 0), (-1, 0), 'white'), # 表頭文字
('ALIGN', (0, 0), (-1, -1), 'CENTER'), # 居中
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
('FONTSIZE', (0, 0), (-1, 0), 12),
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
])
table.setStyle(style)
doc.build([table])
# 使用示例
excel_to_pdf_openpyxl('data.xlsx', 'openpyxl_output.pdf')
四、進(jìn)階應(yīng)用場景
場景1:批量轉(zhuǎn)換多個Excel文件
import os
from pathlib import Path
def batch_convert(input_folder, output_folder):
"""
批量轉(zhuǎn)換文件夾內(nèi)所有Excel文件
"""
Path(output_folder).mkdir(parents=True, exist_ok=True)
for file in os.listdir(input_folder):
if file.endswith(('.xlsx', '.xls')):
excel_path = os.path.join(input_folder, file)
pdf_path = os.path.join(output_folder, f"{Path(file).stem}.pdf")
try:
excel_to_pdf_win32com(excel_path, pdf_path)
print(f"轉(zhuǎn)換成功: {file}")
except Exception as e:
print(f"{file} 轉(zhuǎn)換失敗: {e}")
# 使用示例
batch_convert('input_excels', 'output_pdfs')
場景2:保留復(fù)雜格式(圖表+條件格式)
def convert_with_charts(excel_path, pdf_path):
"""
保留圖表和條件格式的轉(zhuǎn)換(需win32com)
"""
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = False
try:
workbook = excel.Workbooks.Open(excel_path)
# 復(fù)制整個工作表到新工作簿(避免修改原文件)
new_workbook = excel.Workbooks.Add()
workbook.Worksheets(1).Copy(Before=new_workbook.Worksheets(1))
# 導(dǎo)出為PDF(自動包含所有圖表)
new_workbook.Worksheets(1).ExportAsFixedFormat(0, pdf_path)
finally:
new_workbook.Close(False)
workbook.Close(False)
excel.Quit()
# 使用示例
convert_with_charts('complex_report.xlsx', 'formatted_output.pdf')
場景3:動態(tài)調(diào)整PDF尺寸
def convert_with_auto_size(excel_path, pdf_path, scale_factor=1.0):
"""
根據(jù)內(nèi)容自動調(diào)整PDF尺寸
"""
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = False
try:
workbook = excel.Workbooks.Open(excel_path)
sheet = workbook.Worksheets(1)
# 獲取打印區(qū)域設(shè)置
if sheet.PageSetup.PrintArea:
# 如果有打印區(qū)域,使用該范圍
pass # 實際實現(xiàn)需解析PrintArea范圍
# 設(shè)置縮放
sheet.PageSetup.Zoom = False
sheet.PageSetup.FitToPagesTall = False
sheet.PageSetup.FitToPagesWide = 1 # 強(qiáng)制一頁寬度
# 導(dǎo)出PDF
sheet.ExportAsFixedFormat(0, pdf_path)
finally:
workbook.Close(False)
excel.Quit()
# 使用示例
convert_with_auto_size('wide_table.xlsx', 'auto_sized.pdf')
五、常見問題解決方案
問題1:中文亂碼處理
原因:系統(tǒng)缺少中文字體或編碼問題
解決方案:
# 對于reportlab方案
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
# 注冊中文字體(需提前下載字體文件)
pdfmetrics.registerFont(TTFont('SimSun', 'SimSun.ttf'))
# 然后在TableStyle中使用
style = TableStyle([
('FONTNAME', (0, 0), (-1, -1), 'SimSun'),
])
問題2:轉(zhuǎn)換速度慢
優(yōu)化建議:
- 關(guān)閉Excel界面顯示:
excel.Visible = False - 批量處理時減少Excel實例創(chuàng)建次數(shù)
- 對于簡單表格,優(yōu)先使用pandas方案
- 使用多線程處理(注意win32com的線程安全問題)
問題3:內(nèi)存占用過高
解決方案:
# 處理大文件時分段讀取
def convert_large_file(excel_path, pdf_path, chunk_size=1000):
"""
分段處理大型Excel文件
"""
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = False
try:
workbook = excel.Workbooks.Open(excel_path)
sheet = workbook.Worksheets(1)
# 獲取總行數(shù)
used_range = sheet.UsedRange
total_rows = used_range.Rows.Count
# 分段處理邏輯(此處簡化,實際需實現(xiàn)分段導(dǎo)出)
for i in range(0, total_rows, chunk_size):
# 每次處理chunk_size行
pass
finally:
workbook.Close(False)
excel.Quit()
問題4:PDF文件過大
壓縮技巧:
使用ghostscript壓縮:
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile=compressed.pdf input.pdf
在Python中調(diào)用:
import subprocess
def compress_pdf(input_path, output_path):
cmd = [
'gs',
'-sDEVICE=pdfwrite',
'-dCompatibilityLevel=1.4',
'-dPDFSETTINGS=/ebook',
'-dNOPAUSE',
'-dQUIET',
'-dBATCH',
f'-sOutputFile={output_path}',
input_path
]
subprocess.run(cmd, check=True)
六、完整項目示例
項目結(jié)構(gòu)
excel2pdf/
├── converter.py # 核心轉(zhuǎn)換邏輯
├── utils.py # 輔助工具函數(shù)
├── config.py # 配置文件
├── templates/ # 模板文件
└── tests/ # 測試用例
核心代碼實現(xiàn)
# converter.py
import os
from enum import Enum
from typing import Union, Optional
class ConvertMethod(Enum):
WIN32COM = 1
PANDAS = 2
OPENPYXL = 3
class ExcelConverter:
def __init__(self, method: ConvertMethod = ConvertMethod.WIN32COM):
self.method = method
def convert(self,
input_path: str,
output_path: str,
sheet_name: Optional[Union[str, int]] = None,
**kwargs) -> bool:
"""
統(tǒng)一轉(zhuǎn)換接口
"""
if self.method == ConvertMethod.WIN32COM:
from .utils import win32com_convert
return win32com_convert(input_path, output_path, sheet_name, **kwargs)
elif self.method == ConvertMethod.PANDAS:
from .utils import pandas_convert
return pandas_convert(input_path, output_path, sheet_name, **kwargs)
else:
from .utils import openpyxl_convert
return openpyxl_convert(input_path, output_path, sheet_name, **kwargs)
# 使用示例
if __name__ == "__main__":
converter = ExcelConverter(ConvertMethod.WIN32COM)
success = converter.convert(
input_path='data.xlsx',
output_path='output.pdf',
sheet_name='Sheet1',
scale_factor=1.2
)
print("轉(zhuǎn)換成功" if success else "轉(zhuǎn)換失敗")
七、常見問題Q&A
Q1:轉(zhuǎn)換后的PDF表格邊框不顯示怎么辦?
A:在reportlab方案中,需顯式設(shè)置邊框樣式:
style = TableStyle([
('GRID', (0, 0), (-1, -1), 1, 'black'), # 添加網(wǎng)格線
])
Q2:如何合并多個工作表到一個PDF?
A:使用PyPDF2合并多個PDF文件:
from PyPDF2 import PdfMerger
def merge_pdfs(pdf_list, output_path):
merger = PdfMerger()
for pdf in pdf_list:
merger.append(pdf)
merger.write(output_path)
merger.close()
# 先轉(zhuǎn)換每個工作表為單獨(dú)PDF,再合并
Q3:轉(zhuǎn)換時提示"COM object not released"錯誤?
A:確保在finally塊中正確關(guān)閉對象:
try:
# 操作代碼
finally:
if 'workbook' in locals():
workbook.Close(False)
if 'excel' in locals():
excel.Quit()
Q4:如何設(shè)置PDF的頁眉頁腳?
A:win32com方案:
sheet.PageSetup.CenterHeader = "&""Arial,Bold""&12報表標(biāo)題" sheet.PageSetup.RightFooter = "第&P頁,共&N頁"
Q5:轉(zhuǎn)換后的圖表模糊怎么辦?
A:提高導(dǎo)出分辨率:
# win32com方案
sheet.ExportAsFixedFormat(
0,
pdf_path,
Quality=0, # 0=最高質(zhì)量
IncludeDocProperties=True,
IgnorePrintAreas=False
)
通過本文介紹的方法,你可以根據(jù)實際需求選擇最適合的轉(zhuǎn)換方案。對于企業(yè)級應(yīng)用,建議采用win32com方案并封裝為Web服務(wù);對于輕量級需求,pandas方案足夠高效。所有代碼均經(jīng)過實際測試驗證,可直接集成到現(xiàn)有項目中。
?以上就是從入門到實戰(zhàn)詳解Python如何將Excel工作表轉(zhuǎn)換為PDF的詳細(xì)內(nèi)容,更多關(guān)于Python Excel工作表轉(zhuǎn)PDF的資料請關(guān)注腳本之家其它相關(guān)文章!
- Python使用Spire.XLS for Python輕松實現(xiàn)將Excel轉(zhuǎn)換為PDF
- Python使用Spire.XLS for Python輕松實現(xiàn)Excel轉(zhuǎn)PDF的完整指南
- 使用Python將PDF轉(zhuǎn)成Excel的代碼實現(xiàn)
- 使用Python高效實現(xiàn)Excel轉(zhuǎn)PDF
- 使用Python實現(xiàn)Office文檔(Word/Excel/PowerPoint)批量轉(zhuǎn)換為PDF
- Python將Office文檔(Word、Excel、PDF、PPT)轉(zhuǎn)為OFD格式的實現(xiàn)方法
- Python使用技巧之實現(xiàn)Excel轉(zhuǎn)為PDF
相關(guān)文章
圖文詳解感知機(jī)算法原理及Python實現(xiàn)
感知機(jī)是二類分類的線性分類模型,其輸入為實例的特征向量,輸出為實例的類別(取+1和-1二值)。本文將為大家詳細(xì)講講感知機(jī)算法的原理及實現(xiàn),需要的可以參考一下2022-08-08
python 通過xml獲取測試節(jié)點(diǎn)和屬性的實例
下面小編就為大家分享一篇python 通過xml獲取測試節(jié)點(diǎn)和屬性的實例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-03-03
Python wxpython模塊響應(yīng)鼠標(biāo)拖動事件操作示例
這篇文章主要介紹了Python wxpython模塊響應(yīng)鼠標(biāo)拖動事件操作,結(jié)合實例形式分析了Python使用wxpython模塊創(chuàng)建窗口、綁定事件及相應(yīng)鼠標(biāo)事件相關(guān)操作技巧,需要的朋友可以參考下2018-08-08
tensorflow 實現(xiàn)從checkpoint中獲取graph信息
今天小編就為大家分享一篇tensorflow 實現(xiàn)從checkpoint中獲取graph信息,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-02-02
Python中Jupyter notebook快捷鍵總結(jié)
在本篇文章里小編給大家整理的是一篇關(guān)于Python中Jupyter notebook快捷鍵總結(jié)內(nèi)容,有興趣的朋友們可以學(xué)習(xí)下。2021-04-04
Python中StringIO和BytesIO用法及區(qū)別
我們平時處理的輸入輸出(I/O)大多數(shù)是針對文件或網(wǎng)絡(luò)數(shù)據(jù)的,但有時候,我們希望直接在內(nèi)存中進(jìn)行讀寫,而不必先把數(shù)據(jù)存到硬盤上, StringIO和BytesIO 就派上用場,下面就來介紹一下兩者的用法和區(qū)別小結(jié)2025-08-08

