在日常办公中,Excel表格是数据记录与分析的利器,但直接分享Excel文件可能存在以下问题:

PDF格式完美解决了这些问题:跨平台兼容性强、格式固定、不可编辑(除非使用专业工具)。本文将介绍如何用Python实现自动化转换,覆盖从简单表格到复杂报表的全场景。
方案 | 优点 | 缺点 | 适用场景 |
|---|---|---|---|
win32com | 完美保留格式,支持所有Excel功能 | 仅限Windows,需安装Excel | 企业级复杂报表 |
openpyxl+reportlab | 纯Python实现,跨平台 | 需手动处理样式,复杂度较高 | 简单表格转换 |
pandas+matplotlib | 数据可视化结合 | 样式控制有限 | 数据报表生成 |
xlwings | 支持宏和图表操作 | 依赖Excel安装 | 需要交互的场景 |
comtypes | 类似win32com的替代方案 | 文档较少,调试困难 | Windows备用方案 |
推荐方案:
win32com(最高效)pandas+matplotlib组合openpyxl直接导出bash1pip install pandas openpyxl matplotlib win32com xlwingspip install pywin32python1import win32com.client as win32
2
3def excel_to_pdf_win32com(excel_path, pdf_path, sheet_name=None):
4 """
5 使用win32com将Excel转换为PDF
6 :param excel_path: Excel文件路径
7 :param pdf_path: 输出PDF路径
8 :param sheet_name: 指定工作表名,None则转换所有
9 """
10 excel = win32.gencache.EnsureDispatch('Excel.Application')
11 excel.Visible = False # 不显示Excel界面
12
13 try:
14 workbook = excel.Workbooks.Open(excel_path)
15
16 if sheet_name:
17 # 转换单个工作表
18 sheets = workbook.Worksheets(sheet_name)
19 sheets.ExportAsFixedFormat(0, pdf_path) # 0=PDF格式
20 else:
21 # 转换所有工作表
22 for sheet in workbook.Worksheets:
23 # 为每个工作表创建单独PDF或合并(此处演示单独)
24 sheet_pdf_path = f"{pdf_path.rsplit('.', 1)[0]}_{sheet.Name}.pdf"
25 sheet.ExportAsFixedFormat(0, sheet_pdf_path)
26
27 except Exception as e:
28 print(f"转换失败: {e}")
29 finally:
30 workbook.Close(False)
31 excel.Quit()
32
33# 使用示例
34excel_to_pdf_win32com('data.xlsx', 'output.pdf', 'Sheet1')python1import pandas as pd
2from matplotlib.backends.backend_pdf import PdfPages
3import matplotlib.pyplot as plt
4
5def excel_to_pdf_pandas(excel_path, pdf_path, sheet_name=0):
6 """
7 使用pandas+matplotlib将Excel转换为PDF
8 :param sheet_name: 工作表名或索引,默认第一个
9 """
10 df = pd.read_excel(excel_path, sheet_name=sheet_name)
11
12 with PdfPages(pdf_path) as pdf:
13 fig, ax = plt.subplots(figsize=(12, 6))
14 ax.axis('tight')
15 ax.axis('off')
16
17 # 创建表格
18 table = ax.table(
19 cellText=df.values,
20 colLabels=df.columns,
21 loc='center',
22 cellLoc='center'
23 )
24
25 # 调整样式
26 table.auto_set_font_size(False)
27 table.set_fontsize(10)
28 table.scale(1.2, 1.2)
29
30 pdf.savefig(fig, bbox_inches='tight')
31 plt.close()
32
33# 使用示例(适合简单表格)
34excel_to_pdf_pandas('data.xlsx', 'simple_output.pdf')python1from openpyxl import load_workbook
2from reportlab.lib.pagesizes import letter
3from reportlab.platypus import SimpleDocTemplate, Table, TableStyle
4
5def excel_to_pdf_openpyxl(excel_path, pdf_path, sheet_name=0):
6 """
7 使用openpyxl+reportlab转换
8 """
9 wb = load_workbook(excel_path)
10 sheet = wb.worksheets[sheet_name]
11
12 # 提取数据
13 data = []
14 for row in sheet.iter_rows(values_only=True):
15 data.append(list(row))
16
17 # 创建PDF
18 doc = SimpleDocTemplate(pdf_path, pagesize=letter)
19 table = Table(data)
20
21 # 添加样式
22 style = TableStyle([
23 ('BACKGROUND', (0, 0), (-1, 0), '#4472C4'), # 表头背景
24 ('TEXTCOLOR', (0, 0), (-1, 0), 'white'), # 表头文字
25 ('ALIGN', (0, 0), (-1, -1), 'CENTER'), # 居中
26 ('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
27 ('FONTSIZE', (0, 0), (-1, 0), 12),
28 ('BOTTOMPADDING', (0, 0), (-1, 0), 12),
29 ])
30 table.setStyle(style)
31
32 doc.build([table])
33
34# 使用示例
35excel_to_pdf_openpyxl('data.xlsx', 'openpyxl_output.pdf')python1import os
2from pathlib import Path
3
4def batch_convert(input_folder, output_folder):
5 """
6 批量转换文件夹内所有Excel文件
7 """
8 Path(output_folder).mkdir(parents=True, exist_ok=True)
9
10 for file in os.listdir(input_folder):
11 if file.endswith(('.xlsx', '.xls')):
12 excel_path = os.path.join(input_folder, file)
13 pdf_path = os.path.join(output_folder, f"{Path(file).stem}.pdf")
14
15 try:
16 excel_to_pdf_win32com(excel_path, pdf_path)
17 print(f"转换成功: {file}")
18 except Exception as e:
19 print(f"{file} 转换失败: {e}")
20
21# 使用示例
22batch_convert('input_excels', 'output_pdfs')python1def convert_with_charts(excel_path, pdf_path):
2 """
3 保留图表和条件格式的转换(需win32com)
4 """
5 excel = win32.gencache.EnsureDispatch('Excel.Application')
6 excel.Visible = False
7
8 try:
9 workbook = excel.Workbooks.Open(excel_path)
10
11 # 复制整个工作表到新工作簿(避免修改原文件)
12 new_workbook = excel.Workbooks.Add()
13 workbook.Worksheets(1).Copy(Before=new_workbook.Worksheets(1))
14
15 # 导出为PDF(自动包含所有图表)
16 new_workbook.Worksheets(1).ExportAsFixedFormat(0, pdf_path)
17
18 finally:
19 new_workbook.Close(False)
20 workbook.Close(False)
21 excel.Quit()
22
23# 使用示例
24convert_with_charts('complex_report.xlsx', 'formatted_output.pdf')python1def convert_with_auto_size(excel_path, pdf_path, scale_factor=1.0):
2 """
3 根据内容自动调整PDF尺寸
4 """
5 excel = win32.gencache.EnsureDispatch('Excel.Application')
6 excel.Visible = False
7
8 try:
9 workbook = excel.Workbooks.Open(excel_path)
10 sheet = workbook.Worksheets(1)
11
12 # 获取打印区域设置
13 if sheet.PageSetup.PrintArea:
14 # 如果有打印区域,使用该范围
15 pass # 实际实现需解析PrintArea范围
16
17 # 设置缩放
18 sheet.PageSetup.Zoom = False
19 sheet.PageSetup.FitToPagesTall = False
20 sheet.PageSetup.FitToPagesWide = 1 # 强制一页宽度
21
22 # 导出PDF
23 sheet.ExportAsFixedFormat(0, pdf_path)
24
25 finally:
26 workbook.Close(False)
27 excel.Quit()
28
29# 使用示例
30convert_with_auto_size('wide_table.xlsx', 'auto_sized.pdf')原因:系统缺少中文字体或编码问题 解决方案:
python1# 对于reportlab方案
2from reportlab.pdfbase import pdfmetrics
3from reportlab.pdfbase.ttfonts import TTFont
4
5# 注册中文字体(需提前下载字体文件)
6pdfmetrics.registerFont(TTFont('SimSun', 'SimSun.ttf'))
7
8# 然后在TableStyle中使用
9style = TableStyle([
10 ('FONTNAME', (0, 0), (-1, -1), 'SimSun'),
11])优化建议:
excel.Visible = False解决方案:
python1# 处理大文件时分段读取
2def convert_large_file(excel_path, pdf_path, chunk_size=1000):
3 """
4 分段处理大型Excel文件
5 """
6 excel = win32.gencache.EnsureDispatch('Excel.Application')
7 excel.Visible = False
8
9 try:
10 workbook = excel.Workbooks.Open(excel_path)
11 sheet = workbook.Worksheets(1)
12
13 # 获取总行数
14 used_range = sheet.UsedRange
15 total_rows = used_range.Rows.Count
16
17 # 分段处理逻辑(此处简化,实际需实现分段导出)
18 for i in range(0, total_rows, chunk_size):
19 # 每次处理chunk_size行
20 pass
21
22 finally:
23 workbook.Close(False)
24 excel.Quit()压缩技巧:
ghostscript压缩:bash1gs -sDEVICE=pdfwrite -dCompatibilityLevel=1.4 -dPDFSETTINGS=/ebook -dNOPAUSE -dQUIET -dBATCH -sOutputFile=compressed.pdf input.pdfpython1import subprocess
2
3def compress_pdf(input_path, output_path):
4 cmd = [
5 'gs',
6 '-sDEVICE=pdfwrite',
7 '-dCompatibilityLevel=1.4',
8 '-dPDFSETTINGS=/ebook',
9 '-dNOPAUSE',
10 '-dQUIET',
11 '-dBATCH',
12 f'-sOutputFile={output_path}',
13 input_path
14 ]
15 subprocess.run(cmd, check=True)1excel2pdf/
2├── converter.py # 核心转换逻辑
3├── utils.py # 辅助工具函数
4├── config.py # 配置文件
5├── templates/ # 模板文件
6└── tests/ # 测试用例python1# converter.py
2import os
3from enum import Enum
4from typing import Union, Optional
5
6class ConvertMethod(Enum):
7 WIN32COM = 1
8 PANDAS = 2
9 OPENPYXL = 3
10
11class ExcelConverter:
12 def __init__(self, method: ConvertMethod = ConvertMethod.WIN32COM):
13 self.method = method
14
15 def convert(self,
16 input_path: str,
17 output_path: str,
18 sheet_name: Optional[Union[str, int]] = None,
19 **kwargs) -> bool:
20 """
21 统一转换接口
22 """
23 if self.method == ConvertMethod.WIN32COM:
24 from .utils import win32com_convert
25 return win32com_convert(input_path, output_path, sheet_name, **kwargs)
26 elif self.method == ConvertMethod.PANDAS:
27 from .utils import pandas_convert
28 return pandas_convert(input_path, output_path, sheet_name, **kwargs)
29 else:
30 from .utils import openpyxl_convert
31 return openpyxl_convert(input_path, output_path, sheet_name, **kwargs)
32
33# 使用示例
34if __name__ == "__main__":
35 converter = ExcelConverter(ConvertMethod.WIN32COM)
36 success = converter.convert(
37 input_path='data.xlsx',
38 output_path='output.pdf',
39 sheet_name='Sheet1',
40 scale_factor=1.2
41 )
42
43 print("转换成功" if success else "转换失败")Q1:转换后的PDF表格边框不显示怎么办? A:在reportlab方案中,需显式设置边框样式:
python1style = TableStyle([
2 ('GRID', (0, 0), (-1, -1), 1, 'black'), # 添加网格线
3])Q2:如何合并多个工作表到一个PDF? A:使用PyPDF2合并多个PDF文件:
python1from PyPDF2 import PdfMerger
2
3def merge_pdfs(pdf_list, output_path):
4 merger = PdfMerger()
5 for pdf in pdf_list:
6 merger.append(pdf)
7 merger.write(output_path)
8 merger.close()
9
10# 先转换每个工作表为单独PDF,再合并Q3:转换时提示"COM object not released"错误? A:确保在finally块中正确关闭对象:
python1try:
2 # 操作代码
3finally:
4 if 'workbook' in locals():
5 workbook.Close(False)
6 if 'excel' in locals():
7 excel.Quit()Q4:如何设置PDF的页眉页脚? A:win32com方案:
python1sheet.PageSetup.CenterHeader = "&""Arial,Bold""&12报表标题"
2sheet.PageSetup.RightFooter = "第&P页,共&N页"Q5:转换后的图表模糊怎么办? A:提高导出分辨率:
python1# win32com方案
2sheet.ExportAsFixedFormat(
3 0,
4 pdf_path,
5 Quality=0, # 0=最高质量
6 IncludeDocProperties=True,
7 IgnorePrintAreas=False
8)通过本文介绍的方法,你可以根据实际需求选择最适合的转换方案。对于企业级应用,建议采用win32com方案并封装为Web服务;对于轻量级需求,pandas方案足够高效。所有代码均经过实际测试验证,可直接集成到现有项目中。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。