如何加速Python实现Excel表格的条件单元格高亮?
提升Excel条件着色Python代码运行速度的实用方案
你的代码慢的核心原因是openpyxl逐单元格设置样式的开销极大——10万行×3列就是30万次单元格操作,每个操作都会触发内部对象更新,自然耗时惊人。下面是几个能大幅提速的方法:
方法1:用openpyxl内部样式数组批量修改(无需换库)
openpyxl有隐藏的_style_array接口,可以直接操作样式数组,避免逐单元格修改,能把速度提升几十倍。
修改后的代码:
import openpyxl from openpyxl.styles import PatternFill, Font import time # 创建示例数据(和原代码一致) wb = openpyxl.Workbook() ws = wb.active headers = ["ID", "Type", "Value"] for col, header in enumerate(headers, 1): ws.cell(row=1, column=col, value=header) for row in range(2, 100002): ws.cell(row=row, column=1, value=row-1) ws.cell(row=row, column=2, value="Type 1" if row % 3 == 0 else "Type 2" if row % 3 == 1 else "Type 3") ws.cell(row=row, column=3, value=f"Value {row-1}") # 预定义样式,字体只创建一次 bold_font = Font(bold=True) fills = { "Type 1": PatternFill(start_color="FFF2CC", end_color="FFF2CC", fill_type="solid"), "Type 2": PatternFill(start_color="DBEEF4", end_color="DBEEF4", fill_type="solid"), "Type 3": PatternFill(start_color="FFC0CB", end_color="FFC0CB", fill_type="solid") } start = time.perf_counter() # 获取工作表的样式数组 ws_style = ws._style_array col_count = len(headers) for row_idx in range(2, ws.max_row + 1): category = ws.cell(row=row_idx, column=2).value fill = fills.get(category) if fill: # 计算当前行在样式数组中的起始索引 row_start = (row_idx - 1) * col_count # 批量修改当前行所有单元格的样式 for col in range(col_count): style_idx = row_start + col new_style = ws_style[style_idx].copy(fill=fill, font=bold_font) ws_style[style_idx] = new_style # 更新工作表样式 ws._style_array = ws_style print(f"运行耗时: {time.perf_counter() - start:.2f} 秒") wb.save("output.xlsx")
方法2:换用Pandas+XlsxWriter(速度最快)
如果可以切换库,Pandas配合XlsxWriter是处理大表格样式的最优解——它支持直接通过条件格式整行着色,不需要遍历任何单元格,速度能提升上百倍。
示例代码:
import pandas as pd import time start = time.perf_counter() # 生成示例数据 data = [] for row in range(1, 100001): type_val = "Type 1" if row % 3 == 0 else "Type 2" if row % 3 == 1 else "Type 3" data.append({"ID": row, "Type": type_val, "Value": f"Value {row}"}) df = pd.DataFrame(data) # 用XlsxWriter写入Excel writer = pd.ExcelWriter("output_pandas.xlsx", engine="xlsxwriter") df.to_excel(writer, sheet_name="Sheet1", index=False) workbook = writer.book worksheet = writer.sheets["Sheet1"] # 定义三种格式 format_type1 = workbook.add_format({"bg_color": "#FFF2CC", "bold": True}) format_type2 = workbook.add_format({"bg_color": "#DBEEF4", "bold": True}) format_type3 = workbook.add_format({"bg_color": "#FFC0CB", "bold": True}) # 应用整行条件格式:根据B列的值匹配样式 worksheet.conditional_format(1, 0, df.shape[0], df.shape[1]-1, { "type": "formula", "criteria": '=$B2="Type 1"', "format": format_type1 }) worksheet.conditional_format(1, 0, df.shape[0], df.shape[1]-1, { "type": "formula", "criteria": '=$B2="Type 2"', "format": format_type2 }) worksheet.conditional_format(1, 0, df.shape[0], df.shape[1]-1, { "type": "formula", "criteria": '=$B2="Type 3"', "format": format_type3 }) writer.close() print(f"运行耗时: {time.perf_counter() - start:.2f} 秒")
方法3:小优化(不换库不改逻辑)
如果暂时不想改大结构,至少把重复创建的Font对象抽出来复用——原代码每次循环都创建Font(bold=True),会产生大量冗余对象,拖慢速度:
修改原代码的循环部分:
# 提前创建字体对象,只创建一次 bold_font = Font(bold=True) for row_idx in range(2, ws.max_row + 1): category = ws.cell(row=row_idx, column=2).value fill = fills.get(category) if fill: for cell in ws[row_idx]: cell.fill = fill cell.font = bold_font # 复用预创建的对象
内容的提问来源于stack exchange,提问作者user321627
相关产品推荐
相关产品推荐

