openpyxl:既存のExcelファイルにシートを追加して別ファイルからデータをコピペする

※社外のコラムニストによる記事です。Python関連の情報をお伝えします。
「シゴトがはかどるPython自動処理の教科書(著:クジラ飛行机様/マイナビ出版)」を利用して、Pythonを使った自動化について学んでいきます。
前回は、顧客一覧用のExcelファイルから、必要なデータをコピーして新しいExcelに貼り付ける、という2つのExcelブックを行き来してデータを操作する方法を学びました。 今回は、前回使用した顧客一覧から条件で抽出したデータを既にあるExcelの別のシートにコピペするという作業を学びます。
目次
既存のExcelファイルにシートを作って、別のExcelから必要なデータを振分けコピペするまでを自動化
データを取り出す元となるExcelファイルは、前回と同じもの(all-customer.xlsx)を使用します。そして、取り出したデータを転記する先も、前回、新たに作成したExcelファイル(spilit_sheet.xlsx)を使用します。
前回と違う点は新しいExcelファイルを作成して転記するか、それとも既存のExcelファイルに別のシートを作って転記するかです。では早速コードを見ていきます。
P.80
購入プランごとに顧客を異なるシートに分けてみましょう。
これを実現する方法ですが、顧客一覧を上から読んでいって、プランごとのシートを開いてそこに情報を追記していく処理を行います。もし該当するシートがなければ新規作成して追記します。以下が、そのプログラムです。
import openpyxl as excel
# 顧客一覧のブックを開いて顧客一覧ページを得る --- (*1)
book = excel.load_workbook("all-customer.xlsx")
sheet = book["名簿"]
# 顧客一覧を確認してシートに分ける --- (*2)
for row in sheet.iter_rows(min_row=3):
cells = [v.value for v in row]
if cells[0] is None: break
print(cells)
# 各列のデータを変数に代入 --- (*3)
(name,area,plan) = cells
# コピー先のシート名を決める --- (*4)
sname = plan+"プラン"
# 該当するシートがあるか --- (*5)
if sname not in book.sheetnames:
to_sheet = book.create_sheet(title=sname)
to_sheet.append(["名前","住所","プラン"])
else:
to_sheet = book[sname]
# 該当シートに顧客情報を追記 --- (*6)
to_sheet.append(cells)
# ファイルに書き込む --- (*7)
book.save("split_sheet.xlsx")
このプログラムはall-customer.xlsx 内にある顧客名簿から、split_sheet.xlsxにプランの名前を付けたシートを追加し、そこに転記していくというものです。シートが重複してしまうと困るので、該当の名前の付いたシートがあるかを確認し、ある場合には該当のシートの最後尾に追記、なければ新たにシートを追加して書き込んでいくという形が取られています。
出来上がるのはこんな感じのファイルです。

openpyxlの.append()を使うという意味
基本的にほとんどのコードはこれまで出てきたようなものばかりなので詳細な説明は省略しますが、一点気になったところが。
P.81
6ではシートに情報を追記します。ワークシートのメソッドappendは今回、初めて使います。これは、ワークシートの末尾に値を追記します。
「ワークシートのメソッドappendは初めて」、という部分です。
append自体はリストに要素を追加するために使用されるメソッドで、前回も使用しています。なのに「初」とは何か、しかも「ワークシートの」とわざわざついています。
結論だけまずは書いておくと、appendが対象とするオブジェクトがこれまでとは違う、ということになります。まずは該当部分を比較してみます。
<前回>
customers.append(values)
→データを一旦Pythonのlist(ここではcustomers)にまとめた後にExcelに書き込んでいました。
<今回>
to_sheet.append(cells)
→条件で振り分けたデータを都度Excelのワークシートに書き込んでいました。
というわけで、前者はPythonのメソッドであるappendを使用していますが、後者はopenpyxlのメソッドであるappendを使い、都度Excelに直接書き込んでいました。つまり…別の機能に対してデータが追加されており、動作の対象が異なるということになります。
今回のコードもPythonのリストを使って処理することもできます。
ただ、前回の場合は一つのシートに対して条件に合うデータを追記していくものであったため、一度Pythonのリストにまとめてしまってから処理をした方が、Excelにアクセスする回数が少なくて済むため、効率的です。
一方、今回はデータをいくつかのシートに条件に応じて振り分ける形になるため、Excelに都度直接書き込んだ方が、複数のリストを作る必要がない上、リストを経由する必要もないので効率的です。
Pythonのリストを経由せず、Excelに直接書き込む場合の注意点としては、書き込み以前・書き込み中のソートや書式などの編集ができないこと、Excelシートに設定されたヘッダーの数と書き込みたい要素の数が合わない場合、対応する列に空白が入ってしまったり、余分な列が作られて値が入れられてしまったりということがあります。
例えば、ヘッダーが3つなのに書き込む要素が2つしかない場合、3列目のセルは空白のままになります。逆に、ヘッダーよりも多い要素をappendした場合は、余分なデータがヘッダー外の列(4列目以降など)に追加されてしまいます。作る前の確認が重要ですね。
今回もお付き合いいただき、ありがとうございました。
Pythonの自動化で業務の効率化を図りたい方は、グローバルウェイに依頼してみてはいかがでしょうか?興味がある方は以下をご覧の上、是非お問い合わせください。

