You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

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会加载每个单元格对象,内存占用高、遍历速度慢。这里有两个关键优化点:

  1. 使用values_only=True参数:直接返回单元格的原始值,而不是Cell对象,能大幅提升遍历速度
  2. 只读模式+按需加载列:用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

火山引擎 最新活动