基于OpenPyXL拆分Excel带删除线与无删除线记录至不同文件
解决方案
核心问题分析
- 你碰到的
AttributeError是因为单元格内容可能是普通字符串(str)或富文本对象(RichText),只有RichText才有value属性,普通字符串直接访问会报错,必须先判断类型。 - 拆分富文本的关键是遍历
RichText中的每个run(格式统一的文本段),根据font.strike属性区分带删除线和无删除线的内容。
实现步骤
- 拆分合并单元格:遍历原工作表的所有合并区域,将合并单元格的内容和格式复制到每个拆分后的单元格中。
- 区分富文本内容:
- 对每个单元格,先判断是否为
RichText对象; - 若是,遍历每个
run,按strike属性拆分到两个新的RichText对象中; - 若为普通文本,直接根据单元格字体的
strike属性判断归属。
- 对每个单元格,先判断是否为
- 分别写入输出文件:创建两个新工作簿,将对应内容写入,保留原格式(如删除线)。
完整代码示例
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
相关产品推荐
相关产品推荐

