
本文介绍通过改用 ws.iter_rows() 迭代器替代逐单元格索引访问,将 10 万行 Excel 条件着色耗时从 30 分钟以上降至约 2 秒的核心优化方法,并提供可直接运行的高效代码示例。
本文介绍通过改用 `ws.iter_rows()` 迭代器替代逐单元格索引访问,将 10 万行 excel 条件着色耗时从 30 分钟以上降至约 2 秒的核心优化方法,并提供可直接运行的高效代码示例。
在使用 openpyxl 对大型 Excel 表格进行条件格式化(如按列值批量填充行背景色)时,常见误区是依赖 ws.cell(row=row_idx, column=col_idx) 这类随机访问方式——它在内部会触发大量对象创建与坐标解析,导致性能急剧下降。尤其当处理 10 万行数据时,原始代码因反复调用 ws.cell() 和 ws[row_idx] 切片,实际执行时间可能超过 30 分钟。
根本优化思路:避免索引访问,改用原生迭代器
openpyxl 提供了高效的只读/读写迭代接口,其中 ws.iter_rows() 是最佳选择:它以行为单位返回 tuple[Cell],无需重复解析行列坐标,内存友好且速度极快。配合 Python 3.8+ 的海象运算符 :=,还可进一步精简逻辑判断。
以下是优化后的完整实现(已实测在 Apple M2 + Python 3.13 + openpyxl 3.1.5 下仅需约 2 秒):
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)
# 写入 10 万行示例数据(保持不变)
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}")
# 预定义样式(注意:PatternFill 可复用,无需每行新建)
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")
}
bold_font = Font(bold=True) # 复用 Font 实例,避免重复创建
# ✅ 关键优化:使用 iter_rows() + 直接解包
start = time.perf_counter()
for row in ws.iter_rows(min_row=2): # 跳过表头,从第2行开始
type_cell = row[1] # 第2列(索引1),即 "Type" 列
if (fill := fills.get(type_cell.value)) is not None:
for cell in row:
cell.fill = fill
cell.font = bold_font
print(f"✅ 优化后运行时间: {time.perf_counter() - start:.2f} 秒")
wb.save("output_optimized.xlsx")
关键注意事项与进阶建议:
-
样式复用至关重要:
PatternFill和Font是轻量对象,但频繁实例化仍会增加开销。务必在循环外预先定义并复用。 -
避免
ws[row_idx]切片:该操作底层仍会遍历整行生成新元组,不如iter_rows()直接。 -
大数据量时考虑
write_only=True模式:若仅需写入(无需读取已有内容),可创建Workbook(write_only=True),配合ws.append()批量写入 +ws._cells预设样式,性能可再提升 20–30%。 -
不推荐多线程加速:
openpyxl非线程安全,ThreadPoolExecutor在此场景不仅无效,还可能引发异常或样式错乱。 -
替代方案参考:若纯条件着色是唯一需求,可考虑
pandas+xlsxwriter(支持高效条件格式 API),但会失去 openpyxl 的精细单元格控制能力。
综上,将 ws.cell() 或 ws[row][col] 替换为 ws.iter_rows() 是 openpyxl 大表样式处理最立竿见影的性能优化手段——无需引入新依赖,代码更简洁,速度提升可达百倍级。











