Python完美处理Excel合并单元格(拆分填充+自动合并)的示例详解

 更新时间:2026年07月15日 09:06:42   作者:幸福清风  
还在为Excel合并单元格拆分后数据丢失、样式错乱而烦恼吗,本文分享一套基于openpyxl的无损拆分与智能合并工具,自动填充空缺数据并完整保留字体、边框等样式,实现可逆闭环,彻底解决数据断层问题,让你的表格处理更高效

一、前言:Excel合并单元格的痛点

在日常办公、数据爬虫、数据分析、报表自动化场景中,Excel合并单元格是最让人头疼的格式问题之一。

常见痛点:

  • 合并单元格拆分后数据丢失:openpyxl原生拆分单元格后,只有左上角单元格保留数值,其余单元格为空,导致数据断层、无法用于筛选、匹配数据。
  • 样式错乱:拆分/合并后字体、颜色、边框、对齐方式丢失,报表格式崩坏。
  • 无法可逆操作:拆分后想重新规整合并,没有通用自动化方案,只能手动操作。
  • 批量处理困难:多区域、多行多列合并单元格,人工修改效率极低。

为此,我基于 openpyxl 封装了一套无损、可逆、全覆盖的Excel合并单元格工具:

  • 拆分合并单元格:自动填充全部空缺单元格,保留完整样式
  • 智能合并单元格:按行/按列自动合并相同值、支持指定区域合并
  • 全程保留:字体、填充色、边框、对齐、数字格式
  • 拆分+合并双向联动,完美闭环

二、功能核心优势

  • 真·无损拆分:拆分后原合并区域所有单元格自动填充左上角原值,解决数据空白问题
  • 全样式复刻:逐单元格复制字体、背景填充、边框、对齐、数字格式
  • 三种合并模式:按列纵向合并、按行横向合并、自定义区域合并
  • 可逆闭环逻辑:拆分全填充 → 合并清冗余,和Excel原生逻辑一致
  • 安全不毁源文件:支持覆盖原文件/另存新文件双模式

三、完整工具源码(可直接运行)

依赖安装:

pip install openpyxl

完整工具代码:

from openpyxl import load_workbook
from copy import copy


# ===================== 拆分合并单元格(全区域填充值+保留样式) =====================
def unmerge_merged_cells_fill_all(file_path, sheet_name="Sheet1", output_path=None):
    """
    拆分所有合并单元格,拆分后原合并区域全部填充原左上角值,完整保留样式
    :param file_path: 输入Excel路径
    :param sheet_name: 工作表名称
    :param output_path: 输出路径,默认覆盖原文件
    :return: 处理后文件路径
    """
    # 加载工作簿,保留原格式
    wb = load_workbook(file_path)
    ws = wb[sheet_name]

    # 提前读取所有合并区域(拆分后会丢失合并信息,必须前置读取)
    merged_ranges = list(ws.merged_cells.ranges)
    if not merged_ranges:
        print("未检测到合并单元格,无需处理")
        return file_path

    # 遍历所有合并区域逐一处理
    for m_range in merged_ranges:
        min_row = m_range.min_row
        max_row = m_range.max_row
        min_col = m_range.min_col
        max_col = m_range.max_col

        # 获取左上角值与样式
        top_left_cell = ws.cell(row=min_row, column=min_col)
        top_left_value = top_left_cell.value

        # 拆分单元格
        ws.unmerge_cells(range_string=str(m_range))

        # 全区域填充值 + 复刻样式
        for row in range(min_row, max_row + 1):
            for col in range(min_col, max_col + 1):
                current_cell = ws.cell(row=row, column=col)
                current_cell.value = top_left_value
                # 完整复刻样式
                current_cell.font = copy(top_left_cell.font)
                current_cell.fill = copy(top_left_cell.fill)
                current_cell.border = copy(top_left_cell.border)
                current_cell.alignment = copy(top_left_cell.alignment)
                current_cell.number_format = top_left_cell.number_format

    # 保存文件
    output_path = output_path if output_path else file_path
    wb.save(output_path)
    print(f"✅ 拆分完成!共处理 {len(merged_ranges)} 个合并区域,文件保存至: {output_path}")
    return output_path


# ===================== 按列纵向自动合并相同值 =====================
def merge_cells_by_column(file_path, sheet_name="Sheet1", start_row=1, end_row=None, col=None, output_path=None):
    """
    单列纵向合并:同一列连续相同值自动合并
    """
    wb = load_workbook(file_path)
    ws = wb[sheet_name]
    max_row = ws.max_row if end_row is None else end_row

    merge_blocks = []
    current_start = start_row
    prev_val = ws.cell(row=start_row, column=col).value

    # 扫描连续相同值区块
    for r in range(start_row + 1, max_row + 1):
        curr_val = ws.cell(row=r, column=col).value
        if curr_val != prev_val:
            if current_start != r - 1:
                merge_blocks.append((current_start, col, r - 1, col))
            current_start = r
            prev_val = curr_val
    # 收尾最后一段
    if current_start != max_row:
        merge_blocks.append((current_start, col, max_row, col))

    # 执行合并+样式同步
    for min_r, min_c, max_r, max_c in merge_blocks:
        ws.merge_cells(min_row=min_r, min_col=min_c, max_row=max_r, max_col=max_c)
        top_cell = ws.cell(min_r, min_c)
        for r in range(min_r, max_r + 1):
            for c in range(min_c, max_c + 1):
                if not (r == min_r and c == min_c):
                    cell = ws.cell(r, c)
                    cell.value = None
                    cell.font = copy(top_cell.font)
                    cell.fill = copy(top_cell.fill)
                    cell.border = copy(top_cell.border)
                    cell.alignment = copy(top_cell.alignment)
                    cell.number_format = top_cell.number_format

    save_path = output_path if output_path else file_path
    wb.save(save_path)
    print(f"✅ 列合并完成,共 {len(merge_blocks)} 处合并,保存至:{save_path}")
    return save_path


# ===================== 按行横向自动合并相同值 =====================
def merge_cells_by_row(file_path, sheet_name="Sheet1", start_col=1, end_col=None, row=None, output_path=None):
    """
    单行横向合并:同一行连续相同值自动合并
    """
    wb = load_workbook(file_path)
    ws = wb[sheet_name]
    max_col = ws.max_column if end_col is None else end_col

    merge_blocks = []
    current_start = start_col
    prev_val = ws.cell(row=row, column=start_col).value

    for c in range(start_col + 1, max_col + 1):
        curr_val = ws.cell(row=row, column=c).value
        if curr_val != prev_val:
            if current_start != c - 1:
                merge_blocks.append((row, current_start, row, c - 1))
            current_start = c
            prev_val = curr_val
    if current_start != max_col:
        merge_blocks.append((row, current_start, row, max_col))

    for min_r, min_c, max_r, max_c in merge_blocks:
        ws.merge_cells(min_row=min_r, min_col=min_c, max_row=max_r, max_col=max_c)
        top_cell = ws.cell(min_r, min_c)
        for r in range(min_r, max_r + 1):
            for c in range(min_c, max_c + 1):
                if not (r == min_r and c == min_c):
                    cell = ws.cell(r, c)
                    cell.value = None
                    cell.font = copy(top_cell.font)
                    cell.fill = copy(top_cell.fill)
                    cell.border = copy(top_cell.border)
                    cell.alignment = copy(top_cell.alignment)
                    cell.number_format = top_cell.number_format

    save_path = output_path if output_path else file_path
    wb.save(save_path)
    print(f"✅ 行合并完成,共 {len(merge_blocks)} 处合并,保存至:{save_path}")
    return save_path


# ===================== 自定义区域合并 =====================
def manual_merge_range(file_path, sheet_name="Sheet1", min_r=1, min_c=1, max_r=1, max_c=1, output_path=None):
    """手动指定行列区域合并单元格"""
    wb = load_workbook(file_path)
    ws = wb[sheet_name]
    ws.merge_cells(min_row=min_r, min_col=min_c, max_row=max_r, max_col=max_c)
    top_cell = ws.cell(min_r, min_c)

    for r in range(min_r, max_r + 1):
        for c in range(min_c, max_c + 1):
            if not (r == min_r and c == min_c):
                cell = ws.cell(r, c)
                cell.value = None
                cell.font = copy(top_cell.font)
                cell.fill = copy(top_cell.fill)
                cell.border = copy(top_cell.border)
                cell.alignment = copy(top_cell.alignment)
                cell.number_format = top_cell.number_format

    save_path = output_path if output_path else file_path
    wb.save(save_path)
    print(f"✅ 区域合并完成!({min_r},{min_c})~({max_r},{max_c})")
    return save_path


# ===================== 一键联动:拆分填充 + 重新合并 =====================
if __name__ == "__main__":
    # 配置文件路径
    input_file = r"C:\Users\Administrator\Desktop\cs11.xlsx"
    temp_file = r"C:\Users\Administrator\Desktop\temp_拆分后.xlsx"
    final_file = r"C:\Users\Administrator\Desktop\最终规整表格.xlsx"

    # 1. 先拆分所有合并单元格,填充空白、保留样式
    unmerge_merged_cells_fill_all(input_file, output_path=temp_file)

    # 2. 按需重新合并(示例:对第1列纵向合并相同内容)
    merge_cells_by_column(temp_file, col=1, start_row=1, output_path=final_file)

    # 其他用法可单独调用
    # merge_cells_by_row(input_file, row=2)
    # manual_merge_range(input_file, min_r=2, min_c=1, max_r=5, max_c=3)

四、核心逻辑解析

1. 拆分单元格核心逻辑

很多人直接使用 ws.unmerge_cells() 会出现数据丢失,原因是:openpyxl 拆分后仅左上角单元格保留值

本工具解决方案:

  • 先批量读取所有合并区域(必须拆分前读取,否则丢失记录)
  • 记录每块区域左上角单元格的 值 + 全套样式
  • 执行拆分操作
  • 遍历区域内所有单元格,批量填充值、复刻样式

最终实现:拆分后数据完整、格式不变,可直接用于数据分析

2. 合并单元格核心逻辑

模拟人工规整表格逻辑:

  • 扫描行/列中连续相同的值,自动识别合并区块
  • 执行合并后,仅保留左上角值,其余单元格置空(符合Excel原生合并规则)
  • 同步复刻左上角样式,保证表格美观统一

五、常用调用示例

1. 仅拆分填充所有合并单元格

unmerge_merged_cells_fill_all("test.xlsx", output_path="拆分后.xlsx")

2. 按列自动合并相同内容

# 第2列,从第2行开始纵向合并 merge_cells_by_column("拆分后.xlsx", col=2, start_row=2)

3. 按行自动合并相同内容

# 第3行横向合并 merge_cells_by_row("test.xlsx", row=3)

4. 手动指定区域合并

# 2-5行,1-3列区域合并 manual_merge_range("test.xlsx", min_r=2, min_c=1, max_r=5, max_c=3)

六、适用场景总结

  • 数据清洗:解决合并单元格导致的pandas读取数据错位、空值问题
  • 报表自动化:自动规整Excel表格格式,替代人工合并拆分
  • 批量处理文件:海量Excel文件统一标准化格式
  • 数据可逆处理:拆分填充数据 → 规整合并,实现表格标准化闭环

到此这篇关于Python完美处理Excel合并单元格(拆分填充+自动合并)的示例详解的文章就介绍到这了,更多相关Python Excel单元格合并内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Pandas条件筛选与组合筛选的使用

    Pandas条件筛选与组合筛选的使用

    本文主要介绍了Pandas条件筛选与组合筛选的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-01-01
  • Python3爬虫中Selenium的用法详解

    Python3爬虫中Selenium的用法详解

    在本篇内容里小编给大家分享了关于Python3爬虫中Selenium的用法详解内容,需要的朋友们可以参考下。
    2020-07-07
  • Django Rest Framework实现身份认证源码详解

    Django Rest Framework实现身份认证源码详解

    这篇文章主要为大家介绍了Django Rest Framework实现身份认证源码详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-05-05
  • Python-Flask:动态创建表的示例详解

    Python-Flask:动态创建表的示例详解

    今天小编就为大家分享一篇Python-Flask:动态创建表的示例详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • pycharm+django创建一个搜索网页实例代码

    pycharm+django创建一个搜索网页实例代码

    这篇文章主要介绍了pycharm+django创建一个搜索网页实例代码,分享了相关代码示例,小编觉得还是挺不错的,具有一定借鉴价值,需要的朋友可以参考下
    2018-01-01
  • python实现简单温度转换的方法

    python实现简单温度转换的方法

    这篇文章主要介绍了python实现简单温度转换的方法,涉及Python操作字符串的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-03-03
  • 图文详解感知机算法原理及Python实现

    图文详解感知机算法原理及Python实现

    感知机是二类分类的线性分类模型,其输入为实例的特征向量,输出为实例的类别(取+1和-1二值)。本文将为大家详细讲讲感知机算法的原理及实现,需要的可以参考一下
    2022-08-08
  • Python logging日志模块使用指南

    Python logging日志模块使用指南

    Python 的 logging 模块提供了标准的日志接口,可以通过它存储各种格式的日志,日志记录提供了一组便利功能,用于简单的日志记录用法,本文就给大家简单的介绍一下Python logging日志模块使用方法,需要的朋友可以参考下
    2023-08-08
  • python matplotlib 画dataframe的时间序列图实例

    python matplotlib 画dataframe的时间序列图实例

    今天小编就为大家分享一篇python matplotlib 画dataframe的时间序列图实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • Python实现批量翻译的示例代码

    Python实现批量翻译的示例代码

    这篇文章主要为大家详细介绍了如何利用Python语言实现批量翻译的功能,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下
    2022-09-09

最新评论