这里写目录标题

  • 起因
  • 方案一
  • 方案一存在的问题
  • 方案优化思路
  • 方案核心
  • 最终方案代码


起因

方案一

因为工作需求,需要从excel文件中筛选出一些行删掉。由于只是半路出家,觉得人生苦短,我用python,刚开始只是根据网上帖子使用for 加上delete_rows(行号, 第几列)来删除数据,代码如下:

for i in range(1, ws2.max_row, 1):  # 从第一行开始到最后一行逐行进行
    if ws2.cell(row=i, column=1).value == "Zone": # Zone可以变成自己想要的值或者是字符串
        ws2.delete_rows(i, 1)  # 则删除该行

发现在Zone不连续出现时,代码运行效果良好,但是如果删除条件Zone可能连续出现,会导致一次只能删除两个连续的Zone中的其中一行。

方案一存在的问题

经过观察,发现是因为delete_rows在删除对应行时,后面的数据行号发生了改变,已经删除的行号对应的值发生改变,而循环没有重新返回该行重新进行判断是否需要删除。

方案优化思路

自己收搜了一下,发现网友们的分享也是杂七杂八,参考价值不大。
然后自己想了一个不太成熟但好用的方法:
先遍历一遍数据,将需要删除的行号记录到列表中,再循环删除列表对应的行号。但是与方案一不同的是:
删除前需要根据删除的次数,计算此刻真正应该删除的行。经过试验发现,由于列表防止越界限制,需要单独删除最后一个符合条件的行。

方案核心

每次删除一行,后面符合删除条件但未删除的数据行号应该减一。

最终方案代码

最后成果如下,可用好用,代码简单,分享一下也是为了记录:

# 导入需要用到的相关包
import os
import openpyxl

file = r"位置\文件名.xlsx"

wb = openpyxl.load_workbook(file)
ws = wb.active

list1 = []  # 列表存储要删除的行
length = 0  # 删除行数据后,原要删除的行数变化的值

# 获取需要删除的行数
for i in range(1, ws.max_row, 1):  # 从第一行开始到最后一行逐行进行
    if ws.cell(row=i, column=1).value == "None":  # 如果第i行第1列值为“Zone”,i指的是行,column=1,1可以换成想要的列数
        line = i
        list1.append(line)

# 根据删除一行后,行数变化的规律,删除应该删除的行数
for i in range(len(list1)):
    ws.delete_rows(list1[i]-length, 1)
    length = length + 1

# 删除列表无法企及的最后一行
ws.delete_rows(ws.max_row, 1)

# 保存文件
wb.save(file)
print("保存成功!")

如果后面有新的优化思路,可能会优化一下,但现在基本够用。
【发表是最好的记忆】