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

在Linux与MacOS系统下使用Python识别Excel单元格内局部删除线文本的可行方案

在Linux与MacOS系统下使用Python识别Excel单元格内局部删除线文本的可行方案

你遇到的问题其实是两个关键原因导致的:一是CellRichText的元素可能是普通无格式字符串或带格式的文本片段,你没有做类型判断就直接访问font属性;二是代码里的拼写错误——stike应该是strike。我来帮你解决这个问题,同时补充一些更全面的可行思路。

一、修正OpenPyXL代码解决当前报错

首先针对你现有的代码,我们修正类型判断逻辑和拼写错误,就能正常识别带删除线的富文本片段:

from openpyxl import load_workbook
from openpyxl.cell.rich_text import CellRichText, TextBlock

main_xlsx = "test_wb.xlsx"
wb = load_workbook(main_xlsx, rich_text=True)
ws = wb["Sheet1"]

for i in range(1, ws.max_row + 1):
    my_cell = ws[f"C{i}"]  # 用f-string简化单元格坐标拼接
    if isinstance(my_cell.value, CellRichText):
        for part in my_cell.value:
            # 区分普通字符串和带格式的TextBlock片段
            if isinstance(part, TextBlock):
                # 注意拼写修正:是strike不是stike!
                if part.font.strike:
                    print(f"找到带删除线的文本:{part.text}")
            else:
                # 处理无格式的普通文本部分
                print(f"无格式文本片段:{part}")
    else:
        print(f"单元格C{i}:无富文本内容")

代码关键说明:

  1. 类型判断优化:用isinstance()代替type()是Python中更推荐的类型检查方式,能兼容继承场景。
  2. 区分文本片段类型:CellRichText是混合序列,包含普通str(无格式)和TextBlock(带格式)两种元素,必须先判断类型再访问font属性。
  3. 拼写错误修正:你原代码里的stike是拼写错误,正确的属性名是strike,这也是后续即使类型正确也会报错的隐藏问题。

二、报错根源解析

OpenPyXL的CellRichText设计是为了兼容单元格内的混合格式文本:

  • 当单元格内某段文本没有设置任何字体格式时,会被存储为普通str对象;
  • 只有设置了格式(如删除线、加粗、颜色)的文本片段,才会被封装为TextBlock对象,这类对象才有font属性可以访问。

你的原始代码没有区分这两种元素,直接遍历所有元素并访问font,自然会触发str对象无font的AttributeError。

三、进阶方案:直接解析XLSX底层XML

如果OpenPyXL的富文本处理在某些复杂场景下有局限(比如极端格式的单元格),你可以直接操作XLSX的底层XML结构——因为XLSX本质是一个ZIP压缩包,内部包含多个描述内容和格式的XML文件:

实现思路:

  1. 将XLSX文件当作ZIP包解压,读取对应工作表的XML文件(如xl/worksheets/sheet1.xml);
  2. 遍历单元格的<c>元素,找到包含<r>(文本运行片段)的富文本单元格;
  3. 检查每个<r>元素的<rPr>(运行属性)中是否包含<strike/>标签,来判断该片段是否有删除线。

示例代码:

import zipfile
import xml.etree.ElementTree as ET

# 定义XLSX XML的命名空间,必须指定才能正确解析
NS = {
    "ss": "http://schemas.openxmlformats.org/spreadsheetml/2006/main"
}

main_xlsx = "test_wb.xlsx"
with zipfile.ZipFile(main_xlsx, "r") as zf:
    # 读取第一个工作表的XML文件,根据你的实际表名调整路径
    with zf.open("xl/worksheets/sheet1.xml") as f:
        tree = ET.parse(f)
        root = tree.getroot()
        
        # 遍历所有单元格
        for cell in root.findall(".//ss:c", NS):
            cell_ref = cell.attrib.get("r")  # 获取单元格坐标(如C1)
            # 查找单元格内的所有文本运行片段
            runs = cell.findall(".//ss:r", NS)
            if not runs:
                print(f"单元格{cell_ref}:无富文本内容")
                continue
            
            for run in runs:
                # 检查是否存在删除线属性
                strike_tag = run.find(".//ss:strike", NS)
                # 提取该片段的文本内容
                text_content = "".join([t.text for t in run.findall(".//ss:t", NS)])
                if strike_tag is not None:
                    print(f"单元格{cell_ref}中带删除线的文本:{text_content}")
                else:
                    print(f"单元格{cell_ref}中无删除线的文本:{text_content}")

这种方法更底层,能处理所有XLSX支持的格式,但需要熟悉OOXML的结构,适合复杂场景的定制化需求。

四、关于xlrd v1.2的使用建议

你提到的xlrd v1.2确实支持读取XLSX,但该版本已经停止维护,且从xlrd v2.0开始完全移除了XLSX格式的支持,仅兼容旧版XLS文件。除非你必须维护非常老旧的代码环境,否则不推荐在新项目中使用这个版本。


备注:内容来源于stack exchange,提问作者Deficient_brain_words

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 12:59:33