Openpyxl列表词汇文字变色修复:仅最后匹配词变色问题
问题:Excel单元格批量标记指定词汇为红色时仅最后一个词汇生效
需求与问题
需要将Excel单元格文本中属于prev_list列表内的所有词汇设置为红色,但当前代码仅能将最后一个匹配的词汇改为红色。
示例
原句:
I have a dog, a cat and a fish
期望效果(匹配词汇显示为红色):
I have a dog(红色), a cat(红色) and a fish(红色)
实际效果:
I have a dog, a cat and a fish(红色)
错误原因分析
- 变量作用域问题:外层循环检查是否存在匹配词汇时,
word变量最终会停留在prev_list中最后一个匹配的词汇,导致后续re.finditer仅针对该词汇进行查找,忽略了前面的匹配项。 - 富文本构建逻辑错误:每次找到匹配项时,都直接将整个文本拆分为「前缀+红词+后缀」添加到
rich_text中,多次循环后会重复叠加文本,最终只有最后一次的修改覆盖显示。 - 未遍历所有目标词汇:没有对
prev_list中的所有词汇进行全局匹配,仅处理了最后一个匹配的词汇。
修正后的代码
from openpyxl import Workbook from openpyxl.cell.text import InlineFont from openpyxl.cell.rich_text import TextBlock, CellRichText import pandas as pd from openpyxl.utils.dataframe import dataframe_to_rows import re # 读取目标词汇列表 prev_words = pd.read_excel("prev_file.xlsx", usecols=['word']) prev_list = prev_words['word'].tolist() # 构建正则表达式,匹配所有目标词汇(用\b避免部分匹配) pattern = re.compile(r'\b(' + '|'.join(re.escape(word) for word in prev_list) + r')\b') wb = Workbook() ws = wb.active df = pd.read_excel("new_file.xlsx") # 将DataFrame写入工作表 for r in dataframe_to_rows(df, index=False, header=True): ws.append(r) red = InlineFont(color='00FF0000') black = InlineFont(color='00000000') # 遍历所有行(min_row=1跳过表头,根据需求调整) for row in ws.iter_rows(min_row=1): for cell in row: if cell.value is None: continue cell_value = str(cell.value) rich_text = CellRichText() last_end = 0 # 查找所有匹配的目标词汇 for match in pattern.finditer(cell_value): start_idx = match.start() end_idx = match.end() # 添加匹配前的普通文本 if start_idx > last_end: rich_text.append(TextBlock(black, cell_value[last_end:start_idx])) # 添加红色的匹配词汇 rich_text.append(TextBlock(red, cell_value[start_idx:end_idx])) last_end = end_idx # 添加最后一段普通文本 if last_end < len(cell_value): rich_text.append(TextBlock(black, cell_value[last_end:])) # 无匹配时直接添加原文本 if not rich_text: rich_text.append(TextBlock(black, cell_value)) cell.value = rich_text wb.save("resultresult2.xlsx") wb.close()
关键修改点
- 用正则表达式一次性匹配所有目标词汇,避免逐个词汇处理的遗漏问题
- 按文本顺序逐步构建富文本,记录上一次匹配的结束位置,确保片段不重复、不遗漏
- 添加空值判断,避免None值报错
- 使用
\b单词边界,避免把"doggy"这类词中的"dog"误标记
内容的提问来源于stack exchange,提问作者Eve Shin
相关产品推荐
相关产品推荐

