乐于分享
好东西不私藏

告别手动导出!Python一键把50个Excel转成PDF报表

告别手动导出!Python一键把50个Excel转成PDF报表

🚀 告别手动导出!Python一键把50个Excel转成PDF报表,同事以为我开了外挂

💡 每月把几十个Excel另存为PDF发给客户?一个脚本3分钟搞定,省下的时间够摸一上午鱼 🐟


🎯 场景还原

小李是某公司的销售助理,每个月底要做这些事:

  1. 30个区域的销售Excel,逐个打开
  2. 每个都要调整打印区域、页眉页脚
  3. 另存为PDF,发给对应的区域经理

每次光"打开→调格式→另存为PDF"就要点30×5=150次鼠标,加上等Excel响应的时间,2小时起步

更要命的是,总有那么一两个会忘掉,第二天被领导问"XX区域的报表怎么没发?" 😅

如果你也干过这种活,今天这个脚本就是为你写的。


📦 用到的库

pip install pywin32 pandas openpyxl
库名
干啥用
pywin32
调用Windows系统的Excel程序(COM接口),保真度最高
pandas
读写Excel数据
openpyxl
处理xlsx格式

💡 为什么用 pywin32 而不是直接转PDF? 因为它是调用真实Excel程序去转换,图表、条件格式、打印区域全都能保留,效果跟手动"另存为PDF"一模一样!

⚠️ 注意:此方案仅适用于Windows系统(需要安装Microsoft Excel)


🔧 完整代码

import os
import sys
import time

defexcel_to_pdf_batch(input_folder, output_folder=None):
"""
    批量将Excel文件转换为PDF
    :param input_folder: Excel文件所在文件夹
    :param output_folder: PDF输出文件夹(默认同目录下新建PDF文件夹)
    """

# 检查是否在Windows环境
if sys.platform != 'win32':
        print("❌ 此脚本仅支持Windows系统(需要Microsoft Excel)")
return

try:
import win32com.client
except ImportError:
        print("❌ 请先安装pywin32:pip install pywin32")
return

# 默认输出到同级目录的PDF文件夹
if output_folder isNone:
        output_folder = os.path.join(input_folder, "PDF输出")
    os.makedirs(output_folder, exist_ok=True)

# 收集所有Excel文件
    excel_files = [
        f for f in os.listdir(input_folder)
if f.lower().endswith(('.xlsx''.xls')) andnot f.startswith('~$')
    ]

ifnot excel_files:
        print(f"⚠️ 文件夹 {input_folder} 中没有找到Excel文件")
return

    print(f"📂 找到 {len(excel_files)} 个Excel文件,开始转换...\n")

# 启动Excel程序(后台运行,不弹窗)
    excel_app = win32com.client.DispatchEx("Excel.Application")
    excel_app.Visible = False# 不显示Excel窗口
    excel_app.DisplayAlerts = False# 不弹警告框

    success_count = 0
    fail_list = []

for i, filename in enumerate(excel_files, 1):
        filepath = os.path.abspath(os.path.join(input_folder, filename))
        pdf_name = os.path.splitext(filename)[0] + ".pdf"
        pdf_path = os.path.abspath(os.path.join(output_folder, pdf_name))

try:
            print(f"  [{i}/{len(excel_files)}] 转换中:{filename}")

# 打开工作簿
            wb = excel_app.Workbooks.Open(filepath)

# 设置打印区域为"已使用区域"
for ws in wb.Worksheets:
                ws.PageSetup.Zoom = False
                ws.PageSetup.FitToPagesWide = 1# 宽度适合1页
                ws.PageSetup.FitToPagesTall = False# 高度不限

# 导出PDF(0 = xlTypePDF)
            wb.ExportAsFixedFormat(0, pdf_path)
            wb.Close(SaveChanges=False)

            success_count += 1
            print(f"    ✅ 成功 → {pdf_name}")

except Exception as e:
            fail_list.append((filename, str(e)))
            print(f"    ❌ 失败:{e}")
try:
                wb.Close(SaveChanges=False)
except:
pass

# 关闭Excel程序
    excel_app.Quit()
del excel_app

# 汇总结果
    print(f"\n{'='*40}")
    print(f"🎉 转换完成!")
    print(f"   ✅ 成功:{success_count} 个")
    print(f"   ❌ 失败:{len(fail_list)} 个")
    print(f"   📁 PDF输出目录:{output_folder}")

if fail_list:
        print(f"\n⚠️ 失败文件清单:")
for fname, err in fail_list:
            print(f"   - {fname}{err}")


if __name__ == "__main__":
    excel_to_pdf_batch(
        input_folder=r"D:\销售报表\2026年5月",   # 改成你的Excel文件夹
        output_folder=r"D:\销售报表\2026年5月-PDF"# 改成你想输出的位置
    )

📝 代码解读

核心原理只有3步:

  1. 启动Excel后台进程 → DispatchEx("Excel.Application") 就像偷偷打开了一个Excel,但不让你看到窗口
  2. 逐个打开文件,设置打印格式 → FitToPagesWide = 1 让内容宽度适配一页PDF,不会被截断
  3. 导出PDF → ExportAsFixedFormat(0, pdf_path) 跟你手动点"另存为PDF"效果完全一样

关键细节:

  • ~$ 开头的文件是Excel临时文件(打开时生成的),必须跳过
  • Visible = False 让Excel在后台运行,不干扰你干别的事
  • DisplayAlerts = False 屏蔽"是否保存"之类的弹窗

⚠️ 避坑指南

坑①:转换后PDF内容被截断/排版乱掉

现象:转出来的PDF,表格右边被切掉了,或者挤成一团

原因:Excel的打印区域没有正确设置,默认只打印"已使用区域",但有些单元格虽然有内容却不被识别

修复方法

# 在ExportAsFixedFormat之前,手动设置打印区域
for ws in wb.Worksheets:
    used_range = ws.UsedRange
    last_row = used_range.Row + used_range.Rows.Count - 1
    last_col = used_range.Column + used_range.Columns.Count - 1
    first_cell = ws.Cells(11).Address
    last_cell = ws.Cells(last_row, last_col).Address
    ws.PageSetup.PrintArea = f"{first_cell}:{last_cell}"

坑②:脚本运行后Excel进程没退出,占内存

现象:任务管理器里多了几十个 EXCEL.EXE,电脑越来越卡

原因:如果中途报错,excel_app.Quit() 可能没被执行到

修复方法:用 try...finally 确保退出:

excel_app = win32com.client.DispatchEx("Excel.Application")
try:
# ... 所有转换逻辑 ...
finally:
    excel_app.Quit()
del excel_app  # 彻底释放COM对象

坑③:中文路径或文件名报错

现象:文件路径含中文时,ExportAsFixedFormat 直接报错

原因:COM接口对中文路径支持不稳定

修复方法:用 os.path.abspath() 转换为绝对路径(代码中已包含),如果还报错,尝试把文件复制到纯英文路径再转换。


💡 扩展思路

  1. 自动发送邮件 → 结合 smtplib,转完PDF自动发给对应区域经理,实现"一键到底"
  2. 加水印/页码 → 用 PyPDF2 或 reportlab 在PDF上叠加公司水印和页码
  3. 定时执行 → 用Windows任务计划程序,每月最后一天自动运行,彻底解放双手

📢 涨粉引导区

🎁 关注「码上办公」回复「Python」获取:

  • 50个办公自动化脚本合集
  • Python快捷键速查表
  • 本文完整源码+测试数据

💬 思考题:如果每个Excel文件里有多个Sheet,但你只想转其中名为"汇总"的Sheet为PDF,代码应该怎么改?评论区见~

👉 觉得有用?点「在看」+「收藏」,下次用到不迷路!