You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用循环从Excel模板生成多份报表时遇IO及属性错误求助

批量生成月度报表问题解决

错误原因解析

第一个错误:ValueError: I/O operation on closed file.

你在循环外仅加载一次模板文件,第一次调用save()后,openpyxl会自动关闭关联的文件句柄,后续循环再执行保存操作时就会触发文件已关闭的错误。同时,直接修改同一个workbook对象会导致后续报表基于上一次修改后的内容生成,而非原始模板。

第二个错误:AttributeError: 'NoneType' object has no attribute 'save'

你自定义的load_temp_workbook类中,__enter__方法没有返回加载完成的workbook实例,因此with语句中得到的wt是None,调用save()方法自然会报错。

正确实现代码

核心思路:每次循环重新加载原始模板,确保每个报表都基于干净的模板生成;同时简化数据处理逻辑,避免数据匹配错误。

import os
from openpyxl import load_workbook
import pandas as pd

# 设置工作目录
path = r"/Users/xxx/Desktop/xxx"
os.chdir(path)

# 加载并筛选源数据,一次性完成查询提升效率
df = pd.read_excel("Data.xlsx", sheet_name='Sheet1', header=0)
filtered_df = df[df['To_choose'] == "Y"]

# 循环生成每个客户的报表
for _, row in filtered_df.iterrows():
    # 每次循环重新加载原始模板,避免数据污染和文件句柄问题
    workbook = load_workbook('template.xlsx')
    sheet = workbook['Statement']
    
    # 填充基础信息
    sheet['B6'].value = row['client']
    sheet['G6'].value = "31/12/2022"
    
    # 填充业务数据(替换为模板中对应单元格位置)
    sheet['XX'].value = row['Net']  # 示例:点击量对应的单元格
    sheet['YY'].value = row['Fee']  # 示例:应付费用对应的单元格
    
    # 保存个性化报表
    workbook.save(f"Statement as of 31 Dec 2022 of {row['client']}.xlsx")

关键优化点

  • 循环内重复加载模板:彻底避免模板被修改后污染后续报表,同时解决文件句柄关闭的问题。
  • 一次性筛选数据:用布尔索引替代多次query操作,提升代码运行效率和可读性。
  • iterrows()遍历数据:直接获取每行完整数据,避免单独提取列后可能出现的顺序不匹配问题。

内容的提问来源于stack exchange,提问作者beaconho

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 14:25:47