文章目录
- 方案 优点 缺点 适用场景 win32com 完美保留格式,支持所有Excel功能 仅限Windows,需安装Excel 企业级复杂报表 openpyxl+reportlab 纯Python实现,跨平台 需手动处理样式,复杂度较高 简单表格转换 pandas+matplotlib 数据可视化结合 样式控制有限 数据报表生成 xlwings 支持宏和图表操作 依赖Excel安装 需要交互的场景 comtypes 类似win32com的替代方案 文档较少,调试困难 Windows备用方案 推荐方案: Windows环境:win32com(最高效) 跨平台需求:pandas+matplotlib组合 简单需求:openpyxl直接导出
- 安装基础库: pip install pandas openpyxl matplotlib win32com xlwings Windows用户需安装: Microsoft Excel(win32com依赖) PyWin32:pip install pywin32
- import win32com.client as win32 def excel_to_pdf_win32com(excel_path, pdf_path, sheet_name=None): “”” 使用win32com将Excel转换为PDF :param excel_path: Excel文件路径 :param pdf_path: 输出PDF路径 :param sheet_name: 指定工作表名,None则转换所有 “”” excel = win32.gencache.EnsureDispatch(‘Excel.Application’) excel.Visible = False # 不显示Excel界面 try: workbook = excel.Workbooks.Open(excel_path) if sheet_name: # 转换单个工作表 sheets = workbook.Worksheets(sheet_name) sheets.ExportAsFixedFormat(0, pdf_path) # 0=PDF格式 else: # 转换所有工作表 for sheet in workbook.Worksheets: # 为每个工作表创建单独PDF或合并(此处演示单独) sheet_pdf_path = f”{pdf_path.rsplit(‘.’, 1)[0]}_{sheet.Name}.pdf” sheet.ExportAsFixedFormat(0, sheet_pdf_path) except Exception as e: print(f”转换失败: {e}”) finally: workbook.Close(False) excel.Quit() # 使用示例 excel_to_pdf_win32com(‘data.xlsx’, ‘output.pdf’, ‘Sheet1’)
- 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转换为PDF :param sheet_name: 工作表名或索引,默认第一个 “”” 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’) # 创建表格 table = ax.table( cellText=df.values, colLabels=df.columns, loc=’center’, cellLoc=’center’ ) # 调整样式 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’)
- 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转换 “”” wb = load_workbook(excel_path) sheet = wb.worksheets[sheet_name] # 提取数据 data = [] for row in sheet.iter_rows(values_only=True): data.append(list(row)) # 创建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( ) # 使用示例 excel_to_pdf_openpyxl(‘data.xlsx’, ‘openpyxl_output.pdf’)
- import os from pathlib import Path def batch_convert(input_folder, output_folder): “”” 批量转换文件夹内所有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”转换成功: {file}”) except Exception as e: print(f”{file} 转换失败: {e}”) # 使用示例 batch_convert(‘input_excels’, ‘output_pdfs’)
- def convert_with_charts(excel_path, pdf_path): “”” 保留图表和条件格式的转换(需win32com) “”” excel = win32.gencache.EnsureDispatch(‘Excel.Application’) excel.Visible = False try: workbook = excel.Workbooks.Open(excel_path) # 复制整个工作表到新工作簿(避免修改原文件) new_workbook = excel.Workbooks.Add() workbook.Worksheets(1).Copy(Before=new_workbook.Worksheets(1)) # 导出为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’)
- def convert_with_auto_size(excel_path, pdf_path, scale_factor=1.0): “”” 根据内容自动调整PDF尺寸 “”” excel = win32.gencache.EnsureDispatch(‘Excel.Application’) excel.Visible = False try: workbook = excel.Workbooks.Open(excel_path) sheet = workbook.Worksheets(1) # 获取打印区域设置 if sheet.PageSetup.PrintArea: # 如果有打印区域,使用该范围 pass # 实际实现需解析PrintArea范围 # 设置缩放 sheet.PageSetup.Zoom = False sheet.PageSetup.FitToPagesTall = False sheet.PageSetup.FitToPagesWide = 1 # 强制一页宽度 # 导出PDF sheet.ExportAsFixedFormat(0, pdf_path) finally: workbook.Close(False) excel.Quit() # 使用示例 convert_with_auto_size(‘wide_table.xlsx’, ‘auto_sized.pdf’)
- 原因:系统缺少中文字体或编码问题 解决方案: # 对于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’), ])
- 优化建议: 关闭Excel界面显示:excel.Visible = False 批量处理时减少Excel实例创建次数 对于简单表格,优先使用pandas方案 使用多线程处理(注意win32com的线程安全问题)
- 解决方案: # 处理大文件时分段读取 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) # 获取总行数 used_range = sheet.UsedRange total_rows = used_range.Rows.Count # 分段处理逻辑(此处简化,实际需实现分段导出) for i in range(0, total_rows, chunk_size): # 每次处理chunk_size行 pass finally: workbook.Close(False) excel.Quit()
- 压缩技巧: 使用ghostscript压缩: gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile=compressed.pdf input.pdf 在Python中调用: 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)
- excel2pdf/├── converter.py # 核心转换逻辑├── utils.py # 辅助工具函数├── config.py # 配置文件├── templates/ # 模板文件└── tests/ # 测试用例
- # 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: “”” 统一转换接口 “”” 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(“转换成功” if success else “转换失败”)
目录
- 一、为什么需要Excel转PDF功能
- 二、技术选型与工具准备
- 主流转换方案对比
- 环境配置指南
- 三、基础转换方法实现
- 方法1:使用win32com(Windows最佳)
- 方法2:纯Python方案(跨平台)
- 方法3:openpyxl直接处理(适合简单需求)
- 四、进阶应用场景
- 场景1:批量转换多个Excel文件
- 场景2:保留复杂格式(图表+条件格式)
- 场景3:动态调整PDF尺寸
- 五、常见问题解决方案
- 问题1:中文乱码处理
- 问题2:转换速度慢
- 问题3:内存占用过高
- 问题4:PDF文件过大
- 六、完整项目示例
- 项目结构
- 核心代码实现
- 七、常见问题Q&A
在日常办公中,Excel表格是数据记录与分析的利器,但直接分享Excel文件可能存在以下问题:
- 接收方可能没有安装Excel软件
- 不同版本Excel打开时格式错乱
- 担心数据被误修改
- 需要打印时格式固定
PDF格式完美解决了这些问题:跨平台兼容性强、格式固定、不可编辑(除非使用专业工具)。本文将介绍如何用Python实现自动化转换,覆盖从简单表格到复杂报表的全场景。
| 方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
| win32com | 完美保留格式,支持所有Excel功能 | 仅限Windows,需安装Excel | 企业级复杂报表 |
| openpyxl+reportlab | 纯Python实现,跨平台 | 需手动处理样式,复杂度较高 | 简单表格转换 |
| pandas+matplotlib | 数据可视化结合 | 样式控制有限 | 数据报表生成 |
| xlwings | 支持宏和图表操作 | 依赖Excel安装 | 需要交互的场景 |
| comtypes | 类似win32com的替代方案 | 文档较少,调试困难 | Windows备用方案 |
推荐方案:
- Windows环境:
win32com(最高效) - 跨平台需求:
pandas+matplotlib组合 - 简单需求:
openpyxl直接导出
安装基础库:
pip install pandas openpyxl matplotlib win32com xlwings
Windows用户需安装:
- Microsoft Excel(win32com依赖)
- PyWin32:
pip install pywin32
import win32com.client as win32
def excel_to_pdf_win32com(excel_path, pdf_path, sheet_name=None):
"""
使用win32com将Excel转换为PDF
:param excel_path: Excel文件路径
:param pdf_path: 输出PDF路径
:param sheet_name: 指定工作表名,None则转换所有
"""
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = False # 不显示Excel界面
try:
workbook = excel.Workbooks.Open(excel_path)
if sheet_name:
# 转换单个工作表
sheets = workbook.Worksheets(sheet_name)
sheets.ExportAsFixedFormat(0, pdf_path) # 0=PDF格式
else:
# 转换所有工作表
for sheet in workbook.Worksheets:
# 为每个工作表创建单独PDF或合并(此处演示单独)
sheet_pdf_path = f"{pdf_path.rsplit('.', 1)[0]}_{sheet.Name}.pdf"
sheet.ExportAsFixedFormat(0, sheet_pdf_path)
except Exception as e:
print(f"转换失败: {e}")
finally:
workbook.Close(False)
excel.Quit()
# 使用示例
excel_to_pdf_win32com('data.xlsx', 'output.pdf', 'Sheet1')
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转换为PDF
:param sheet_name: 工作表名或索引,默认第一个
"""
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')
# 创建表格
table = ax.table(
cellText=df.values,
colLabels=df.columns,
loc='center',
cellLoc='center'
)
# 调整样式
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')
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转换
"""
wb = load_workbook(excel_path)
sheet = wb.worksheets[sheet_name]
# 提取数据
data = []
for row in sheet.iter_rows(values_only=True):
data.append(list(row))
# 创建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(
import os
from pathlib import Path
def batch_convert(input_folder, output_folder):
"""
批量转换文件夹内所有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"转换成功: {file}")
except Exception as e:
print(f"{file} 转换失败: {e}")
# 使用示例
batch_convert('input_excels', 'output_pdfs')
def convert_with_charts(excel_path, pdf_path):
"""
保留图表和条件格式的转换(需win32com)
"""
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = False
try:
workbook = excel.Workbooks.Open(excel_path)
# 复制整个工作表到新工作簿(避免修改原文件)
new_workbook = excel.Workbooks.Add()
workbook.Worksheets(1).Copy(Before=new_workbook.Worksheets(1))
# 导出为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')
def convert_with_auto_size(excel_path, pdf_path, scale_factor=1.0):
"""
根据内容自动调整PDF尺寸
"""
excel = win32.gencache.EnsureDispatch('Excel.Application')
excel.Visible = False
try:
workbook = excel.Workbooks.Open(excel_path)
sheet = workbook.Worksheets(1)
# 获取打印区域设置
if sheet.PageSetup.PrintArea:
# 如果有打印区域,使用该范围
pass # 实际实现需解析PrintArea范围
# 设置缩放
sheet.PageSetup.Zoom = False
sheet.PageSetup.FitToPagesTall = False
sheet.PageSetup.FitToPagesWide = 1 # 强制一页宽度
# 导出PDF
sheet.ExportAsFixedFormat(0, pdf_path)
finally:
workbook.Close(False)
excel.Quit()
# 使用示例
convert_with_auto_size('wide_table.xlsx', 'auto_sized.pdf')
原因:系统缺少中文字体或编码问题
解决方案:
# 对于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'),
])
优化建议:
- 关闭Excel界面显示:
excel.Visible = False - 批量处理时减少Excel实例创建次数
- 对于简单表格,优先使用pandas方案
- 使用多线程处理(注意win32com的线程安全问题)
解决方案:
# 处理大文件时分段读取
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)
# 获取总行数
used_range = sheet.UsedRange
total_rows = used_range.Rows.Count
# 分段处理逻辑(此处简化,实际需实现分段导出)
for i in range(0, total_rows, chunk_size):
# 每次处理chunk_size行
pass
finally:
workbook.Close(False)
excel.Quit()
压缩技巧:
使用ghostscript压缩:
gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile=compressed.pdf input.pdf
在Python中调用:
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)
excel2pdf/
├── converter.py # 核心转换逻辑
├── utils.py # 辅助工具函数
├── config.py # 配置文件
├── templates/ # 模板文件
└── tests/ # 测试用例
excel2pdf/
├── converter.py # 核心转换逻辑
├── utils.py # 辅助工具函数
├── config.py # 配置文件
├── templates/ # 模板文件
└── tests/ # 测试用例
# 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:
"""
统一转换接口
"""
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("转换成功" if success else "转换失败")
Q1:转换后的PDF表格边框不显示怎么办?
A:在reportlab方案中,需显式设置边框样式:
style = TableStyle([
('GRID', (0, 0), (-1, -1), 1, 'black'), # 添加网格线
])
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()
# 先转换每个工作表为单独PDF,再合并
Q3:转换时提示"COM object not released"错误?
A:确保在finally块中正确关闭对象:
try:
# 操作代码
finally:
if 'workbook' in locals():
workbook.Close(False)
if 'excel' in locals():
excel.Quit()
Q4:如何设置PDF的页眉页脚?
A:win32com方案:
sheet.PageSetup.CenterHeader = "&""Arial,Bold""&12报表标题" sheet.PageSetup.RightFooter = "第&P页,共&N页"
Q5:转换后的图表模糊怎么办?
A:提高导出分辨率:
# win32com方案
sheet.ExportAsFixedFormat(
0,
pdf_path,
Quality=0, # 0=最高质量
IncludeDocProperties=True,
IgnorePrintAreas=False
)
通过本文介绍的方法,你可以根据实际需求选择最适合的转换方案。对于企业级应用,建议采用win32com方案并封装为Web服务;对于轻量级需求,pandas方案足够高效。所有代码均经过实际测试验证,可直接集成到现有项目中。
以上就是从入门到实战详解Python如何将Excel工作表转换为PDF的详细内容,更多关于Python Excel工作表转PDF的资料请关注风君子博客其它相关文章!
您可能感兴趣的文章:
- Python使用Spire.XLS for Python轻松实现将Excel转换为PDF
- Python使用Spire.XLS for Python轻松实现Excel转PDF的完整指南
- 使用Python将PDF转成Excel的代码实现
- 使用Python高效实现Excel转PDF
- 使用Python实现Office文档(Word/Excel/PowerPoint)批量转换为PDF
- Python将Office文档(Word、Excel、PDF、PPT)转为OFD格式的实现方法
- Python使用技巧之实现Excel转为PDF