影刀RPA Excel拆分:按条件拆分工作表
署名:林焱
什么情况用什么
汇总表里有多个部门的数据,需要按部门拆分成独立Excel文件发给各部门负责人。或者一张总表里有12个月的数据,需要按月拆分。
| 场景 | 推荐方式 |
|---|---|
| 按某列值拆分成多个文件 | Python + pandas groupby |
| 按某列值拆分到同文件不同Sheet | Python + openpyxl/pandas |
| 按固定行数拆分 | Python + 分块处理 |
怎么做
方式一:按列值拆分成多个文件
importpandasaspdimportos# 读取总表df=pd.read_excel(r"D:\数据\员工总表.xlsx",sheet_name="员工信息")# 按部门列拆分output_dir=r"D:\数据\拆分结果"os.makedirs(output_dir,exist_ok=True)[video(video-sNX3LOPR-1783501230813)(type-csdn)(url-https://live.csdn.net/v/embed/525000)(image-https://v-blog.csdnimg.cn/asset/23da3fe1f67a47106d725406cfde9a97/cover/Cover0.jpg)(title-拼多多店群自动化上架方案)]fordept,groupindf.groupby("部门"):# 生成文件名(清理非法字符)safe_name=str(dept).replace("/","_").replace("\\","_").replace(":","_")output_path=os.path.join(output_dir,f"{safe_name}.xlsx")group.to_excel(output_path,index=False)print(f"已生成:{safe_name}.xlsx,{len(group)}行")方式二:拆分到同文件不同Sheet
importpandasaspd df=pd.read_excel(r"D:\数据\员工总表.xlsx")withpd.ExcelWriter(r"D:\数据\按部门拆分.xlsx")aswriter:fordept,groupindf.groupby("部门"):# Sheet名最多31字符,且不能包含特殊字符safe_name=str(dept)[:31]safe_name=safe_name.replace("/","_").replace("\\","_").replace("?","_")safe_name=safe_name.replace("*","_").replace("[","_").replace("]","_")group.to_excel(writer,sheet_name=safe_name,index=False)print(f"Sheet:{safe_name},{len(group)}行")方式三:按固定行数拆分
importpandasaspdimportos df=pd.read_excel(r"D:\数据\大表.xlsx")rows_per_file=1000# 每个文件1000行output_dir=r"D:\数据\拆分"os.makedirs(output_dir,exist_ok=True)total_rows=len(df)file_count=(total_rows+rows_per_file-1)//rows_per_fileforiinrange(file_count):start=i*rows_per_file end=min((i+1)*rows_per_file,total_rows)chunk=df.iloc[start:end]output_path=os.path.join(output_dir,f"数据_{i+1:03d}.xlsx")chunk.to_excel(output_path,index=False)print(f"已生成: 数据_{i+1:03d}.xlsx,{len(chunk)}行")完整流程:多维度拆分
importpandasaspdimportos# yd_input: input_path, output_dir, split_col, split_modeinput_path=yd_input.get("input_path",r"D:\数据\总表.xlsx")output_dir=yd_input.get("output_dir",r"D:\数据\拆分结果")split_col=yd_input.get("split_col","部门")# 按哪列拆分split_mode=yd_input.get("split_mode","file")# file=多文件, sheet=多Sheetos.makedirs(output_dir,exist_ok=True)# 读取数据df=pd.read_excel(input_path)print(f"总数据:{len(df)}行")# 清理拆分列的空值df=df.dropna(subset=[split_col])df[split_col]=df[split_col].astype(str).str.strip()# 统计各分组group_counts=df[split_col].value_counts()print(f"分组数:{len(group_counts)}")print(group_counts.head(10))defsafe_filename(name):"""清理文件名/Sheet名中的非法字符"""illegal=['/','\\',':','*','?','"','<','>','|']forchinillegal:name=name.replace(ch,'_')returnname[:31]# Sheet名最多31字符ifsplit_mode=="file":# 拆分成多个文件forkey,groupindf.groupby(split_col):safe_name=safe_filename(str(key))output_path=os.path.join(output_dir,f"{safe_name}.xlsx")group.to_excel(output_path,index=False)yd_output={"status":"ok","mode":"file","file_count":len(group_counts),"groups":group_counts.to_dict()}elifsplit_mode=="sheet":# 拆分到同文件不同Sheetoutput_path=os.path.join(output_dir,"拆分结果.xlsx")# Excel Sheet数量限制:最多255个iflen(group_counts)>250:yd_output={"status":"error","message":f"分组数{len(group_counts)}超过Sheet上限"}else:withpd.ExcelWriter(output_path,engine="openpyxl")aswriter:forkey,groupindf.groupby(split_col):safe_name=safe_filename(str(key))group.to_excel(writer,sheet_name=safe_name,index=False)yd_output={"status":"ok","mode":"sheet","sheet_count":len(group_counts),"output":output_path}有什么坑
坑一:文件名包含非法字符导致保存失败
现象:按"部门"列拆分,某个部门名是"研发/测试部",生成文件时报错。
原因:Windows文件名不能包含/ \ : * ? " < > |这些字符。
解决:统一替换非法字符:
defsafe_filename(name):illegal=['/','\\',':','*','?','"','<','>','|']forchinillegal:name=str(name).replace(ch,'_')returnname# 使用safe_name=safe_filename(dept)output_path=os.path.join(output_dir,f"{safe_name}.xlsx")坑二:分组值为空或NaN导致报错
现象:拆分列有空值,groupby时空值被丢弃,或者生成的文件名为"nan.xlsx"。
原因:pandas的groupby默认忽略NaN值,空值不会产生分组。
解决:提前处理空值:
TEMU店群如何管理运营?
# 方案1:删除空值行df=df.dropna(subset=[split_col])# 方案2:填充空值df[split_col]=df[split_col].fillna("未分类")# 方案3:把空字符串也当作"未分类"df[split_col]=df[split_col].replace("","未分类").fillna("未分类")坑三:拆分后每个文件的表头格式丢失
现象:原表有格式化的表头(背景色、加粗等),拆分后全是默认格式。
原因:pandas的to_excel不保留原Excel格式,只写数据。
解决:用openpyxl写入并设置格式,或先复制模板再写数据:
importopenpyxlfromopenpyxl.stylesimportFont,PatternFill,Alignmentimportshutil# 模板文件(只有格式化表头)template_path=r"D:\模板\表头模板.xlsx"fordept,groupindf.groupby("部门"):output_path=os.path.join(output_dir,f"{dept}.xlsx")# 复制模板shutil.copy2(template_path,output_path)# 打开复制的文件写入数据wb=openpyxl.load_workbook(output_path)ws=wb.active# 从第2行开始写数据(第1行是模板表头)forrow_idx,(_,row_data)inenumerate(group.iterrows(),2):forcol_idx,valueinenumerate(row_data,1):ws.cell(row=row_idx,column=col_idx).value=value wb.save(output_path)坑四:按多列组合拆分时分组太多
现象:按"部门+岗位"两列组合拆分,生成了几百个文件,每个文件只有几行数据。
原因:多列组合的分组数 = 部门数 × 岗位数,容易爆炸。
解决:限制最小分组大小,小分组合并到"其他":
# 按多列拆分时,小分组合并min_group_size=10# 少于10行的分组归入"其他"# 创建组合键df["分组键"]=df["部门"].astype(str)+"_"+df["岗位"].astype(str)# 统计各组大小group_sizes=df["分组键"].value_counts()# 标记小分组为"其他"small_groups=group_sizes[group_sizes<min_group_size].index df.loc[df["分组键"].isin(small_groups),"分组键"]="其他"# 按合并后的键拆分forkey,groupindf.groupby("分组键"):output_path=os.path.join(output_dir,f"{key}.xlsx")group.drop(columns=["分组键"]).to_excel(output_path,index=False)print(f"{key}:{len(group)}行")