【業務自動化】チャプター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フォルダ内に保存してください。

Q
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のエクセルファイルの保存フォルダ
 │       ├── ・・・
【Python】勉強猫がノートパソコンを前にして学習を始める様子。記事内の学習スタート用イラスト

サンプルコード紹介|全体像と実行例

ここでは、実際に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)

この部分では、既存のシートにある見出し(列名)を取得し、新しいシートにコピーできるよう準備しています。

これを後の処理で新しいシートに書き込み、どのシートにも同じ見出しを付けることで、データの見やすさと一貫性を保ちます。

  1. 列の範囲をループで回す
    • sheet.min_columnsheet.max_column を使って、シート内の列の最小番号と最大番号を取得
    • その範囲を for ループで繰り返し処理し、見出し行の値を1つずつ取り出す
  2. セルの値をリストに追加
    • 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自動化」を体験し、実務に近い形で活用できるようにしていきましょう。

練習問題|シート分割を体験しよう

今回学習した内容を復習する練習問題に挑戦しましょう。

【Python】勉強猫がノートパソコンに向かい、練習問題に挑戦する様子。記事内の休憩用イラスト

問題|Excelデータを年齢区分ごとに分類してシート作成

Excelファイルに記録されている人物データを処理し、年齢区分ごとにシートを分割して保存するプログラムを作成してください。

以下の要件に従ってコードを完成させて下さい。

  • 入力ファイルは既存の Excel ファイル Chapter1-5.xlsx を使用すること。
  • 見出し行を保持し、データ行は 3 行目以降から処理を開始すること。
  • 分類のキーは「年齢区分」の列を用いること。
  • まだ存在しない分類のシートが必要になった場合は、新しいシートを作成し、先頭行に見出しを追加すること。
  • 最終的に分類結果を同じExcelファイルに上書き保存すること。

正解サンプルコードと詳細解説

例えば以下のようなプログラムが考えられます。

Q
正解コード例
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")
Q
正解コードの解説

データ行を順番に読み込み、セルの値をリストに変換する処理

# データ行を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)

ここでは行ごとのデータから年齢区分を取り出して、その区分に合ったシートに書き込んでいます。
もしすでにその区分の名前を持つシートがあれば、そのシートにデータを追加します。
まだそのシートが存在しない場合は、新しいシートを作り、最初に見出し行を書いてからデータを追加します。
これによって、同じ年齢区分のデータがひとつのシートにまとまります。

もっと分かりやすい学習サイトにするために

この記事を読んで「ここが分かりにくかった」「ここが難しかった」等の意見を募集しています。

世界一わかりやすいExcel自動化学習サイトにするため、ぜひ 問い合わせフォーム からご意見下さい。

<<前のページ

業務自動化の記事一覧

次のページ>>

記事URLをコピーしました