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

使用xlrd读取.xls文件单元格内各文本片段的字体颜色与删除线状态的实现问题

使用xlrd读取.xls文件单元格内各文本片段的字体颜色与删除线状态的实现问题

嘿,我懂你的困扰了——你现在用xlrd只能拿到整个单元格的统一格式,但单元格里的文本是分段设置了不同样式的(比如部分文字带删除线、部分是红色),这确实得用到xlrd的富文本(Rich Text)解析功能才能解决。

问题根源

你当前的代码是基于单元格整体的xf_index获取格式的,但.xls文件里的分段格式化文本是按「文本片段(run)」来存储的,每个片段有独立的字体配置。常规的单元格xf格式只对应单元格的默认样式,当单元格内有多个格式不同的文本时,必须解析单元格的富文本信息才能拿到每个片段的具体格式。

解决方案:解析单元格的富文本片段

xlrd其实支持读取单元格的富文本内容,每个单元格的rich_text属性会返回一个列表,列表里的每个元素是(文本内容, 字体索引)的元组:

  • 文本内容:当前片段的具体文字
  • 字体索引:该片段对应的字体配置索引,通过它可以从workbook.font_list里拿到对应的字体样式(颜色、删除线等)

下面是修改后的核心代码,我替换了你原来处理单个单元格的逻辑,加入了富文本解析的部分:

修改后的完整代码示例

import pandas as pd
import numpy as np
import xlrd
import math

# 假设你的get_color_palette和compare_font_color方法已实现
palette = self.get_color_palette(data_path)
workbook = xlrd.open_workbook(data_path, formatting_info=True, on_demand=True)

dfs = {}
for sheet_name in sheet_names:
    print(f'Read sheet: {sheet_name}')
    sheet = workbook.sheet_by_name(sheet_name)
                    
    filtered_data = []
    for row in range(sheet.nrows):
        filtered_row = []
        for col in range(sheet.ncols):
            cell = sheet.cell(row, col)
            # 处理空单元格
            if cell.value == '':
                filtered_row.append(math.nan)
                continue
            
            # 检查单元格是否包含富文本(分段格式化内容)
            if hasattr(cell, 'rich_text') and cell.rich_text:
                # 存储每个文本片段的详细格式信息
                cell_segment_details = []
                for text_segment, font_idx in cell.rich_text:
                    font = workbook.font_list[font_idx]
                    # 判断是否带删除线(和你原逻辑保持一致)
                    is_striked = not font.struck_out
                    # 判断颜色是否符合你的要求
                    color_valid = self.compare_font_color(palette[font.colour_index])
                    # 保存片段的文本和格式信息
                    cell_segment_details.append({
                        'text': text_segment,
                        'is_striked': is_striked,
                        'color_valid': color_valid
                    })
                # 按需组合片段信息,这里示例为带格式标记的字符串
                formatted_cell = ""
                for seg in cell_segment_details:
                    seg_text = seg['text']
                    # 给删除线片段加标记
                    if seg['is_striked']:
                        seg_text = f"<strike>{seg_text}</strike>"
                    # 给符合颜色要求的片段加标记(这里用[red]示例,可按需修改)
                    if seg['color_valid']:
                        seg_text = f"[red]{seg_text}[/red]"
                    formatted_cell += seg_text
                filtered_row.append(formatted_cell)
            else:
                # 无富文本的单元格,沿用你原来的逻辑处理
                xf_index = cell.xf_index
                xf = workbook.xf_list[xf_index]
                font_index = xf.font_index
                font = workbook.font_list[font_index]
                strike_bool = not font.struck_out
                font_color_bool = self.compare_font_color(palette[font.colour_index])
                keep_cell = font_color_bool and strike_bool
                
                # 处理单元格值的类型
                if isinstance(cell.value, (int, float)):
                    if isinstance(cell.value, float) and cell.value.is_integer():
                        filtered_row.append(int(cell.value) if keep_cell else None)
                    else:
                        filtered_row.append(float(cell.value) if keep_cell else None)
                else:
                    filtered_row.append(str(cell.value) if keep_cell else None)
        filtered_data.append(filtered_row)
    
    df_proper = pd.DataFrame(filtered_data)
    dfs[sheet_name] = df_proper
    workbook.unload_sheet(sheet_name)

关键细节说明

  1. 富文本判断:通过hasattr(cell, 'rich_text') and cell.rich_text检查单元格是否包含分段格式化的文本,避免报错。
  2. 遍历文本片段:每个富文本片段对应独立的字体配置,通过字体索引可以精准获取该片段的删除线状态和颜色信息。
  3. 结果存储灵活:你可以根据需求把片段信息组合成带格式标记的字符串(比如示例中的<strike>和[red]),或者直接存储为字典列表,方便后续Pandas的进一步处理。
  4. 兼容普通单元格:对于没有分段格式的单元格,依然沿用你原来的逻辑,保证代码的兼容性。

针对你给出的示例:

单元格内容:That can be not a value

  • "That"是红色(假设你的compare_font_color识别红色为符合条件)
  • "not"是删除线

修改后的代码会把这个单元格处理成[red]That[/red] can be <strike>not</strike> a value的字符串,完美识别每个片段的格式状态。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 18:08:01