使用Python win32com批量转换Excel为PDF时仅成功转换首个文件
解决Excel转PDF时第二个文件报错的问题
兄弟,我来帮你搞定这个头疼的问题!你遇到的这个com_error是win32com操作Excel时非常常见的坑,主要是资源没清理干净加上代码里的小bug导致的,咱们一步步来修复:
先说说问题出在哪
- 重复创建Excel实例:你每次调用
SheetPrint函数都会新建一个Excel进程,第一个实例可能没彻底关闭,残留的资源会干扰第二个文件的操作,几千个文件这么干的话,电脑内存直接爆炸。 - PDF命名重复覆盖:你的
num是函数内部的局部变量,每次进入函数都会重置为1,结果所有PDF都会被命名为1.pdf,后面的直接覆盖前面的,这肯定不是你想要的。 - 资源未正确释放:没有显式退出Excel进程,后台残留的Excel实例会占用文件资源,导致后续操作失败。
修复后的代码
我给你调整了代码逻辑,核心是复用一个Excel实例,合理命名PDF,并且确保资源彻底释放:
import win32com.client import os # 配置路径 source_dir = 'C:/Users/Guy/Documents/P/' pdf_output_dir = 'C:/Users/Guy/Documents/P/pdf/' # 确保PDF输出目录存在,不存在则创建 os.makedirs(pdf_output_dir, exist_ok=True) # 获取所有需要转换的xlsm文件 file_list = [ os.path.join(source_dir, filename) for filename in os.listdir(source_dir) if filename.endswith('.xlsm') ] # 只创建一次Excel实例,避免重复创建导致的资源冲突 excel_app = win32com.client.Dispatch("Excel.Application") excel_app.Visible = False excel_app.DisplayAlerts = False # 关闭弹窗提示(比如保存警告),避免程序中断 def convert_sheet_to_pdf(workbook_path, pdf_save_path): try: # 打开工作簿 wb = excel_app.Workbooks.Open(workbook_path) # 选中第2个工作表(注意Excel的索引是从1开始的) target_sheet = wb.WorkSheets(2) # 设置打印区域 target_sheet.PageSetup.PrintArea = 'A1:G50' # 导出为PDF target_sheet.ExportAsFixedFormat( Type=0, # 0代表PDF格式,1代表XPS Filename=pdf_save_path, IgnorePrintAreas=False # 启用我们设置的打印区域 ) # 关闭工作簿,不保存原文件的修改 wb.Close(SaveChanges=False) print(f✅ 成功转换: {os.path.basename(workbook_path)}") except Exception as e: print(f❌ 转换失败 {os.path.basename(workbook_path)}: {str(e)}") # 出错时尽量关闭工作簿,避免资源泄漏 try: wb.Close(SaveChanges=False) except: pass # 遍历所有文件逐个转换 for idx, file_path in enumerate(file_list, start=1): # 用原文件名命名PDF,避免覆盖,也方便对应原文件 file_base_name = os.path.splitext(os.path.basename(file_path))[0] pdf_full_path = os.path.join(pdf_output_dir, f"{file_base_name}.pdf") convert_sheet_to_pdf(file_path, pdf_full_path) # 所有文件处理完成后,彻底退出Excel并释放资源 excel_app.Quit() del excel_app
关键修改点说明
- 复用Excel实例:整个转换过程只创建一个Excel进程,大幅提升效率,也避免了多实例冲突的问题。
- 关闭弹窗提示:添加
DisplayAlerts = False,防止转换过程中弹出保存提示、格式警告等弹窗导致程序卡住。 - 合理命名PDF:用原Excel文件的名称作为PDF文件名,既不会覆盖,也能快速对应到原文件。
- 异常处理:加入try-except块,即使某个文件转换失败,程序也能继续处理下一个,同时尽量关闭出错的工作簿,避免资源泄漏。
- 彻底释放资源:最后调用
Quit()退出Excel,并删除COM对象,确保后台没有残留的Excel进程。
额外注意事项
- 确保你的Excel 2010没有禁用
ExportAsFixedFormat功能(这个版本默认支持,但如果是精简版可能有问题)。 - 转换前确认所有Excel文件都没有被其他程序占用(比如手动打开没关闭)。
- 对于几千个文件,这个代码的效率已经足够,如果担心卡顿,可以适当添加
time.sleep(0.1)的小延迟,但一般不需要。
内容的提问来源于stack exchange,提问作者MakinetaJim




