openpyxl iter_rows仅遍历首个单元格,数据匹配复制功能异常求助
问题原因
B_Rows是openpyxl的iter_rows()返回的生成器对象,生成器只能被遍历一次。当你处理完A的第一行后,B_Rows已经被耗尽,后续循环A的其他行时,内层的for name2,dob2,gen2 in B_Rows不会执行任何迭代,所以只处理了第一行数据。
解决方案
方案1:将B_Rows转为列表(简单直接)
把生成器转成列表,这样每次循环A行时都能重新遍历B的所有数据:
# 把B_Rows转为列表,保存所有行数据 A_Rows = A_List.iter_rows(min_row=2, min_col=5, max_row=289, max_col=7) B_Rows = list(B_List.iter_rows(min_row=2, min_col=5, max_row=48927, max_col=7)) for name,dob,gen in A_Rows: # 每次循环A行都能遍历完整的B_Rows列表 for name2,dob2,gen2 in B_Rows: d1 = dob.value.strftime('%m/%d/%Y') d2 = dob2.value.strftime('%m/%d/%Y') if str(d1) == str(d2) and gen.value == gen2.value and name.value in name2.value.upper(): # 复制对应单元格数据 A_List.cell(row=name.row, column=4, value=B_List.cell(row=dob2.row, column=4).value) A_List.cell(row=name.row, column=8, value=B_List.cell(row=dob2.row, column=8).value) A_List.cell(row=name.row, column=9, value=B_List.cell(row=dob2.row, column=9).value) A_List.cell(row=name.row, column=11, value=B_List.cell(row=dob2.row, column=11).value)
方案2:预处理B数据为字典(性能优化)
因为B有48927行,嵌套循环会执行约1400万次迭代,效率极低。可以先把B的关键数据(生日、性别、姓名)作为键,对应要复制的单元格数据作为值,存入字典,之后A的每一行直接查字典匹配:
from collections import defaultdict # 预处理B的数据:用(生日, 性别)作为键,存储符合条件的姓名和对应单元格数据 b_data = defaultdict(list) for name2, dob2, gen2 in B_List.iter_rows(min_row=2, min_col=5, max_row=48927, max_col=7): d2 = dob2.value.strftime('%m/%d/%Y') key = (d2, gen2.value) # 存储姓名(大写)和要复制的单元格值 b_data[key].append({ 'name_upper': name2.value.upper(), 'col4': B_List.cell(row=dob2.row, column=4).value, 'col8': B_List.cell(row=dob2.row, column=8).value, 'col9': B_List.cell(row=dob2.row, column=9).value, 'col11': B_List.cell(row=dob2.row, column=11).value }) # 遍历A的行,直接查字典匹配 for name, dob, gen in A_List.iter_rows(min_row=2, min_col=5, max_row=289, max_col=7): d1 = dob.value.strftime('%m/%d/%Y') key = (d1, gen.value) if key in b_data: # 检查姓名是否匹配 for item in b_data[key]: if name.value in item['name_upper']: # 复制数据 A_List.cell(row=name.row, column=4, value=item['col4']) A_List.cell(row=name.row, column=8, value=item['col8']) A_List.cell(row=name.row, column=9, value=item['col9']) A_List.cell(row=name.row, column=11, value=item['col11']) # 找到匹配后可break,避免重复处理(如果有多个匹配可根据需求调整) break
这个优化方案能把时间复杂度从O(M*N)降到O(M+N),处理速度会快很多。
内容的提问来源于stack exchange,提问作者yeehaw
相关产品推荐
相关产品推荐

