【问题标题】:Sorting with openpyxl使用 openpyxl 排序
【发布时间】:2017-11-29 18:08:53
【问题描述】:

我正在尝试使用 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')

非常感谢任何帮助!

【问题讨论】:

    标签: python excel openpyxl


    【解决方案1】:

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

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

    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】:

      openpyxl documentation 明确指出:

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

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

      【讨论】:

        【解决方案3】:

        在 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 上。

        使用“reverse”可以反转排序顺序,就像使用“sorted()”一样。

        如果您需要更复杂的排序,请提供“排序器”功能。这会接收一个值元组(来自 '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 列颠倒。

        【讨论】:

        • 编辑为先前版本失败,其中有重复的行(具有相同的排序键)。
        猜你喜欢
        • 1970-01-01
        • 2023-01-20
        • 1970-01-01
        • 2012-06-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-09-04
        • 1970-01-01
        相关资源
        最近更新 更多