Python Lambda实现S3中Excel文件工作表顺序调整
问题描述
我用Python生成带多工作表的Excel文件,初始工作表顺序是:
["COMP1_hires","COMP2_hires","COMP1_det","COMP2_det"]
想要调整为:
["COMP1_hires","COMP1_det","COMP2_hires","COMP2_det"]
文件最终存在S3指定文件夹里,请问能不能在生成过程中或生成后调整工作表顺序?
现有代码如下(components_sep就是上述初始顺序的列表):
filename = 'exported_comp_file_'+today with io.BytesIO() as output: with pd.ExcelWriter(output, engine='xlsxwriter') as writer: for comp in components_sep: df1= df[df['component']==comp] df1.to_excel(writer, sheet_name=comp, index=False) writer.save() data = output.getvalue() s3 = boto3.resource('s3') s3.Bucket('demo bucket').put_object(Key='myfolder/'+filename+'.xlsx', Body=data)
解决方案
方法一:生成时直接按目标顺序创建工作表(推荐)
这是最高效的方式,无需额外修改已生成的Excel文件,直接调整遍历顺序即可。
你可以直接定义目标顺序的列表,按该顺序循环生成工作表:
filename = 'exported_comp_file_'+today # 定义目标工作表顺序 target_sheet_order = ["COMP1_hires","COMP1_det","COMP2_hires","COMP2_det"] with io.BytesIO() as output: with pd.ExcelWriter(output, engine='xlsxwriter') as writer: # 按目标顺序遍历生成工作表 for comp in target_sheet_order: df1= df[df['component']==comp] df1.to_excel(writer, sheet_name=comp, index=False) writer.save() data = output.getvalue() s3 = boto3.resource('s3') s3.Bucket('demo bucket').put_object(Key='myfolder/'+filename+'.xlsx', Body=data)
如果不想硬编码目标顺序,也可以通过分组排序动态生成:
from itertools import groupby # 按组件前缀(COMP1/COMP2)分组,每组内按后缀排序 sorted_components = [] # 先按前缀排序,再按完整名称排序 for key, group in groupby(sorted(components_sep, key=lambda x: (x.split('_')[0], x))): sorted_components.extend(list(group)) # 后续用sorted_components代替原components_sep循环即可
方法二:生成后调整工作表顺序(适用已生成文件的场景)
如果已经生成了Excel文件,或无法提前修改生成顺序,可以用openpyxl库加载文件调整工作表顺序,再重新上传到S3:
- 先安装依赖:
pip install openpyxl - 修改后的代码:
import openpyxl filename = 'exported_comp_file_'+today with io.BytesIO() as output: with pd.ExcelWriter(output, engine='xlsxwriter') as writer: for comp in components_sep: df1= df[df['component']==comp] df1.to_excel(writer, sheet_name=comp, index=False) writer.save() # 加载生成的Excel文件 wb = openpyxl.load_workbook(output) # 定义目标顺序,调整工作表位置 target_order = ["COMP1_hires","COMP1_det","COMP2_hires","COMP2_det"] # 按目标顺序重新排列工作表 for idx, sheet_name in enumerate(target_order): wb._sheets.insert(idx, wb._sheets.pop(wb.sheetnames.index(sheet_name))) # 保存调整后的文件到新的BytesIO对象 adjusted_output = io.BytesIO() wb.save(adjusted_output) adjusted_output.seek(0) s3 = boto3.resource('s3') s3.Bucket('demo bucket').put_object(Key='myfolder/'+filename+'.xlsx', Body=adjusted_output.getvalue())
注意:这种方式需要额外加载并修改文件,性能不如方法一,优先推荐方法一。
内容的提问来源于stack exchange,提问作者Rick
相关产品推荐
相关产品推荐

