Python如何解析xlsx文件获取文本格式样式及起止位置
Python解析xlsx富文本特殊格式实现方案
依赖安装
使用openpyxl库处理xlsx富文本,该库对新版xlsx的块级格式支持完整,不要使用已停止维护的xlrd/xlwt处理此类需求,安装命令:
pip install openpyxl
实现逻辑
xlsx单元格内的差异化格式文本是以**富文本块(TextRun)**为单位存储的,每个连续同格式的字符段对应一个独立文本块,自带完整字体属性(加粗、字号、颜色等)。实现步骤:
- 先读取无任何特殊格式的第四句内容,提取默认字体属性作为对比基准
- 逐行遍历目标单元格的富文本块,累加字符长度计算每个块的起止字符位置
- 对比每个文本块的字体属性和基准属性,存在差异的块就记录位置、差异属性值
可直接运行的代码
from openpyxl import load_workbook from openpyxl.cell.rich_text import CellRichText, TextBlock from openpyxl.cell.text import InlineFont def parse_special_format_xlsx(file_path: str, target_sheet: str, target_cell_range: list[str]): """ 解析xlsx中带特殊格式的文本 :param file_path: xlsx文件路径 :param target_sheet: 要读取的工作表名 :param target_cell_range: 四个语句所在的单元格坐标列表,顺序按[第一句,第二句,第三句,第四句]传入,比如["A1","A2","A3","A4"] :return: 每个单元格的特殊格式结果列表 """ wb = load_workbook(file_path, rich_text=True, data_only=True) ws = wb[target_sheet] # 取第四句的格式作为基准 base_cell = ws[target_cell_range[3]] base_font = None if isinstance(base_cell.value, CellRichText): for block in base_cell.value: if isinstance(block, TextBlock): base_font = block.font break else: # 普通无富文本单元格直接取单元格字体属性 base_font = InlineFont( bold=base_cell.font.bold, sz=base_cell.font.sz, color=base_cell.font.color ) res = [] # 遍历四个目标单元格 for cell_addr in target_cell_range: cell = ws[cell_addr] cell_val = cell.value cell_result = { "cell": cell_addr, "full_text": "", "special_formats": [] } current_pos = 0 # 处理富文本单元格 if isinstance(cell_val, CellRichText): full_text = "" for block in cell_val: # 普通无格式字符串段 if isinstance(block, str): block_len = len(block) full_text += block current_pos += block_len continue # 带独立格式的文本块 block_text = block.text block_len = len(block_text) start_pos = current_pos end_pos = current_pos + block_len full_text += block_text # 对比和基准格式的差异 font_diff = {} if block.font.bold != base_font.bold: font_diff["bold"] = block.font.bold if block.font.sz != base_font.sz: font_diff["font_size_pt"] = block.font.sz # 对比字体颜色 block_color = block.font.color.rgb if block.font.color else None base_color = base_font.color.rgb if base_font.color else None if block_color != base_color: font_diff["font_color_rgb"] = block_color # 存在格式差异则记录 if font_diff: cell_result["special_formats"].append({ "start_char_index": start_pos, "end_char_index": end_pos, "text": block_text, "format_attrs": font_diff }) current_pos = end_pos cell_result["full_text"] = full_text else: # 无富文本的普通单元格直接存储全量文本 cell_result["full_text"] = str(cell_val) res.append(cell_result) wb.close() return res # 调用示例 if __name__ == "__main__": result = parse_special_format_xlsx( file_path="你的文件路径.xlsx", target_sheet="Sheet1", target_cell_range=["A1","A2","A3","A4"] # 按实际四个句子所在单元格坐标修改 ) for item in result: print(f"单元格{item['cell']} 全量文本:{item['full_text']}") for fmt in item["special_formats"]: print(f" 特殊文本:{fmt['text']},起止位置:{fmt['start_char_index']}-{fmt['end_char_index']},格式属性:{fmt['format_attrs']}")
返回结果说明
- 字符索引默认从0开始计数,和Python字符串切片规则一致
- 格式属性仅返回和常规格式有差异的字段:
- 加粗文本会返回
"bold": True - 红色文本会返回对应ARGB值,比如纯红色对应
"font_color_rgb": "FFFF0000" - 大字号文本会返回对应字号值,比如16磅字号对应
"font_size_pt": 16
- 加粗文本会返回
- 无特殊格式的第四句返回结果里
special_formats为空列表
注意事项
- 加载工作簿必须加
rich_text=True参数,否则openpyxl会自动把富文本转成普通字符串,丢失所有块级格式信息 - openpyxl读取的字号单位为磅(pt),如果需要换算为px可按
1pt ≈ 1.333px计算 - 如果需要识别单元格背景高亮、删除线、斜体等其他格式,可在代码的格式对比逻辑中扩展对应属性的判断即可
内容的提问来源于stack exchange,提问作者user238664
相关产品推荐
相关产品推荐

