You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于OpenPyXL拆分Excel带删除线与无删除线记录至不同文件

解决方案

核心问题分析

  • 你碰到的AttributeError是因为单元格内容可能是普通字符串(str)或富文本对象(RichText),只有RichText才有value属性,普通字符串直接访问会报错,必须先判断类型。
  • 拆分富文本的关键是遍历RichText中的每个run(格式统一的文本段),根据font.strike属性区分带删除线和无删除线的内容。

实现步骤

  1. 拆分合并单元格:遍历原工作表的所有合并区域,将合并单元格的内容和格式复制到每个拆分后的单元格中。
  2. 区分富文本内容:
    • 对每个单元格,先判断是否为RichText对象;
    • 若是,遍历每个run,按strike属性拆分到两个新的RichText对象中;
    • 若为普通文本,直接根据单元格字体的strike属性判断归属。
  3. 分别写入输出文件:创建两个新工作簿,将对应内容写入,保留原格式(如删除线)。

完整代码示例

from openpyxl import load_workbook, Workbook
from openpyxl.cell.text import RichText
from openpyxl.styles import Font

def split_merged_cells(ws):
    # 拆分合并单元格,将内容填充到每个单元格
    merged_cells = list(ws.merged_cells)
    for merged_range in merged_cells:
        min_col, min_row, max_col, max_row = merged_range.bounds
        # 获取合并单元格的内容和格式
        top_cell = ws.cell(row=min_row, column=min_col)
        cell_value = top_cell.value
        cell_font = top_cell.font
        # 取消合并
        ws.unmerge_cells(str(merged_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 = cell_value
                current_cell.font = cell_font

def split_strikethrough_content(input_file, output_no_strike, output_strike):
    # 加载原工作簿
    wb = load_workbook(input_file)
    ws = wb.active

    # 拆分合并单元格
    split_merged_cells(ws)

    # 创建两个输出工作簿
    wb_no_strike = Workbook()
    ws_no_strike = wb_no_strike.active
    wb_strike = Workbook()
    ws_strike = wb_strike.active

    # 遍历原工作表的所有单元格
    for row in ws.iter_rows(values_only=False):
        # 为两个输出表创建对应行
        row_no_strike = []
        row_strike = []
        for cell in row:
            # 处理无删除线内容
            no_strike_rt = RichText()
            # 处理带删除线内容
            strike_rt = RichText()

            if isinstance(cell.value, RichText):
                # 处理富文本单元格
                for run in cell.value:
                    run_font = run.font
                    if run_font.strike:
                        # 带删除线的run加入strike_rt
                        strike_rt.append(run)
                    else:
                        # 无删除线的run加入no_strike_rt
                        no_strike_rt.append(run)
                # 如果no_strike_rt有内容,就赋值,否则留空
                row_no_strike.append(no_strike_rt if len(no_strike_rt) else None)
                row_strike.append(strike_rt if len(strike_rt) else None)
            else:
                # 处理普通文本单元格
                cell_value = cell.value
                if cell.font.strike:
                    row_no_strike.append(None)
                    # 保留删除线格式
                    strike_cell = ws_strike.cell(row=cell.row, column=cell.column)
                    strike_cell.value = cell_value
                    strike_cell.font = Font(strike=True)
                    row_strike.append(cell_value)
                else:
                    row_strike.append(None)
                    no_strike_cell = ws_no_strike.cell(row=cell.row, column=cell.column)
                    no_strike_cell.value = cell_value
                    no_strike_cell.font = cell.font
                    row_no_strike.append(cell_value)
        # 将行写入输出表
        ws_no_strike.append(row_no_strike)
        ws_strike.append(row_strike)

    # 保存文件
    wb_no_strike.save(output_no_strike)
    wb_strike.save(output_strike)

# 使用示例
split_strikethrough_content("input.xlsx", "无删除线记录.xlsx", "带删除线记录.xlsx")

代码说明

  • split_merged_cells函数负责拆分合并单元格,确保每个单元格都有独立的内容和格式;
  • 遍历单元格时,通过isinstance(cell.value, RichText)判断是否为富文本,避免AttributeError;
  • 对富文本的每个run单独判断删除线属性,分别收集到对应富文本对象中,保留原格式;
  • 普通文本单元格直接根据字体的strike属性判断归属,并保留格式写入对应文件。

内容的提问来源于stack exchange,提问作者Roshan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 18:40:14