【業務自動化】チャプター1-5|データを新規シートへ自動で振り分け
一つ前のページでは シートにデータを書き込む方法 について学習しました。
今回は データの自動振り分け について見ていきましょう。
Chapter1:PythonでExcelを操作しよう
・Chapter1-1:openpyxlとは何か|インストールと動作確認
・Chapter1-2:PythonでExcelファイルを作成しよう
・Chapter1-3:Excelシートからデータを読み込もう
・Chapter1-4:Excelシートにデータを書き込もう
・Chapter1-5:データを新規シートへ自動振り分けしよう ◁今回はここ
・Chapter1-6:簡単なExcel自動化を体験しよう
Chapter2:PyInstallerで自動化ツール(.exe)を作ろう
Chapter3:ファイル・フォルダを操作しよう
Chapter4:メール送信を自動化しよう
Chapter5:Webスクレイピング
Excelを日常的に扱っていると、「特定の条件ごとにデータを分類して別のシートに分けたい」と思う場面はよくあります。
たとえば、名簿を男女別のシートに振り分けたり、売上データを支店ごとに分けたりといった作業です。
手作業で行うと非常に面倒ですが、Pythonとopenpyxlを使えば自動でシートを作成し、条件に応じてデータを仕分けることができます。
この記事では、Excelの1つのシートにまとまったデータを、条件ごとに新しいシートへ自動で振り分ける方法を学んでいきます。
初心者でも理解できるように、コードの紹介から動作の仕組みまで丁寧に解説していきます。
条件別で行を新規シートへ自動振り分けする方法
この節では、openpyxlを使って既存のExcelデータを特定の条件(例:性別)ごとに分け、新しいシートを自動生成しながらデータを振り分けるプログラムを作成していきます。
前回作成したExcel資料「chapter1-4.xlsx」を引き続き使用します。
資料がない方は↓↓のダウンロードリンクからファイルをダウンロードし、workbooksフォルダ内に保存してください。
- Excelファイルの保存場所について
-
ダウンロードしたExcelファイルは以下の階層になるように保存して下さい。
この理由については、Chapter1-2 の記事で詳しく解説しています。
Excel自動化学習 # 学習フォルダ ├── Chap1/ # チャプター1の保存フォルダ │ ├── app1-1.py │ ├── app1-2.py │ ├── ・・・ │ └── workbooks/ # チャプター1のエクセルファイルの保存フォルダ │ ├── sample1-1.xlsx │ ├── sample2-1.xlsx │ ├── ・・・ │ ├── Chap2/ # チャプター2の保存フォルダ │ ├── app2-1.py │ ├── ・・・ │ └── workbooks/ # チャプター2のエクセルファイルの保存フォルダ │ ├── ・・・
サンプルコード紹介|全体像と実行例
ここでは、実際にExcelデータを条件ごとに新しいシートへ振り分けるプログラムを紹介します。
以下のサンプルコードでは、既存のExcelファイルを読み込み、特定の列(ここでは「性別」)を基準にシートを作成してデータを仕分けています。
import openpyxl, pathlib # openpyxlとpathlibのインポート file_path = pathlib.Path(__file__).parent / "workbooks" # エクセルファイルの保存フォルダの相対パスを作成 book = openpyxl.load_workbook(file_path / "Chapter1-4.xlsx") # ワークブックの読み込み sheet = book.active # アクティブなシートを取得 HEADER_ROW_NO = 2 # 見出しが書かれている行番号 READ_START_ROW_NO = 3 # データ読み込みを開始する行番号 KEY_INDEX = 2 # 分類に使う列のインデックス番号(列番号ではない) # 見出し行の値を取得してリストに格納 header_row_values = [] # 見出しの行を格納するリストの定義 for i in range(sheet.min_column-1, sheet.max_column+1): header_row_values.append(sheet.cell(HEADER_ROW_NO, i).value) # データ行を1行ずつ処理 for row in sheet.iter_rows(min_row = READ_START_ROW_NO): # 3行目以降をタプル形式で取得(中身はセルオブジェクト) row_values = [] # 空のリストを定義 for cell in row: # 変数row内のデータ(セルオブジェクト)を順番に row_values.append(cell.value) # 値だけ取り出してリストrow_valuesに代入 key_value = row_values[KEY_INDEX] # 性別(分類キー)を変数key_valueに代入 if key_value in book.sheetnames: # もしその性別のシートがあるならば to_sheet = book[key_value] # そのシートを取得 else: # もし無いなら to_sheet = book.create_sheet(title=key_value) # その性別のシートを作成し、 to_sheet.append(header_row_values) # 1行目に見出しを書き込む to_sheet.append(row_values) # そのシートにリストrow_valuesの内容を書き込み # ファイルを保存 book.save(file_path / "Chapter1-5.xlsx")
このコードを実行すると、新規ブックchapter1-5.xlsxが作成されます。
そのブックには「男」と「女」という新しいシートが追加されており、適切に分類されているはずです。
ブックを直接開き、結果を確認して下さい。
サンプルコードの解説|処理の流れとポイント
このプログラムのポイントを順に解説します。
Excel処理の準備|ライブラリ導入とファイル指定
import openpyxl, pathlib # openpyxlとpathlibのインポート file_path = pathlib.Path(__file__).parent / "workbooks" # エクセルファイルの保存フォルダの相対パスを作成 book = openpyxl.load_workbook(file_path / "Chapter1-4.xlsx") # ワークブックの読み込み sheet = book.active # アクティブなシートを取得 HEADER_ROW_NO = 2 # 見出しが書かれている行番号 READ_START_ROW_NO = 3 # データ読み込みを開始する行番号 KEY_INDEX = 2 # 分類に使う列のインデックス番号(列番号ではない)
1行目から5行目まではここまで学習してきた内容と同じです。
必要なライブラリのインポート、ワークブックの保存場所のパス作成、そして実際にワークブックを開く処理をしています。
この部分に分からないところがある人は、Chapter1-2 の記事に戻って復習しましょう。
その後、データの読みとりに必要となる定数を定義しています。
ヘッダー取得|新規シートへ見出しを引き継ぐ準備
# 見出し行の値を取得してリストに格納 header_row_values = [] # 見出しの行を格納するリストの定義 for i in range(sheet.min_column-1, sheet.max_column+1): header_row_values.append(sheet.cell(HEADER_ROW_NO, i).value)
この部分では、既存のシートにある見出し(列名)を取得し、新しいシートにコピーできるよう準備しています。
これを後の処理で新しいシートに書き込み、どのシートにも同じ見出しを付けることで、データの見やすさと一貫性を保ちます。
- 列の範囲をループで回す
sheet.min_column
とsheet.max_column
を使って、シート内の列の最小番号と最大番号を取得- その範囲を
for
ループで繰り返し処理し、見出し行の値を1つずつ取り出す
- セルの値をリストに追加
sheet.cell(HEADER_ROW_NO, i).value
で「見出し行のi列目」の値を取得- 取得した値を
header_row_values.append(...)
でリストに追加
最終的に、見出し行の値だけを集めたリストが完成します。
行を順番に読み込んでリスト化|iter_rows()メソッドの使い方
# データ行を1行ずつ処理 for row in sheet.iter_rows(min_row = READ_START_ROW_NO): # 3行目以降をタプル形式で取得(中身はセルオブジェクト) row_values = [] # 空のリストを定義 for cell in row: # 変数row内のデータ(セルオブジェクト)を順番に row_values.append(cell.value) # 値だけ取り出してリストrow_valuesに代入
この部分では、Excelのデータ部分を1行ずつ読み込んで、扱いやすいPythonリストに変換 しています。
最初のfor文の中にある iter_rows()メソッド は、Excel シートの行をタプルとして効率的に読み込むためのメソッドです。
戻り値として行単位のセルオブジェクト(Cell
インスタンス)を返します。
基本的な使い方は以下の通りです。
for row in worksheet.iter_rows( min_row=None, # 開始する行番号 (デフォルトは 1) max_row=None, # 終了する行番号 (省略するとシートの最終行まで) min_col=None, # 開始する列番号 (デフォルトは 1, A列) max_col=None, # 終了する列番号 (省略するとシートの最終列まで) ):
各引数にNoneを代入するとデフォルト値が適用されます。また、デフォルト値を使用する場合は引数は省力することもできます。
すなわち、今回の提供コードは「データ読み込みを開始する行番号(=3行目)」からデータがある最後の行まで、4列のデータをタプルとして取得し、そのタプルをリストrow_valuesに格納しています。
row_values = [3行目のタプル, 4行目のタプル, 5行目のタプル, ...] 3行目のタプル = (<Cell 'Sheet'.B3>, <Cell 'Sheet'.C3>, <Cell 'Sheet'.D3>, <Cell 'Sheet'.E3>) 3行目のタプル[0].value = 吉田 彩花 3行目のタプル[1].value = 女
振り分け処理|分類キーでシート選択・自動作成しappendで書き込む
key_value = row_values[KEY_INDEX] # 性別(分類キー)を変数key_valueに代入 if key_value in book.sheetnames: # もしその性別のシートがあるならば to_sheet = book[key_value] # そのシートを取得 else: # もし無いなら to_sheet = book.create_sheet(title=key_value) # その性別のシートを作成し、 to_sheet.append(header_row_values) # 1行目に見出しを書き込む to_sheet.append(row_values) # そのシートにリストrow_valuesの内容を書き込み
この部分では、性別毎にシートを作成し、データを振り分けています。
- .sheetnamesプロパティ:その
Workbook
に含まれるワークシート名のリストを返す - .create_sheet()メソッド:新しいワークシートをブックに追加
- .appendメソッド:指定したリストやタプルを「新しい行として」追加
振り分けられたデータ(タプル)は、最後の行でそのシートに書き込まれます。
保存|新規ブックとして出力
# ファイルを保存 book.save(file_path / "Chapter1-5.xlsx")
最後に、分類処理を終えたワークブックを新しいファイルとして保存して終了です。
まとめ|iter_rows()で条件別に新規シートへ自動振り分け
今回のサンプルでは、Excelのデータを特定の列を基準に自動で新規シートへ振り分ける方法を学びました。
openpyxl
を使えば、手作業では面倒な「データ仕分け」も自動化できる- 条件に応じて新しいシートを作成し、ヘッダーをコピーして整った形式で保存できる
- 出力ファイルを別名で保存することで元データを守れる
こうした処理は、顧客リストの分類、商品カテゴリ別の売上管理、担当者別のタスク分けなど、ビジネスの現場で幅広く応用できます。
次のステップでは、さらに「簡単なExcel自動化」を体験し、実務に近い形で活用できるようにしていきましょう。
練習問題|シート分割を体験しよう
今回学習した内容を復習する練習問題に挑戦しましょう。
問題|Excelデータを年齢区分ごとに分類してシート作成
Excelファイルに記録されている人物データを処理し、年齢区分ごとにシートを分割して保存するプログラムを作成してください。
以下の要件に従ってコードを完成させて下さい。
- 入力ファイルは既存の Excel ファイル
Chapter1-5.xlsx
を使用すること。 - 見出し行を保持し、データ行は 3 行目以降から処理を開始すること。
- 分類のキーは「年齢区分」の列を用いること。
- まだ存在しない分類のシートが必要になった場合は、新しいシートを作成し、先頭行に見出しを追加すること。
- 最終的に分類結果を同じExcelファイルに上書き保存すること。
正解サンプルコードと詳細解説
例えば以下のようなプログラムが考えられます。
- 正解コード例
-
import openpyxl, pathlib file_path = pathlib.Path(__file__).parent / "workbooks" book = openpyxl.load_workbook(file_path / "Chapter1-5.xlsx") sheet = book.active HEADER_ROW_NO = 2 READ_START_ROW_NO = 3 KEY_INDEX = 4 # 年齢区分(E列) # 見出し行をリスト化 header_row_values = [] for i in range(sheet.min_column-1, sheet.max_column+1): header_row_values.append(sheet.cell(HEADER_ROW_NO, i).value) # データ行を1つずつ処理 for row in sheet.iter_rows(min_row=READ_START_ROW_NO): row_values = [cell.value for cell in row] key_value = str(row_values[KEY_INDEX]) # 年齢区分(必ず文字列化) if key_value in book.sheetnames: to_sheet = book[key_value] else: to_sheet = book.create_sheet(title=key_value) to_sheet.append(header_row_values) to_sheet.append(row_values) # 保存 book.save(file_path / "Chapter1-5-answer.xlsx")
- 正解コードの解説
-
データ行を順番に読み込み、セルの値をリストに変換する処理
# データ行を1つずつ処理 for row in sheet.iter_rows(min_row=READ_START_ROW_NO): row_values = [cell.value for cell in row]
この部分では、Excelシートの3行目以降のデータを1行ずつ取り出しています。
取り出した1行はセルの集まりなので、そのままでは扱いにくいため、セルの中の値だけを取り出してリストにまとめています。
これで、1行分の情報をPythonのリストとして使えるようになります。年齢区分をキーにシートを振り分け
key_value = str(row_values[KEY_INDEX]) # 年齢区分(必ず文字列化) if key_value in book.sheetnames: to_sheet = book[key_value] else: to_sheet = book.create_sheet(title=key_value) to_sheet.append(header_row_values) to_sheet.append(row_values)
ここでは行ごとのデータから年齢区分を取り出して、その区分に合ったシートに書き込んでいます。
もしすでにその区分の名前を持つシートがあれば、そのシートにデータを追加します。
まだそのシートが存在しない場合は、新しいシートを作り、最初に見出し行を書いてからデータを追加します。
これによって、同じ年齢区分のデータがひとつのシートにまとまります。