影刀RPA Excel合并单元格处理:读取与写入 影刀RPA Excel合并单元格处理读取与写入署名林焱什么情况用什么做RPA数据采集时经常遇到合并单元格的Excel表格——表头跨列合并、某些数据行合并了相同值。这种表格读取时只有左上角单元格有值其他都是None导致批量处理时数据丢失。场景推荐方式读取合并单元格填充空值Python openpyxl遍历合并区域写入合并单元格Python openpyxl merge_cells取消合并并向下填充Python openpyxl unmerge 填充怎么做一读取合并单元格的值importopenpyxl wbopenpyxl.load_workbook(rD:\报表\区域销售.xlsx)wswb[Sheet1]# 方法1遍历所有合并区域填充空单元格merged_rangeslist(ws.merged_cells.ranges)# 获取所有合并区域formerged_rangeinmerged_ranges:# 获取合并区域左上角的值top_left_valuews.cell(rowmerged_range.min_row,columnmerged_range.min_col).value# 把值填充到合并区域内所有单元格forrowinrange(merged_range.min_row,merged_range.max_row1):[video(video-7LLD9jRW-1783500652180)(type-csdn)(url-https://live.csdn.net/v/embed/525010)(image-https://v-blog.csdnimg.cn/asset/f4faa587144cb7070f19e8b36813806b/cover/Cover0.jpg)(title-店群矩阵自动化突破运营极限)]forcolinrange(merged_range.min_col,merged_range.max_col1):ws.cell(rowrow,columncol).valuetop_left_value# 现在可以正常遍历读取了forrowinrange(2,ws.max_row1):regionws.cell(rowrow,column1).value# 之前合并的单元格现在每行都有值productws.cell(rowrow,column2).value salesws.cell(rowrow,column3).valueprint(f{region}|{product}|{sales})wb.save(rD:\报表\区域销售_填充.xlsx)二写入合并单元格importopenpyxlfromopenpyxl.stylesimportAlignment wbopenpyxl.Workbook()wswb.active ws.title汇总表# 写入表头ws.cell(row1,column1).value区域ws.cell(row1,column2).value产品ws.cell(row1,column3).value销售额# 合并A1:A3区域列合并3行ws.merge_cells(A1:A3)# 合并后的值取左上角ws.cell(row1,column1).value华东区# 设置居中对齐ws.cell(row1,column1).alignmentAlignment(horizontalcenter,verticalcenter)# 写入其他数据data[(产品A,1000),(产品B,2000),(产品C,1500),]fori,(product,sales)inenumerate(data):ws.cell(rowi1,column2).valueproduct ws.cell(rowi1,column3).valuesales wb.save(rD:\报表\合并示例.xlsx)三取消合并并向下填充importopenpyxl wbopenpyxl.load_workbook(rD:\报表\区域销售.xlsx)wswb[Sheet1]# 获取所有合并区域要先拷贝因为取消合并时会修改原列表merged_rangeslist(ws.merged_cells.ranges)formerged_rangeinmerged_ranges:min_rowmerged_range.min_row max_rowmerged_range.max_row min_colmerged_range.min_col# 获取左上角值valuews.cell(rowmin_row,columnmin_col).value# 取消合并ws.unmerge_cells(str(merged_range))# 向下填充所有行forrowinrange(min_row,max_row1):ws.cell(rowrow,columnmin_col).valuevalue wb.save(rD:\报表\区域销售_拆分.xlsx)完整流程合并单元格报表转换importopenpyxlfromopenpyxl.stylesimportAlignment,Font# yd_input: input_path, output_pathinput_pathyd_input.get(input_path,rD:\报表\原始报表.xlsx)output_pathyd_input.get(output_path,rD:\报表\标准报表.xlsx)wbopenpyxl.load_workbook(input_path)wswb.active# 第一步取消所有合并单元格并填充merged_rangeslist(ws.merged_cells.ranges)formerged_rangeinmerged_ranges:min_rowmerged_range.min_row max_rowmerged_range.max_row min_colmerged_range.min_col max_colmerged_range.max_col valuews.cell(rowmin_row,columnmin_col).value ws.unmerge_cells(str(merged_range))# 填充所有单元格forrowinrange(min_row,max_row1):forcolinrange(min_col,max_col1):ws.cell(rowrow,columncol).valuevalue# 第二步读取数据到列表headers[]forcolinrange(1,ws.max_column1):headers.append(ws.cell(row1,columncol).value)data[]forrowinrange(2,ws.max_row1):row_data{}forcolinrange(1,ws.max_column1):row_data[headers[col-1]]ws.cell(rowrow,columncol).value data.append(row_data)# 第三步写入标准格式无合并wb2openpyxl.Workbook()ws2wb2.active ws2.title数据# 写表头header_fontFont(boldTrue)forcol,hinenumerate(headers,1):cellws2.cell(row1,columncol)cell.valueh cell.fontheader_font cell.alignmentAlignment(horizontalcenter)# 写数据forrow_idx,row_datainenumerate(data,2):forcol_idx,hinenumerate(headers,1):ws2.cell(rowrow_idx,columncol_idx).valuerow_data.get(h)# 自动列宽forcolinrange(1,len(headers)1):max_lenlen(str(headers[col-1]or))forrowinrange(2,len(data)2):valws2.cell(rowrow,columncol).valueifval:max_lenmax(max_len,len(str(val)))ws2.column_dimensions[openpyxl.utils.get_column_letter(col)].widthmax_len4wb2.save(output_path)yd_output{status:ok,rows:len(data),cols:len(headers)}有什么坑坑一读取合并单元格时除左上角外全是None现象一个合并了A1:A5的单元格读取A2、A3、A4、A5都返回None。原因Excel合并单元格只在左上角存储值其他位置在底层XML中不存储数据。openpyxl忠实反映了这个结构。解决读取前先填充或者封装一个安全读取函数defsafe_read(ws,row,col,merged_rangesNone):安全读取单元格值处理合并单元格ifmerged_rangesisNone:merged_rangesws.merged_cells.ranges valuews.cell(rowrow,columncol).valueifvalueisnotNone:returnvalue# 检查是否在某个合并区域内formerged_rangeinmerged_ranges:if(merged_range.min_rowrowmerged_range.max_rowandmerged_range.min_colcolmerged_range.max_col):returnws.cell(rowmerged_range.min_row,columnmerged_range.min_col).valuereturnvalue# None坑二取消合并时报错cell not in merged range现象调用unmerge_cells时抛出异常。原因遍历ws.merged_cells.ranges时取消合并导致列表在遍历过程中被修改。解决先拷贝列表再遍历temu店群自动化报活动案例# 错误遍历同时修改# for mr in ws.merged_cells.ranges:# ws.unmerge_cells(str(mr)) ❌ 运行中修改了ranges# 正确先转成列表拷贝merged_rangeslist(ws.merged_cells.ranges)formrinmerged_ranges:ws.unmerge_cells(str(mr))坑三合并单元格后排序导致数据错乱现象合并了A1:A3“华东区”然后对数据排序合并区域没有跟着移动导致区域和数据错位。原因Excel排序时合并单元格不会自动调整排序后合并区域位置不变但数据行变了。解决排序前先取消所有合并排序后再按需要重新合并# 1. 取消合并并填充merged_rangeslist(ws.merged_cells.ranges)formrinmerged_ranges:valws.cell(rowmr.min_row,columnmr.min_col).value ws.unmerge_cells(str(mr))forrinrange(mr.min_row,mr.max_row1):ws.cell(rowr,columnmr.min_col).valueval# 2. 读取数据data[]forrowinrange(2,ws.max_row1):data.append([ws.cell(rowrow,columnc).valueforcinrange(1,ws.max_column1)])![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/63b5139ba6994d4ab0b9f7c8dd27cfad.png#pic_center)# 3. 排序按第3列降序data.sort(keylambdax:x[2]or0,reverseTrue)# 4. 写回fori,row_datainenumerate(data,2):forj,valinenumerate(row_data,1):ws.cell(rowi,columnj).valueval# 5. 如果需要重新合并相同值的连续行# 根据具体需求实现坑四写入合并单元格时只设置左上角样式不够现象合并了一行5列做标题设置了左上角单元格居中但打开Excel后发现文字偏左。原因合并单元格的样式需要所有单元格都设置才能正确显示。只设置左上角在某些Excel版本中不生效。解决遍历合并区域所有单元格设置样式fromopenpyxl.stylesimportAlignment,Font# 合并ws.merge_cells(A1:E1)# 设置所有单元格样式forcolinrange(1,6):![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/76ddb9aaca374202ae5eac18d1dee66a.png#pic_center)![在这里插入图片描述](https://i-blog.csdnimg.cn/direct/415befd8a1f846479c28859078dbab1e.png#pic_center)cellws.cell(row1,columncol)cell.alignmentAlignment(horizontalcenter,verticalcenter)cell.fontFont(boldTrue,size14)# 设置值ws.cell(row1,column1).value2024年度销售汇总