Openpyxl遍历大Excel文件:指定列匹配取值及性能优化问询
解决openpyxl读取大Excel的精准列定位与性能问题
嗨,我来帮你搞定这个问题!你的代码里有几个小问题,而且针对9万行的大表格,我们还得优化性能,不然确实会慢到让人崩溃。
先修正代码里的基础错误
你原来的代码有两个明显的语法/逻辑问题:
- 外层循环变量是
y_row,但内层循环却用了未定义的row,变量名不匹配会直接报错 if cell.value == "Y"后面缺了冒号:,这是Python语法的基本要求
精准指向B列(第2列)的方法
要直接定位到B列的单元格,完全没必要嵌套循环遍历每行的所有单元格——既浪费时间又容易出错。这里有两种高效的方式:
方式1:利用单元格元组的索引
iter_rows返回的每一行是一个单元格元组,B列是第2列,对应元组里的索引是1(因为Python是0开始索引)。我们可以直接取每行的第2个元素:
for row in sheet.iter_rows(min_row=1, max_row=sheet.max_row): # 直接获取B列的单元格(索引1) b_cell = row[1] if b_cell.value == "Y": # 假设code列是第N列,比如是第5列就用row[4] code_value = row[code_column_index].value # 执行你的业务函数 your_target_function(code_value)
方式2:通过列名直接获取(更直观)
如果你的表格有表头,可以先找到code列对应的索引,再直接用列名定位B列,可读性更强:
# 先读取表头行,找到code列的位置 header = [cell.value for cell in sheet[1]] code_col_idx = header.index("code") # 从第2行开始遍历数据行(跳过表头) for row in sheet.iter_rows(min_row=2): # 直接取B列的单元格值,row[0].row可以拿到当前行号 if sheet[f"B{row[0].row}"].value == "Y": code_value = row[code_col_idx].value your_target_function(code_value)
针对大表格的性能优化
9万行50列的表格属于典型的大文件,默认的iter_rows会加载每个单元格对象,内存占用高、遍历速度慢。这里有两个关键优化点:
- 使用
values_only=True参数:直接返回单元格的原始值,而不是Cell对象,能大幅提升遍历速度 - 只读模式+按需加载列:用
read_only=True加载文件,只读取B列和code列,减少不必要的内存开销
优化后的完整示例代码:
from openpyxl import load_workbook def your_target_function(code): # 这里替换成你的实际业务逻辑 print(f"正在处理code: {code}") # 用只读模式加载大文件,内存占用更低 wb = load_workbook("your_excel_file.xlsx", read_only=True) sheet = wb.active # 获取表头,确定B列和code列的索引 header = next(sheet.iter_rows(min_row=1, max_row=1, values_only=True)) code_col_idx = header.index("code") b_col_idx = 1 # B列是第2列,对应索引1 # 只遍历需要的列,values_only=True直接返回数值而非Cell对象 for row in sheet.iter_rows(min_row=2, values_only=True): b_value = row[b_col_idx] if b_value == "Y": code_value = row[code_col_idx] your_target_function(code_value) wb.close()
额外提示
- 如果表头行不是第1行,记得调整
min_row参数 - 确认
code列的表头拼写完全一致,不然index()会报错,可以加个判断处理不存在的情况 - 调试时可以先取前100行测试,没问题再跑全量数据,避免浪费时间
内容的提问来源于stack exchange,提问作者user5847481




