使用openpyxl排序

时间:2017-06-26 19:46:13

标签: python excel openpyxl

我正在尝试使用openpyxl将列从最小到最大排序。我愿意使用其他库来实现这一目标。这是我现在的代码,然而,没有任何东西被分类。

from openpyxl import load_workbook

wb=load_workbook('NotSorted.xlsx')
ws1=wb.get_sheet_by_name('Mean')

ws1.auto_filter.add_sort_condition('J2:J21')

wb.save('Sorted.xlsx')

非常感谢任何帮助!

3 个答案:

答案 0 :(得分:3)

openpyxl documentation明确指出:

  

这会将相关指令添加到文件中,但实际上既不会过滤也不会排序。

因此,您需要计算新的行序列并明确移动数据(即将单元格分配到新位置)。

答案 1 :(得分:3)

您可以使用win32com.client进行排序(使用pip install pypiwin32安装)。

名为MyWorkbook.xlsx的示例工作簿,其中包含内容(之前和之后):

Before sorting After sorting

import win32com.client

excel = win32com.client.Dispatch("Excel.Application")

wb = excel.Workbooks.Open('MyWorkbook.xlsx')
ws = wb.Worksheets('Sheet1')

ws.Range('A2:A9').Sort(Key1=ws.Range('A1'), Order1=1, Orientation=1)

wb.Save()
excel.Application.Quit()

如果您不想更改原始工作簿,请使用SaveAs()或创建另一个工作簿并复制数据,如下所示:ws_from.Range("A1:AF100").Copy(ws_to.Range("A1:AF100"))(具有适当的范围)。

有关Sort()及其参数的详细信息,请参阅这些文档链接:

答案 2 :(得分:1)

似乎没有内置函数可以在 openpyxl 中进行排序,但下面的函数将根据某些条件对行进行排序:

def sheet_sort_rows(ws, row_start, row_end=0, cols=None, sorter=None, reverse=False):
""" Sorts given rows of the sheet
    row_start   First row to be sorted
    row_end     Last row to be sorted (default last row)
    cols        Columns to be considered in sort
    sorter      Function that accepts a tuple of values and
                returns a sortable key
    reverse     Reverse the sort order
"""

bottom = ws.max_row
if row_end == 0:
    row_end = ws.max_row
right = get_column_letter(ws.max_column)
if cols is None:
    cols = range(1, ws.max_column+1)

array = {}
for row in range(row_start, row_end+1):
    key = []
    for col in cols:
        key.append(ws.cell(row, col).value)
    array[key] = array.get(key, set()).union({row})

order = sorted(array, key=sorter, reverse=reverse)

ws.move_range(f"A{row_start}:{right}{row_end}", bottom)
dest = row_start
for src_key in order:
    for row in array[src_key]:
        src = row + bottom
        dist = dest - src
        ws.move_range(f"A{src}:{right}{src}", dist)
        dest += 1

用工作表调用它并开始作为最小排序的行。默认情况下,它将按该顺序对所有列 A...max 进行排序,但这可以通过传递“cols”列表来更改。例如。 [4, 2] 将首先在 D 上排序,然后在 B 上排序。

可以像使用 'sorted()' 一样使用 'reverse' 来反​​转排序顺序。

如果您需要更复杂的排序,请提供“排序器”功能。这将接收一个值元组(来自“cols”列的值)并且应该返回一个可排序的键。

它的工作原理是确定每行所需的最终目的地,将它们全部向下移动到当前工作表下方,然后将它们移回所需的目的地。

我想要每行中的所有列,但是可以通过将两次调用更改为 ws.move_range() 来修改以移动更小的区域。

示例:

sheet_sort_rows(ws, 5, 10)  # Sort rows 5-10 using key: A, B, C, ...
sheet_sort_rows(ws, 5, 10, [2, 1])  # Sort rows using B, A
sheet_sort_rows(ws, 5, 10, [2, 1], reverse=True)  # As above in reverse


def sorter(t):
    return t[1] + " " + t[0][::-1]

sheet_sort_rows(ws, 5, 10, sorter=sorter)

最后按 B 列排序,然后反转 A 列。