【Python】エクセル:ソートSort(昇順・降順)する方法(win32com、openpyxl)

時計 2021.02.17 / 時計

【Python】エクセル:ソートSort(昇順・降順)する方法(win32com、openpyxl)

本記事ではPythonエクセル操作を行い、ソートSort(昇順・降順)する方法について解説していきます。

エクセルのセル範囲内をソートしてデータを並べ替えることは、エクセル作業をするうえでよく行います。

エクセルのフィルター機能やVBAを使えば簡単にソートをすることができます。
Pythonでも同じように簡単にソートすることができます。

win32comを使ったエクセルのソート(昇順・降順)方法について見ていきましょう。

本記事を通して以下の知識を学べます。

学べる知識
  • win32comの使い方
  • win32comでエクセルをソート(昇順・降順)する方法
  • openpyxlでフィルターをエクセルに付ける方法

Pythonでソートする方法

Pythonにはopenpyxlやwin32comといったエクセル操作のライブラリが用意されています。

Pythonでエクセルデータをソートするにはwin32comを使用します。
win32comでマクロVBAを使用することができます。

win32comを使う上での注意点として、OSがWindowsかつMicrosoft製品であるExcelがインストールされている必要があります。

win32comの詳しい使い方は以下記事をご参照ください。

openpyxlではエクセルのソート(昇順・降順)を自動ですることはできません。
しかしフィルターをエクセルに付けることは可能です。

openpyxlの基本的な使い方は以下記事をご参照ください。

以下ではこれらの方法について解説します。

win32comでのソート(昇順・降順)方法

win32comの準備

win32comは標準ライブラリではないので、pipによるインストールが必要です。

pip install pywin32

Pythonスクリプトで使用するためにスクリプトの先頭でwin32comをインポートします。

import win32com.client

対象のエクセルファイルを開く

まずはエクセル本体を起動します。

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

今回は「エクセルの上書きをしますか」といった警告表示をなくすためにDisplayAlertsをFalseにします。

excel.DisplayAlerts = False

次に対象となるエクセルファイルを開きます。

wb = excel.Workbooks.Open("C:\OFFICE54\OFFICE54.xlsx")

ここではOFFICE54.xlsxという次のようなエクセルを対象とします。

OFFICE54.xlsx

ワークシートを開く

次に対象のワークシートを開きます。

ws = wb.Worksheets(1)

ここでは左から1番目のワークシートを開いています。

Sortで使用する変数に数値を代入

VBAでエクセルの並び替えにはSortメソッドを使用しますよね。

Rangeオブジェクト.Sort Key1:=キー, Order1:=並び替えのルール ,Header:=先頭行見出しの指定

win32comを使用することでPythonでもVBAのコマンドが使用できます。
しかしこのSortメソッドで使用するxlAscendingやxlYesなどのVBA専用の定数はこのままだと使用することができません。

こういったVBA専用の定数を使用する場合は、その定数の数値を代入しておく必要があります。

以下にSortで使用する定数の一覧を記します。

定数 数値
xlAscending 1
xlDescending 2
xlManual -4135
xlGuess 0
xlYes 1
xlNo 2
xlSortColumns 1
xlSortRows 2
xlPinYin 1
xlStroke 2
xlSortNormal 0
xlSortTextAsNumbers 1

Pythonでwin32comを使用し、Sortメソッドを使用する場合は、各VBA定数に上記数値を代入してから使用してください。

# Sortで使用する変数に数値を代入
xlAscending = 1
xlDescendig = 2
xlYes = 1

ソート(昇順・降順)を行う

Pythonのwin32comを使用してソートする場合、次のように記述します。

ws.範囲指定.Sort(Key1=ws.並び替えのキー, Order1=並び替えのルール, Header=先頭行見出しの指定)

エクセルのA列とB列を範囲指定し、昇順、先頭行をタイトル指定すると次のように記述します。

ws.Columns("A:B").Sort(Key1=ws.Range("B2"), Order1=xlAscending, Header=xlYes)

サンプルプログラム

上記をふまえてOFFICE54.xlsxをB列をキーとして昇順するサンプルプログラムを以下に記します。

import win32com.client

# エクセルの起動
excel = win32com.client.Dispatch("Excel.Application")
excel.DisplayAlerts = False

# 既存のエクセルを開く
wb = excel.Workbooks.Open("C:\OFFICE54\OFFICE54.xlsx")

# ワークシートの指定
ws = wb.Worksheets(1)
ws.Activate()

# Sortで使用する変数に数値を代入
xlAscending = 1
xlDescendig = 2
xlYes = 1

ws.Columns("A:B").Sort(Key1=ws.Range("B2"), Order1=xlAscending, Header=xlYes)

wb.SaveAs("C:\OFFICE54\test.xlsx")

wb.Close()

このサンプルプログラムを起動すると次のようなエクセルが作成されます。

サンプルプログラムによって作成されるエクセル

画像を見るとわかるように、タイトル行を含めて昇順してしまっています。
理由はわかりませんが、win32comのSortではxlYesを指定して先頭行見出しありにしても、先頭行を含めて昇順にしてしまいました。

タイトルを含んでしまうバグの解決

HeaderにxlYesを指定しても先頭行を含んでしまうので、範囲指定時に先頭行を含めない範囲を指定することで、この問題を回避することができます。

今回のOFFICE54.xlsxでは、セルA2からB列の最終行までを範囲指定すればいいということです。

OFFICE54.xlsx

最終行の取得方法については以下記事をご参照ください。

サンプルプログラムでタイトル行を含めずにソート昇順するには、ソートの部分を以下のように記述します。

xlUp = -4162
lastrow = ws.Cells(ws.Rows.Count, 2).End(xlUp).Row

ws.Range(ws.Range("A2"), ws.Cells(lastrow, 2)).Sort(Key1=ws.Range("B2"), Order1=xlAscending, Header=xlYes)

このようにすることで正しく昇順にソートしたエクセルを得ることができました。

openpyxlでのフィルター追加

Pythonのopenpyxlでは昇順・降順をすることができません。
その代わりにフィルターを付けることができます。

ws.auto_filter.ref

OFFICE54.xlsxにフィルターを追加するサンプルプログラムを以下に記します。

import openpyxl

wb = openpyxl.load_workbook('C:\OFFICE54\OFFICE54.xlsx')
ws = wb.active

ws.auto_filter.ref = "A1:B11"

wb.save(r"C:\OFFICE54\test.xlsx")

まとめ

本記事「【Python】エクセル:ソートSort(昇順・降順)する方法(win32com、openpyxl)」はいかがでしたか。

win32comは使い方が難しいですが、使えるようになるとエクセルの自動化が楽になります。

ぜひwin32comとopenpyxlを組み合わせてエクセルの自動化プログラムを作ってみてください。