Python在给定列中查找最高行

我在stackoverflow很新,最近学到了一些基本的Python。 这是我第一次使用openpyxl。 在我使用xlrd和xlsxwriter之前,我设法做了一些有用的程序。 但是现在我需要一个.xlsx的读写器。

有一个文件,我需要阅读和编辑已经存储在代码中的数据。 假设.xlsx有五列数据:A,B,C,D,E。在列A中,我有超过1000行的数据。 在D列上,我有150行数据。

基本上,我想让程序find给定列上的数据的最后一行(如D)。 然后,将存储的variablesdata写入列D中的下一个可用行(最后一行+1)。

问题是我不能使用ws.get_highest_row()因为它返回列A上的行1000

基本上,到目前为止,这是我得到的一切:

 data = 'xxx' from openpyxl import load_workbook wb = load_workbook('book.xlsx', use_iterators=True) ws = wb.get_sheet_by_name('Sheet1') last_row = ws.get_highest_row() 

显然这根本不起作用。 last_row返回1000。

以下是如何使用pandas来做到这一点。

使用last_valid_index 很容易得到Pandas中的最后一个非空行。

将结果数据DataFrame写入xlsx文件可能有更好的方法,但根据文档 ,这种非常愚蠢的方式实际上是如何在openpyxl完成的。

假设您从这个简单的工作表开始:

原始工作表

假设我们想把xxx放到C列中:

 import openpyxl as xl import pandas as pd wb = xl.load_workbook('deleteme.xlsx') ws = wb.get_sheet_by_name('Sheet1') df = pd.read_excel('deleteme.xlsx') def replace_first_null(df, col_name, value): """ Replace the first null value in DataFrame df.`col_name` with `value`. """ return_df = df.copy() idx = list(df.index) last_valid = df[col_name].last_valid_index() last_valid_row_number = idx.index(last_valid) # This next line has mixed number and string indexing # but it should be ok, since df is coming from an # Excel sheet and should have a consecutive index return_df.loc[last_valid_row_number + 1, col_name] = value return return_df def write_df_to_worksheet(ws, df): """ Write the values in df to the worksheet ws in place """ for i, col in enumerate(replaced): for j, val in enumerate(replaced[col]): if not pd.isnull(val): # Python is zero indexed, so add one # (plus an extra one to take account # of the header row!) ws.cell(row=j + 2, column=i + 1).value = val # Here's the actual replacing happening replaced = replace_first_null(df, 'C', 'xxx') write_df_to_worksheet(ws, df) wb.save('changed.xlsx') 

这导致:

编辑的Excel文件

问题是, get_highest_row()本身使用行维度实例来定义工作表中的最大行。 RowDimension没有关于列的信息 – 这意味着我们不能用它来解决你的问题,必须以不同的方式处理它。

这是一种“丑陋的”openpyxl特定的选项,虽然不会工作,如果use_iterators=True

 from openpyxl.utils import coordinate_from_string def get_maximum_row(ws, column): return max(coordinate_from_string(cell)[-1] for cell in ws._cells if cell.startswith(column)) 

用法:

 print get_maximum_row(ws, "A") print get_maximum_row(ws, "B") print get_maximum_row(ws, "C") print get_maximum_row(ws, "D") 

除此之外,我会按照@ LondonRob的build议来parsingpandas的内容,并让它做这项工作。

如果这是openpyxl的限制,那么你可以尝试下面的方法之一:

  • 将Excel文件转换为csv并使用Python csv模块。
  • 使用zipfile解压缩Excel文件,然后导航到未压缩文件的“xl / worksheets”子文件夹,在那里您将find每个工作表的XML。 从那里你可以用BeautifulSouplxmlparsing和更新。

xslx Excel格式是XML文件的压缩(压缩)树文件夹。 你可以在这里find规格。

我将开始回馈给stackoverflow社区。 Alecxe的解决scheme对我不起作用,我不想使用pandas等,所以我做了这个。 它从电子表格的末尾进行检查,并为您提供D列中的下一个可用/空行。

 def unassigned_row_in_column_D(): ws_max_row = int(ws.max_row) cell_coord = 'D' + str(ws_max_row) while ws.cell(cell_coord).value == None: ws_max_row -= 1 cell_coord = 'D' + str(ws_max_row) ws_max_row += 1 return 'D' + str(ws_max_row) #then add variable data = 'xxx' to that cell ws.cell(unassigned_row_in_column_D()).value = data 

alexce的解决scheme不适合我。 这可能是一个openpyxl版本的问题,我在2.4.1,这是一个小的调整后工作:

 def get_max_row_in_col(ws, column): return max([cell[0] for cell in ws._cells if cell[1] == column])