删除空行 - openpyxl

时间:2016-02-12 18:07:54

标签: python excel openpyxl

在最后几个小时试图找到一种方法,我决定只是问。

我经历了openpyxl docs次多次,并且经历了herehere提出的问题,甚至是{{3}的章节并没有真正回答我试图做的事情。

这是我现在的代码:

for row in ws.iter_rows():
    i = 1
    if row[i].internal_value() == None:
        ws.Rows(i).Delete()
    else:
        i + 1

我已尝试过很多不同的事情,现在我收到了错误:

  

TypeError:' NoneType'对象不可调用

我做错了什么,如何修复它以便我遍历所有行并删除任何完全为空的行,或者(如果它更容易实现)一个空的第一个细胞?

由于

8 个答案:

答案 0 :(得分:4)

2018更新:我正在搜索今天如何删除一行,发现该功能已添加到openpyxl 2.5.0-b2中。刚试过,它完美无缺。 这是我找到答案的链接:https://bitbucket.org/openpyxl/openpyxl/issues/964/delete_rows-does-not-work-on-deleting

以下是删除一行的语法:

ws.delete_rows(index, 1)

其中: ' WS'是工作表, '指数'是行号,和 ' 1'是要删除的行数。

还可以删除列,但我还没有尝试过。

答案 1 :(得分:4)

可能适合某人使用下一个代码:

index_row = []

# loop each row in column A
for i in range(1, ws.max_row):
    # define emptiness of cell
    if ws.cell(i, 1).value is None:
        # collect indexes of rows
        index_row.append(i)

# loop each index value
for row_del in range(len(index_row)):
    ws.delete_rows(idx=index_row[row_del], amount=1)
    # exclude offset of rows through each iteration
    index_row = list(map(lambda k: k - 1, index_row))

答案 2 :(得分:3)

据我所知,openpyxl无法删除行。您可以使用COM代替,例如:

import win32com.client

filename = 'c:/my_file.xlsx'
sheetname = 'Sheet1'
xl = win32com.client.DispatchEx('Excel.Application')
wb = xl.Workbooks.Open(Filename=filename) 
ws = wb.Sheets(sheetname)

begrow = 1
endrow = ws.UsedRange.Rows.Count
for row in range(begrow,endrow+1): # just an example
  if ws.Range('A{}'.format(row)).Value is None:
    ws.Range('A{}'.format(row)).EntireRow.Delete(Shift=-4162) # shift up

wb.Save()
wb.Close()
xl.Quit()

答案 3 :(得分:1)

我发现的原因之一是,每次循环运行时,您都将i的值初始化为1:

i=1
for row in ws.iter_rows():
    if row[i].internal_value() == None:
        ws.Rows(i).Delete()
    else:
        i + 1

Rest可以在查看完整代码后回答。

答案 4 :(得分:1)

可以将相同的逻辑应用于删除空列。

from openpyxl import *
import numpy as np
import os


path = "filepath"

workbooks = os.listdir(path)
workbooks = [_ for _ in workbooks if not _.startswith('~')]



for workbook in workbooks:
    wb2 = load_workbook(os.path.join(path, workbook))
    for sheet in wb2.worksheets:
        max_row_in_sheet = sheet.max_row
        max_col_in_sheet = sheet.max_column
        array_3 = np.array([])
        array_4 = np.array([])
        r = 1
        c = 1
        for r in range(1, max_row_in_sheet+1):
            array_1 = np.array([])
            array_2 = np.array([])
            for c in range (1, max_col_in_sheet+1):
                if sheet.cell(row = r, column = c).value == None:
                    array_1 = np.append(array_2, c)
                    array_2 = array_1
            if len(array_1) == max_col_in_sheet:
                array_3 = np.append(array_4, r)
                array_4 = array_3
                array_3 = array_3.astype(int)
        if len(array_3) != 0:
            index_of_last_array_element = len(array_3) - 1
            while index_of_last_array_element != -1:
                sheet.delete_rows(array_3[index_of_last_array_element], 1)
                index_of_last_array_element = index_of_last_array_element - 1
    wb2.save(workbook)

答案 5 :(得分:0)

有很多理由说明openpyxl没有提供这种可能性,但您可以根据此代码段解决问题: https://bitbucket.org/snippets/openpyxl/qyzKn

否则请查看xlwings以远程控制Excel,而不必乱用COM。

答案 6 :(得分:0)

openpyxl.worksheet.worksheet.Worksheet.insert_rows()
openpyxl.worksheet.worksheet.Worksheet.insert_cols()
openpyxl.worksheet.worksheet.Worksheet.delete_rows()
openpyxl.worksheet.worksheet.Worksheet.delete_cols()

特定行:

ws.insert_rows(7)

列范围(与行相同):

ws.delete_cols(6, 3)

OpenPyXL documentation

(这是2018年的功能,因此请记住升级:python3 -m pip install openpyxl --upgrade)

答案 7 :(得分:0)

此脚本遍历工作簿中的所有工作表,并删除列表“ rows_to_delete”中的行。在运行脚本之前,请确保删除所有表格格式。换句话说,您要先将表格转换为正常范围。

import openpyxl
rows_to_delete = [None, '', ' ']
for i in wb.sheetnames:
    print(f'Now in sheet: {i}')
    ws = wb[i]
    # loop each row in column B
    column_b = range(1, ws.max_row)
    for i in reversed(column_b):
        if ws.cell(i, 2).value in rows_to_delete:
            print(f'Deleting Row: {ws.cell(i,2).row}')
            ws.delete_rows(ws.cell(i,2).row)