Вы всегда найдете проблему с удалением прямых элементов в цикле 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]
, смещение строк началось со строки 6, потому что строка 5 уже была удалена, что делает исходную строку 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
не делаетt достигает 12, каждая строка повторяется, потому что i=5
был обработан трижды.
Если по какой-либо причине вы должны использовать цикл for
для итерации, вы можете рассмотретьнекоторые альтернативные методы, такие как итерация копии или обратная