【業務自動化】Chapter1-6|簡単なExcel自動化を体験しよう

ながみえ

一つ前のページでは データを各シートへ自動振り分けする方法 について学習しました。

今回は 簡単なExcel自動化 を体験してみましょう。

Chapter1:PythonによるExcel自動化の基本を身につけよう
 ・Chapter1-1:openpyxlとは何か|インストールと動作確認
 ・Chapter1-2:PythonでExcelファイルを作成しよう
 ・Chapter1-3:Excelシートからデータを読み込もう
 ・Chapter1-4:Excelシートにデータを書き込もう
 ・Chapter1-5:データを新規シートへ自動振り分けしよう
 ・Chapter1-6:簡単なExcel自動化を体験しよう ◁今回はここ
Chapter2:自動化ツールを.exe化して配布しよう
Chapter3:現場で使える便利な自動化ツールを4つ作ろう
Chapter4:Webスクレイピングでデータを自動で集めよう
Chapter5:自動化ツールを作ってお金を稼ごう

これまでの学習で、Excelファイルの作成・読み込み・書き込みといった基本的な操作を体験してきました。

本記事では、Chapter1の集大成として「簡単なExcel自動化」に挑戦します。

具体的には、あらかじめ用意したExcelテンプレートを使い、名簿データをもとにメンバーごとの個別ファイルを自動で作成する方法を学びます。

この手法を覚えれば、手作業では時間のかかるファイル複製や名前の入力が自動で行われるようになります。

Excel業務を効率化する第一歩として、Pythonとopenpyxlを使った自動化を実際に体験してみましょう。

あわせて読みたい
openpyxl使える関数・メソッド・クラス一覧【Excel自動化の基本リファレンス】
openpyxl使える関数・メソッド・クラス一覧【Excel自動化の基本リファレンス】

<<前のページ

業務自動化の記事一覧

次のページ>>

Excelテンプレートの自動複製で名簿別ファイルを量産

この記事では、テンプレートとなるExcelファイルを複製し、名簿にあるメンバーごとに新しいファイルを作成する方法を紹介します。

これにより、同じ形式のファイルを大量に作成する作業を自動化できるようになります。

前回作成したExcel資料「Chapter1-5.xlsx」を引き続き使用します。

資料がない方は↓↓の「make_workbook1-5.py」をコピーして適切な場所(※)に保存し、実行してください。

Q
make_workbook1-5.py
import pathlib
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Border, Side, Alignment
from openpyxl.styles.colors import Color


def create_main_sheet(sheet):
    sheet.title = "Sheet1"

    # 行の高さ・列幅
    sheet.sheet_format.defaultRowHeight = 18.75
    sheet.sheet_format.defaultColWidth = 9
    sheet.column_dimensions["B"].width = 11.625
    sheet.column_dimensions["D"].width = 11.375

    # データ(Chapter1-5で使う元データ)
    data_list = [
        ["名前", "性別", "年齢", "年齢区分"],
        ["吉田 彩花", "女", 45, "成人"],
        ["小林 翔太", "男", 21, "成人"],
        ["長谷川 清", "男", 80, "シニア"],
        ["山田 大輔", "男", 40, "成人"],
        ["佐藤 陽翔", "男", 1, "未成年"],
        ["渡辺 亮", "男", 50, "成人"],
        ["伊藤 陽菜", "女", 12, "未成年"],
        ["木村 智子", "女", 75, "シニア"],
        ["鈴木 結衣", "女", 3, "未成年"],
        ["松本 健太", "男", 30, "成人"],
        ["石井 誠", "男", 70, "シニア"],
        ["中村 莉子", "女", 18, "未成年"],
        ["高橋 悠真", "男", 6, "未成年"],
        ["田中 美月", "女", 9, "未成年"],
        ["岡田 隆", "男", 60, "成人"],
        ["藤田 美穂", "女", 55, "成人"],
        ["山本 大和", "男", 15, "未成年"],
        ["村上 幸子", "女", 65, "シニア"],
        ["佐々木 真由", "女", 35, "成人"],
        ["加藤 愛美", "女", 25, "成人"],
    ]

    # スタイル設定
    font = Font(name="游ゴシック", size=11)

    fill = PatternFill(
        patternType="solid",
        fgColor=Color(theme=5, tint=0.4)
    )

    thin_side = Side(style="thin", color=Color(auto=1))

    header_border = Border(
        left=thin_side, right=thin_side, top=thin_side, bottom=thin_side
    )
    row3_b_d_border = Border(
        left=thin_side, right=thin_side, bottom=thin_side
    )
    row3_c_border = Border(
        left=thin_side, bottom=thin_side
    )
    body_b_d_border = Border(
        left=thin_side, right=thin_side, top=thin_side, bottom=thin_side
    )
    body_c_border = Border(
        left=thin_side, top=thin_side, bottom=thin_side
    )
    body_e_border = Border(
        left=thin_side, right=thin_side, top=thin_side, bottom=thin_side
    )

    header_alignment = Alignment(vertical="center")
    body_alignment = Alignment(vertical="center", wrap_text=True)

    # セルに書き込み
    start_row = 2
    start_col = 2  # B列から開始

    for r, row_data in enumerate(data_list, start=start_row):
        for c, value in enumerate(row_data, start=start_col):
            cell = sheet.cell(row=r, column=c, value=value)
            cell.font = font

            if r == 2:
                cell.fill = fill
                cell.border = header_border
                cell.alignment = header_alignment
            else:
                if c in [2, 4]:  # B列、D列
                    if r == 3:
                        cell.border = row3_b_d_border
                    else:
                        cell.border = body_b_d_border
                    cell.alignment = body_alignment

                elif c == 3:  # C列
                    if r == 3:
                        cell.border = row3_c_border
                    else:
                        cell.border = body_c_border
                    cell.alignment = body_alignment

                elif c == 5:  # E列
                    cell.border = body_e_border
                    cell.alignment = Alignment(vertical="center")


def split_to_new_sheets(book, source_sheet, key_index, keep_main_sheet_format=False):
    HEADER_ROW_NO = 2
    READ_START_ROW_NO = 3

    # 見出し行をリスト化(A列の空欄も含める)
    header_row_values = []
    start_column = max(1, source_sheet.min_column - 1)
    for i in range(start_column, source_sheet.max_column + 1):
        header_row_values.append(source_sheet.cell(HEADER_ROW_NO, i).value)

    # データ行を振り分け
    for row in source_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)

            # アップロードされた最終形に合わせて、性別シートのみ既定の行高・列幅をそろえる
            if keep_main_sheet_format:
                to_sheet.sheet_format.defaultRowHeight = source_sheet.sheet_format.defaultRowHeight
                to_sheet.sheet_format.defaultColWidth = source_sheet.sheet_format.defaultColWidth

            to_sheet.append(header_row_values)

        to_sheet.append(row_values)


def make_workbook():
    folder_path = pathlib.Path(__file__).parent / "workbooks"
    folder_path.mkdir(exist_ok=True)
    save_path = folder_path / "Chapter1-5.xlsx"

    workbook = Workbook()
    sheet = workbook.active

    # 元の一覧シートを作成(Chapter1-4の完成状態)
    create_main_sheet(sheet)

    # Chapter1-5本文の結果(性別ごとのシート)
    split_to_new_sheets(
        book=workbook,
        source_sheet=sheet,
        key_index=2,   # 性別(C列)
        keep_main_sheet_format=True
    )

    # Chapter1-5練習問題の結果(年齢区分ごとのシート)
    split_to_new_sheets(
        book=workbook,
        source_sheet=sheet,
        key_index=4,   # 年齢区分(E列)
        keep_main_sheet_format=False
    )

    workbook.save(save_path)
    print(f"{save_path} を作成しました。")


if __name__ == "__main__":
    make_workbook()
Q
(※)コードの保存場所について

コピーしたコードは以下の階層になるように保存して下さい。

この理由については、Chapter1-2 の記事で詳しく解説しています。

業務自動化学習/			  # 学習フォルダ
 ├── Chap1/				 # チャプター1の保存フォルダ
 │   ├── Chap1-6/		# チャプター1-6の保存フォルダ
 │   │   ├── Chapter1-6.py
 │   │   ├── make_workbook1-5.py # ☆ここに保存
 │   │   └── workbooks/
 │   │       ├── Chapter1-5.xlsx 
 │   │       └── outputs/ 
勉強猫
勉強猫

Chapter1-5から続けて学習している人は、ExcelファイルをコピーしてChapter1-6のworkbooksフォルダに貼り付けよう!

サンプルコード|テンプレート複製と個別保存の最小実装

ここでは、名簿からメンバー名を読み込み、Excelテンプレートをもとに個別のファイルを自動で生成するプログラムを紹介します。

import openpyxl, pathlib
file_path = pathlib.Path(__file__).parent / "workbooks" # 読み込むファイルの保存場所
output_path = file_path / "outputs"                  	# 新規出力するファイルの保存場所
output_path.mkdir(exist_ok=True)                        # フォルダがない場合は作成

read_book = openpyxl.load_workbook(file_path / "Chapter1-5.xlsx")
sheet = read_book.active

INPUT_COLUMN_NO = 2     # データを入力するセル
READ_START_ROW_NO = 3   # データ読み込みを開始する行

# Chapter1-5.xlsx内の名前の列を取得してリスト化
members = []
for row_no in range(READ_START_ROW_NO, sheet.max_row+1):
    name = sheet.cell(row_no, INPUT_COLUMN_NO).value
    if name is None:
        break
    members.append(name)

# メンバーごとにテンプレートをコピーして保存
copy_book = openpyxl.load_workbook(file_path / "Chapter1-5.xlsx")
copy_sheet = copy_book.active
for member in members:
    copy_sheet.cell(1, 2).value = f"メンバーリスト:{member} 様"	 # 先頭の行に書き込み
    copy_book.save(output_path / f"{member} 様.xlsx")			# 新規ブックとして保存

このコードを実行すると、新規フォルダ “outputs” が作成され、その中にリストの人数分(20人分)のExcelブックが新規作成されます。

各ブックにはメンバーのリストがコピーされており、先頭の行には各メンバーの名前が記入されているはずです。

ブックを直接開き、結果を確認して下さい。

コード解説|前処理(フォルダ/名簿)と出力処理(複製/保存)

それでは、上のコードを部分ごとに解説していきます。

フォルダを自動作成する|pathlib.Path.mkdir()の基本

output_path = file_path / "outputs"	# 新規出力するファイルの保存場所
output_path.mkdir(exist_ok=True)		# フォルダがない場合は作成

今回は沢山のブックを一斉に作成するため、保存場所を分けています。

ベースであるChapter1-5.xlsxがあるフォルダ内に outputs という名前のフォルダを新規作成し、その中に作成するブックを保存します。

pathlibライブラリPath.mkdir()メソッド は、Pythonコード内から新しいディレクトリ(フォルダ)を作成するメソッドです。

キーワード引数として exist_ok=True を指定することで、そのディレクトリがすでに存在していてもエラーを出さずにスルーします。

名簿データをリスト化|リスト化して後続処理に渡す

# Chapter1-5.xlsx内の名前の列を取得してリスト化
members = []
for row_no in range(READ_START_ROW_NO, sheet.max_row+1):
    name = sheet.cell(row_no, INPUT_COLUMN_NO).value
    if name is None:
        break
    members.append(name)

Excelの名簿から名前を順番に読み込み、membersリストに格納しています。

このmembersリストは、このあとのファイル複製時に使用されます。

テンプレートをコピーして個別ファイルを一括保存

# メンバーごとにテンプレートをコピーして保存
copy_book = openpyxl.load_workbook(file_path / "Chapter1-5.xlsx")
copy_sheet = copy_book.active

for member in members:
    copy_sheet.cell(1, 2).value = f"メンバーリスト:{member} 様"	 # 先頭の行に書き込み
    copy_book.save(output_path / f"{member} 様.xlsx")			# 新規ブックとして保存

まず、コピー用のテンプレートとして新たに Chapter1-5.xlsx を読み込みます。

その後、membersリストを使って一人ずつ名前を書き込み、個別の名称で保存していきます。

ループを繰り返すことで、全員分のExcelファイルが一気に出力されます。

まとめ|Excelテンプレートの複製処理を使いこなそう

今回の記事では、これまで学んできた Excelの読み込み・書き込み に加えて、以下の新しい要素を体験しました。

  • mkdir(exist_ok=True) を使ってプログラム内でフォルダを自動作成する方法
  • テンプレートをコピーして編集し、名簿をもとに複数ファイルを一斉に生成する方法

これらを組み合わせることで、単なる「Excel操作」から一歩進んで、実際の業務を効率化する自動化スクリプト が作れるようになりました。

Chapter1はここで完結です。

Chapter2では、このようなPythonスクリプトを、Pythonがなくても使える実行形式(EXEファイル)に変換し、本格的な自動化ツールとして配布できるようにしていきます。

より高度な自動化も色々とできるようになりますので、是非このまま学習を進めて下さい。

練習問題|Excelファイルの大量複製を体験しよう

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

問題|Excelブックの作成と複製コードを作ろう

新しいExcelブックを作成し、内容を書き込んで保存しましょう。

その後、別のブックに名前リストを保存し、そのリストを使って最初のブックを複製し、名前ごとのファイルを作成してください。

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

  • 新しいブックを作成し、任意の内容を書き込んでテンプレートとして保存
  • 別のブックを作成し、名前のリストを保存
    例:田中, 佐藤, 鈴木, 高橋
  • 名前リストを読み込んでテンプレートを複製し、各名前を反映させたブックを作成

ヒント|コードの構成と穴埋め問題化

1からコードを組み立てることが難しい場合は、以下のヒントを開いて参考にしましょう。

Q
ヒント① コードの構成を見る

正解のコードは上から順に以下のような構成となっています。

1.作業用フォルダの準備をする
 ・import を使ってライブラリを読み込む
 ・pathlib.Path(__file__).parent で現在のファイルの場所を取得できる
 ・.mkdir(exist_ok=True) を使うとフォルダがなければ自動で作れる

2.テンプレートとなる新しいExcelブックを作成する
 ・openpyxl.Workbook() で新しいブックを作成できる
 ・sheet.title でシート名を変更できる
 ・sheet["セル番地"] = 値 でセルに文字を書き込める

3.名前リストを新しいExcelブックに書き込む
 ・Workbook() で新しいブックを作成できる
 ・.cell(row, column).value でセルに値を代入できる
 ・for 文でリストの要素を順番に処理できる

4.保存した名前リストを読み込んでリストに取り込む
 ・load_workbook() で既存のブックを読み込める
 ・sheet.max_row でシートの最終行番号を取得できる
 ・.append() でリストに要素を追加できる

5.テンプレートを複製し、名前を差し込んで個別のファイルを作成する
 ・for 文でリストの要素を順番に処理できる
 ・load_workbook() で既存のブックを読み込める
 ・セル参照 = 値 の形式でセルに文字を書き込める

Q
ヒント② 穴埋め問題にする

以下のコードをコピーし、穴埋め部に適切なコードを書きこんで下さい。

import openpyxl, pathlib

# フォルダの設定
file_path = pathlib.Path(__file__).parent / "workbooks"
output_path = file_path / "Training1-6"
'''(穴埋め)フォルダを作成するコードを書いてください'''

# --- ① 最初のブックを作成 ---
main_book = '''(穴埋め)ブックの作成'''
main_sheet = main_book.active
'''(穴埋め)シートのタイトルを指定してください'''
main_sheet["A1"] = "これはテンプレートです"
main_sheet["B2"] = "ここに名前が入ります"
main_book.save(output_path / "template.xlsx")

# --- ② リストを別のブックに保存 ---
names = ["田中", "佐藤", "鈴木", "高橋"]

list_book = openpyxl.Workbook()
list_sheet = list_book.active
list_sheet.title = "メンバーリスト"
row_no = 1  # Excelは1行目から始まるので初期値を1にする
for name in names:
    list_sheet.'''(穴埋め)'''(row_no, 1).value = name
    row_no += 1  # 行番号を1つずつ増やす
list_book.save(output_path / "names.xlsx")

# --- ③ リストを読み込み、テンプレートを複製 ---
# 名前リストを読み込む
list_book = openpyxl.load_workbook(output_path / "names.xlsx")
list_sheet = list_book.active
members = []
'''(穴埋め)for文を使ってリストの全ての行を読み取り、membersに追加する処理を書いてください'''

# テンプレートを複製して名前を差し込む
for member in members:
    copy_book = openpyxl.load_workbook(output_path / "template.xlsx")
    copy_sheet = copy_book.active
    copy_sheet["B2"] = f"{member} 様"
    copy_book.'''(穴埋め)'''

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

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

Q
正解コード例
import openpyxl, pathlib

# フォルダの設定
file_path = pathlib.Path(__file__).parent / "workbooks"
output_path = file_path / "Training1-6"
output_path.mkdir(exist_ok=True)

# --- ① 最初のブックを作成 ---
main_book = openpyxl.Workbook()
main_sheet = main_book.active
main_sheet.title = "メイン"
main_sheet["A1"] = "これはテンプレートです"
main_sheet["B2"] = "ここに名前が入ります"
main_book.save(output_path / "template.xlsx")

# --- ② リストを別のブックに保存 ---
names = ["田中", "佐藤", "鈴木", "高橋"]

list_book = openpyxl.Workbook()
list_sheet = list_book.active
list_sheet.title = "メンバーリスト"
row_no = 1  # Excelは1行目から始まるので初期値を1にする
for name in names:
    list_sheet.cell(row_no, 1).value = name
    row_no += 1  # 行番号を1つずつ増やす
list_book.save(output_path / "names.xlsx")

# --- ③ リストを読み込み、テンプレートを複製 ---
# 名前リストを読み込む
list_book = openpyxl.load_workbook(output_path / "names.xlsx")
list_sheet = list_book.active
members = []
for i in range(1, list_sheet.max_row + 1):
    value = list_sheet.cell(i, 1).value
    members.append(value)

# テンプレートを複製して名前を差し込む
for member in members:
    copy_book = openpyxl.load_workbook(output_path / "template.xlsx")
    copy_sheet = copy_book.active
    copy_sheet["B2"] = f"{member} 様"
    copy_book.save(output_path / f"{member} 様.xlsx")
Q
正解コードの解説

作業用フォルダの準備

import openpyxl, pathlib

# フォルダの設定
file_path = pathlib.Path(__file__).parent / "workbooks"
output_path = file_path / "Training1-6"
output_path.mkdir(exist_ok=True)

まず、必要なライブラリを読み込みます。
openpyxl は Excel ファイルを操作するため、pathlib はファイルやフォルダの場所を扱うために使います。
次にプログラムが作業するフォルダを指定します。もしそのフォルダが存在しない場合は、自動的に新しく作られるようにしています。
これで以降の処理でファイルを保存してもエラーにならないように準備が整います。

テンプレートとなる新しいExcelブックを作成

# --- ① 最初のブックを作成 ---
main_book = openpyxl.Workbook()
main_sheet = main_book.active
main_sheet.title = "メイン"
main_sheet["A1"] = "これはテンプレートです"
main_sheet["B2"] = "ここに名前が入ります"
main_book.save(output_path / "template.xlsx")

新しいExcelファイルを作成します。
その中で最初に開かれるシートを取得し、シートの名前を「メイン」に変更します。
次に、いくつかのセルに文字を書き込みます。
ここではテンプレートとして使うために、あらかじめ固定の文字を入力しておきます。
最後に、このテンプレートファイルを保存します。

名前リストを新しいExcelブックに書き込む

# --- ② リストを別のブックに保存 ---
names = ["田中", "佐藤", "鈴木", "高橋"]

list_book = openpyxl.Workbook()
list_sheet = list_book.active
list_sheet.title = "メンバーリスト"
row_no = 1  # Excelは1行目から始まるので初期値を1にする
for name in names:
    list_sheet.cell(row_no, 1).value = name
    row_no += 1  # 行番号を1つずつ増やす
list_book.save(output_path / "names.xlsx")

複数の名前を並べたリストを用意します。
次に、新しいExcelファイルを作成し、最初のシートを「メンバーリスト」という名前に変更します。
その後、リストの名前を上から順番にシートの1列目に書き込んでいきます。
行番号は1から始めて、1つ名前を書き込むごとに1行ずつ下へ移動させます。
最後にこの名前リストを保存します。

保存した名前リストを読み込んでリストに取り込む

# --- ③ リストを読み込み、テンプレートを複製 ---
# 名前リストを読み込む
list_book = openpyxl.load_workbook(output_path / "names.xlsx")
list_sheet = list_book.active
members = []
for i in range(1, list_sheet.max_row + 1):
    value = list_sheet.cell(i, 1).value
    members.append(value)

先ほど保存した名前リストのExcelファイルを開きます。
そして最初のシートを指定して、そこから1列目に書かれている名前を上から順番に読み取ります。
読み取った名前はPythonのリストに追加していき、後で利用できるようにまとめておきます。

テンプレートを複製し、名前を差し込んで個別のファイルを作成

# テンプレートを複製して名前を差し込む
for member in members:
    copy_book = openpyxl.load_workbook(output_path / "template.xlsx")
    copy_sheet = copy_book.active
    copy_sheet["B2"] = f"{member} 様"
    copy_book.save(output_path / f"{member} 様.xlsx")

先ほどの名前リストから1人ずつ名前を取り出します。
そのたびにテンプレートのExcelファイルを開き、指定したセルに名前を差し込みます。
次に、その内容を個別のファイルとして保存します。
こうすることで、リストの人数分だけ名前入りのExcelファイルを自動的に作成できます。

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

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

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

<<前のページ

業務自動化の記事一覧

次のページ>>

記事URLをコピーしました