OpenPyXL-如何根据某些条件从Excel文件中删除行?

时间:2018-10-15 17:09:29

标签: python python-3.x openpyxl

我想从excel文件中删除行,知道这些值。我使用的是openpyxl:

key_values_list是带有数字的列表(所有内容都在excel文件的列中)

   wb = load_workbook(src)
    sheet = wb['Sheet 1']

    for i in range(2, sheet.max_row + 1):
        if sheet.cell(row=i, column=1).value in key_values_list:
            sheet.delete_rows(i, 1)
    wb.save(src)

上面的代码不会删除所有对应的行

1 个答案:

答案 0 :(得分:2)

您总是会发现在for循环中删除直接元素的问题。对于具有12行及其各自的行值的工作表,请考虑以下代码:

for i in range(1, sh.max_row + 1):
    print(sh.cell(row=i, column=1).value)

# 1 .. 12

现在看看开始删除内容时会发生什么:

for i in range(1, sh.max_row + 1):
    if sh.cell(row=i, column=1).value in [5,6,7]:
        sh.delete_rows(i, 1)
    print(f'i = {i}\tcell value (i, 1) is {sh.cell(row=i, column=1).value}')

# i = 1     cell value (i, 1) is 1
# i = 2     cell value (i, 1) is 2
# i = 3     cell value (i, 1) is 3
# i = 4     cell value (i, 1) is 4
# i = 5     cell value (i, 1) is 5
# i = 6     cell value (i, 1) is 7
# i = 7     cell value (i, 1) is 9
# i = 8     cell value (i, 1) is 10
# i = 9     cell value (i, 1) is 11
# i = 10    cell value (i, 1) is 12
# i = 11    cell value (i, 1) is None
# i = 12    cell value (i, 1) is None

您可以看到,在i in [5, 6, 7]期间,由于第5行已被删除,所以行的移动从第6行开始,从而使原始第6行成为新的第5行,原始第7行成为新的第6行...因此,在i = 6的下一次迭代中,单元格实际上是从原始数据中引用第7行的值。您有效地跳过了第6行的迭代。

最简单的答案是使用while循环,而不是for

i = 1
while i <= sh.max_row:
    print(f'i = {i}\tcell value (i, 1) is {sh.cell(row=i, column=1).value}')
    if sh.cell(row=i, column=1).value in [5,6,7]:
        sh.delete_rows(i, 1)
        # Note the absence of incremental.  Because we deleted a row, we want to stay on the same row because new data will show in the next iteration.
    else:
        i += 1
        # Because the check failed, we can safely increment to the next row.

# i = 1 cell value (i, 1) is 1
# i = 2 cell value (i, 1) is 2
# i = 3 cell value (i, 1) is 3
# i = 4 cell value (i, 1) is 4
# i = 5 cell value (i, 1) is 5 # deleted
# i = 5 cell value (i, 1) is 6 # deleted
# i = 5 cell value (i, 1) is 7 # deleted
# i = 5 cell value (i, 1) is 8
# i = 6 cell value (i, 1) is 9
# i = 7 cell value (i, 1) is 10
# i = 8 cell value (i, 1) is 11
# i = 9 cell value (i, 1) is 12

# verify the data has been deleted
for i in range(1, sh.max_row +1):
    print(sh.cell(row=i, column=1).value)

# 1
# 2
# 3
# 4
# 8
# 9
# 10
# 11
# 12

现在您可以看到,i尚未达到12时,由于i=5已被处理三次,因此每一行都被迭代。

如果出于任何原因必须必须使用for循环进行迭代,则可能需要考虑一些alternative methods such as iterating through a copy or doing it backward