查看: 144|回复: 3

Python openpyxl拆分合并单元格并自动填充原左上角数据

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
日常处理Excel报表时,合并单元格往往导致数据导出后仅左上角有值,其余单元格为空,严重影响后续统计、匹配和数据库导入。手动拆分单元格并逐一填充不仅效率低,还容易破坏原有样式。本文介绍一个基于openpyxl的Python脚本,能自动读取所有合并区域,拆分后统一填充原左上角数值,并同步复制字体、边框、填充色、对齐等样式,无需二次手动调整。

一、环境依赖

本脚本仅依赖openpyxl库,用于读写.xlsx格式的Excel文件。安装命令如下:
  1. pip install openpyxl
复制代码

二、完整可运行代码
  1. from openpyxl import load_workbook
  2. from copy import copy
  3. def unmerge_merged_cells_fill_all(file_path, sheet_name="Sheet1", output_path=None):
  4.     """
  5.     Excel拆分合并单元格,拆分后原合并区域的所有单元格全部填充原左上角的值
  6.     :param file_path: str 输入Excel文件完整路径
  7.     :param sheet_name: str 目标工作表名称,默认Sheet1
  8.     :param output_path: str 输出文件路径,不传则直接覆盖原文件
  9.     :return: str 处理完成后的文件路径
  10.     """
  11.     # 1. 加载工作簿,保留表格原有全部格式样式
  12.     wb = load_workbook(file_path)
  13.     ws = wb[sheet_name]
  14.     # 2. 提前读取所有合并单元格区域(关键:拆分后无法获取合并范围,必须先缓存)
  15.     merged_ranges = list(ws.merged_cells.ranges)
  16.     if not merged_ranges:
  17.         print("当前工作表未检测到任何合并单元格,无需执行处理")
  18.         return
  19.     # 3. 循环处理每一块合并区域
  20.     for m_range in merged_ranges:
  21.         # 获取合并区域边界:起始行、结束行、起始列、结束列
  22.         min_row = m_range.min_row
  23.         max_row = m_range.max_row
  24.         min_col = m_range.min_col
  25.         max_col = m_range.max_col
  26.         # 获取合并区域左上角单元格与原始数值
  27.         top_left_cell = ws.cell(row=min_row, column=min_col)
  28.         top_left_value = top_left_cell.value
  29.         # 拆分当前合并单元格
  30.         ws.unmerge_cells(range_string=str(m_range))
  31.         # 遍历原合并区域内所有单元格,统一填充左上角值并复制样式
  32.         for row in range(min_row, max_row + 1):
  33.             for col in range(min_col, max_col + 1):
  34.                 current_cell = ws.cell(row=row, column=col)
  35.                 # 填充数值
  36.                 current_cell.value = top_left_value
  37.                 # 复制左上角单元格全套样式,保证表格美观不混乱
  38.                 current_cell.font = copy(top_left_cell.font)
  39.                 current_cell.fill = copy(top_left_cell.fill)
  40.                 current_cell.border = copy(top_left_cell.border)
  41.                 current_cell.alignment = copy(top_left_cell.alignment)
  42.                 current_cell.number_format = top_left_cell.number_format
  43.     # 4. 文件保存逻辑
  44.     if output_path is None:
  45.         output_path = file_path
  46.     wb.save(output_path)
  47.     print(f"处理完成!共拆分 {len(merged_ranges)} 个合并单元格区域,文件保存路径:{output_path}")
  48.     return output_path
  49. if __name__ == "__main__":
  50.     # Windows本地文件路径,r字符串避免转义符报错
  51.     input_file = r"C:\Users\Administrator\Desktop\cs11.xlsx"
  52.     # 方式1:直接覆盖原文件
  53.     unmerge_merged_cells_fill_all(input_file)
  54.     # 方式2:生成新文件,不修改原文件(取消注释使用)
  55.     # new_file = r"C:\Users\Administrator\Desktop\cs11_处理后.xlsx"
  56.     # unmerge_merged_cells_fill_all(input_file, output_path=new_file)
复制代码

三、核心逻辑解析

1. 预读所有合并区域

openpyxl在执行unmerge_cells后,工作表的合并记录会被移除,因此必须先通过ws.merged_cells.ranges将全部合并区域缓存到列表中。这一步是保证循环能够正确遍历所有区域的基石。

2. 获取左上角数据与样式

每个合并区域仅左上角单元格存有原始值,其余均为None。脚本在拆分前读取该单元格的value及font、fill、border、alignment、number_format等样式对象,作为后续填充的模板。

3. 拆分与批量填充

调用ws.unmerge_cells释放合并后,使用双重for循环遍历原区域所有单元格,统一写入先前缓存的左上角值,并通过copy()复制全套样式。

4. 样式同步的细节

使用copy()而非直接赋值,避免多个单元格引用同一个样式对象导致后续修改相互影响。支持的样式属性包括字体、填充、边框、对齐和数字格式,覆盖了日常报表所需的所有视觉要素。

四、两种使用方式

方式1:覆盖原文件

不指定output_path参数,处理后的结果直接写入原文件,适合不想产生额外文件的场景。
  1. input_file = r"C:\Users\Administrator\Desktop\cs11.xlsx"
  2. unmerge_merged_cells_fill_all(input_file)
复制代码

方式2:输出新文件,保留原始数据

通过output_path指定新路径,原文件不受影响,适合需要备份原始报表或对比处理前后结果的场景。
  1. input_file = r"C:\Users\Administrator\Desktop\cs11.xlsx"
  2. output_file = r"C:\Users\Administrator\Desktop\cs11_拆分填充后.xlsx"
  3. unmerge_merged_cells_fill_all(input_file, output_path=output_file)
复制代码

五、适用场景与扩展思路

适用场景:
- 生产月度汇总表、年度统计报表(常有多行多列合并);
- 财务台账、项目台账导出后的数据清洗;
- 数据导入数据库前的预处理,消除空白单元格以避免空值干扰;
- 配合pandas读取Excel前的规整步骤,确保数据完整。

扩展改造思路:
- 结合pandas向右填充:拆分后,可按年月分区对右侧连续空白进行填充;
- 批量处理文件夹:配合os模块遍历所有.xlsx文件;
- 过滤指定工作表:增加跳过逻辑,仅处理名称匹配的Sheet;
- 输出处理日志:记录每个文件拆分的合并区域数量,方便回溯。

六、常见问题

1. 路径报错:Windows路径中的反斜杠需要转义,建议在字符串前加r,如r"C:\...";或使用正斜杠。
2. 文件被占用:Excel打开时会锁定文件,运行脚本前请关闭相关Excel文件。
3. 不支持.xls:openpyxl仅支持.xlsx格式,旧版.xls文件需先用Excel另存为.xlsx。
4. 无合并单元格:脚本会自动检测并直接返回,不会生成空文件或报错。

总结:本脚本通过openpyxl实现了合并单元格的自动化拆分与数据样式填充,几十行代码即可替代大量手动操作,适用于各类Excel报表的日常处理。代码封装完整、注释清晰,可直接复制使用,也易于根据实际需求二次扩展。
回复

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python openpyxl拆分合并单元格并自动填充原左上角数据

感谢分享,正好最近在处理一批合并单元格的报表,每次手动拆分太痛苦了。这个脚本把拆、填、样式复制一步到位,而且代码结构很清晰,缓存合并区域再遍历填充的思路很实用。周末试跑一下看看效果,希望以后导出数据能少踩几个坑。
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python openpyxl拆分合并单元格并自动填充原左上角数据

感谢分享,这个脚本很实用!平时处理报表确实经常遇到合并单元格导致数据缺失的问题,手动处理又慢又容易出错。你这段代码逻辑清晰,尤其是先缓存合并区域再拆分,避免循环时丢失范围,这个细节很关键。另外还复制了样式,省去了后续格式调整的麻烦。我打算直接拿去试试,正好手头有份类似的表格要处理。一个小建议:如果合并区域里左上角本身是空值,填充后会不会保留空?或者可以加个参数控制是否跳过空值填充?不过目前这个版本已经足够满足大部分场景了。再次感谢!
回复 支持 反对

使用道具 举报

发表于 2 小时前 | 显示全部楼层

Re: Python openpyxl拆分合并单元格并自动填充原左上角数据

这篇分享非常实用,很多人在处理Excel报表时确实会被合并单元格坑到——数据导出后大量空白,手工填充又容易出错。你的脚本思路清晰,先缓存合并区域再挨个拆分并复制样式,考虑得很周全,尤其是复制字体、边框、对齐等样式这一点,避免了拆分后表格变乱。另外,代码里加了判断“若无合并直接返回”也很贴心,通用性更强。 一个小建议:如果文件中存在多级嵌套合并(比如大合并里套小合并),当前逻辑是按缓存列表顺序逐个处理,可能会出现拆分后部分区域又被后续合并影响的情况。不过常见报表一般不会有复杂嵌套,日常用你这个脚本完全够用。 感谢分享,收藏备用!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-7-15 11:28 , Processed in 0.025656 second(s), 17 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部