Python WebAcademy Blog

Pythonのopenpyxlとは?Excelファイルの読み書きを自動化する基本を初心者向けに解説

|

Pythonのopenpyxlを、IT初心者向けにやさしく解説します。インストールから読み込み、セルの指定の仕方、iter_rowsでの一括読み取り、新しいブックへの書き出し、数式が計算されない理由、pandasとの使い分け、大きなファイルを扱うread_onlyモードまで。手元で動かせるコードと表を並べながら、毎月のExcel作業を自動化する第一歩を順番に整理していきます。

毎月おなじExcelファイルを開いて、おなじ列をコピーして、おなじ集計をする。そんな作業に心当たりはありませんか。

一度きりなら手でやったほうが早い。でも毎月となると話は別です。

Pythonを学び始めた人が最初に効果を実感しやすいのが、まさにこのExcel作業の自動化です。手元にある見慣れたファイルが題材になるので、動いたときの手応えがまるで違います。

その入り口になるのがopenpyxlというライブラリです。Excelを起動しなくても、ファイルの中身をPythonから直接読み書きできます。

この記事では、openpyxlの基本と、初心者がつまずきやすいところを順番に整理していきます。

openpyxlは、Excelファイルを直接さわる道具

まずは立ち位置から確認しましょう。openpyxlは、Excelのファイルそのものを読み書きするライブラリです。

Excelアプリを裏で動かしているわけではありません。ファイルの中身を組み立てたり読み解いたりしているだけなので、Excelが入っていないサーバーでも動きます。

扱えるのは新しい形式だけ、という点だけ先に押さえてください。公式の説明では、対応するのはxlsx・xlsm・xltx・xltmの4つです。

拡張子ごとの対応をまとめておきます。手元のファイルがどれか、先に確認しておくと安心です。

拡張子 中身 openpyxlで扱えるか
.xlsx Excel 2007以降の標準的なブック 扱える
.xlsm マクロを含むブック 扱える(マクロ自体は実行しない)
.xltx / .xltm テンプレート 扱える
.xls Excel 2003以前の古い形式 扱えない
.csv ただのテキスト 対象外(標準ライブラリのcsvを使う)

古い .xls が出てきたら、いったんExcelで開いて .xlsx として保存し直すのが一番早い解決策です。

拡張子がcsvのファイルなら、そもそもopenpyxlの出番はありません。文字コードの落とし穴も含めて、こちらで詳しく扱っています。【関連記事】Pythonのcsvモジュールとは?表データの読み書きと文字化けの防ぎ方を初心者向けに解説

インストールと、読み込みの3行

openpyxlは標準ライブラリではないので、まずインストールが必要です。pipで入れます。

pip install openpyxl

インストールが済んだら、読み込みは驚くほど短く書けます。ブックを開いて、シートを選んで、セルの値を取るだけです。

from openpyxl import load_workbook

wb = load_workbook("売上.xlsx")
ws = wb["8月"]          # シート名で選ぶ
# ws = wb.active        # 開いたときに表示されるシートでよければこちら

print(ws["B2"].value)   # セルB2の値
print(ws.title)         # 8月
print(ws.max_row)       # データが入っている最終行

load_workbook() が返すのがブック、つまりファイル全体です。そこからシートを取り出し、シートからセルを取り出す。この入れ子の関係さえつかめば、あとは応用です。

3行目の .value を忘れる人がとても多いところです。ws["B2"] はセルという入れ物そのものなので、中身がほしいときは必ず .value を付けてください。

ライブラリを入れるときは、プロジェクトごとに仮想環境を分けておくと後々ラクになります。【関連記事】Pythonの仮想環境(venv)って何のためにある?プロジェクトごとに混ぜない管理法

セルの指定には2つの書き方がある

セルを指すやり方は1つではありません。Excelでおなじみの表記と、行と列の番号で指す表記があります。

慣れないうちは混乱しますが、使い分けの基準はとてもはっきりしています。

print(ws["A1"].value)                 # Excelと同じ表記
print(ws.cell(row=1, column=1).value) # 行と列の番号で指定

for row in range(2, 6):
    name = ws.cell(row=row, column=1).value
    price = ws.cell(row=row, column=2).value
    print(name, price)

決め打ちで特定のセルを見るなら ws["A1"] が読みやすい。ループで動かすなら ws.cell() のほうが素直に書けます。

ここでPythonの常識とひとつだけ違う点があります。行番号も列番号も1から始まります。

リストのように0から数えると、1行ずつずれた結果が返ってきます。私は10年ほどエンジニアとして開発に関わってきましたが、久しぶりにopenpyxlを触ると今でも最初の一回はずらします。エラーにならず静かに1行ずれるので、気づくのが遅れるのが厄介なところです。

行ごとにまとめて読むならiter_rows

1セルずつ取るコードは、行数が増えると読みにくくなります。表として一気に読みたいときは iter_rows() が便利です。

for row in ws.iter_rows(min_row=2, max_row=5, values_only=True):
    print(row)
# ('りんご', 120, 30)
# ('みかん', 80, 45)

values_only=True を付けると、セルではなく値のタプルが返ってきます。表計算のデータを扱いたいだけなら、ほとんどの場面でこれで足ります。

min_row=2 としているのは、1行目の見出しを飛ばすためです。読み取りの起点を指定できるので、ヘッダー付きの表がそのまま扱えます。

新しいブックを作って書き出す

読むだけでなく、作るほうも簡単です。空のブックを用意して、行を足して、保存します。

from openpyxl import Workbook

wb = Workbook()
ws = wb.active
ws.title = "集計結果"

ws.append(["商品", "単価", "在庫"])
for item in [("りんご", 120, 30), ("みかん", 80, 45)]:
    ws.append(list(item))

ws["E1"] = "作成: 自動集計"
wb.save("結果.xlsx")

append() は、いま入っているデータの次の行にまとめて書き足すメソッドです。行番号を自分で数える必要がないので、ループとの相性がとてもよくなります。

保存するまでファイルは1バイトも変わりません。 save() を呼び忘れて、なぜ反映されないと悩む人が本当に多いところです。

もうひとつ大事な注意があります。save() は同じ名前のファイルを黙って上書きします。元データを読み込んで加工するときは、必ず別名で保存してください。

保存先のパスを組み立てるときは、文字列をつなぐより専用の道具を使ったほうが安全です。【関連記事】Pythonのpathlibとは?ファイルパス操作を初心者向けに解説

見た目を整えるところまでできる

openpyxlの強みは、値だけでなく書式も扱えることです。太字にする、色を変える、列幅を広げる。どれもコードから指定できます。

from openpyxl.styles import Font, PatternFill

ws["A1"].font = Font(bold=True, size=12)
ws["A1"].fill = PatternFill("solid", fgColor="FFF2CC")
ws.column_dimensions["A"].width = 18
ws.freeze_panes = "A2"   # 1行目を固定して見出しを残す

最後の freeze_panes は、Excelのウィンドウ枠の固定にあたる設定です。人が目で見る資料を出すときは、これがあるだけで印象が変わります。

書式まで再現できるのは、報告書の雛形を毎月配るような仕事で効いてきます。データだけ差し替えて配布する流れが、そのまま自動化できます。

数式は計算されない。ここがいちばんの落とし穴

初心者がもっとも驚くのが、この振る舞いです。openpyxlは数式を計算しません。

=SUM(B2:B10) と書かれたセルを読むと、返ってくるのは計算結果ではなく数式の文字列そのものです。openpyxlは表計算エンジンではないので、当然といえば当然の話です。

では計算結果を取りたいときはどうするか。data_only=True を付けて開きます。

wb = load_workbook("売上.xlsx", data_only=True)
ws = wb.active
print(ws["D10"].value)   # 数式ではなく、保存時の計算結果が返る

ただし、ここには条件があります。返ってくるのはExcelが最後に保存したときの計算結果、つまりキャッシュされた値です。

Pythonだけで作ったファイルや、Excelで一度も開いていないファイルには、その計算結果が保存されていません。その場合は None が返ります。

読み取り方の違いを表にしておきます。迷ったらここに戻ってきてください。

開き方 数式セルから返る値 向いている場面
load_workbook(path) 数式の文字列 数式を保ったまま編集する
load_workbook(path, data_only=True) 保存時の計算結果(無ければNone) データとして値だけ使う

私の失敗談をひとつ。月次の集計ファイルをPythonで組み立て、その中に数式を書き込んで、別のスクリプトで読み直す仕組みを作ったことがあります。手元では動くのに本番だけ結果が空になり、原因にたどり着くまでに半日かかりました。誰もExcelで開いていないファイルには、計算結果が存在しなかったのです。

計算が必要なら、Python側で計算してから値として書き込む。この順番にしておけば事故は起きません。

pandasとどう使い分けるか

Excelを扱うライブラリとしては、pandasの名前も耳にすると思います。どちらを使うべきか迷いますよね。

実は対立するものではありません。pandasが .xlsx を読むとき、裏側ではopenpyxlが動いています。

役割の違いはこう整理できます。集計や分析が主役ならpandas、ファイルそのものの形を触りたいならopenpyxlです。

やりたいこと 向いている道具
平均や合計を出す、条件で絞り込む pandas
複数の表を結合する pandas
セルの色や罫線を設定する openpyxl
既存の帳票の一部だけ書き換える openpyxl
シートの追加や削除 openpyxl

pandasは表を丸ごとデータとして扱うので、書式や図は落ちてしまいます。逆にopenpyxlで大量データの集計を書くと、コードが長くなりがちです。

データ分析寄りの使い方から知りたい方は、こちらから読んでみてください。【関連記事】pandas入門 データ処理をやってみよう

大きいファイルはread_onlyで開く

行数が数万を超えるファイルを普通に開くと、メモリを一気に使います。全セルをオブジェクトとして持つためです。

公式ドキュメントでは、こうした場面のために最適化モードが用意されています。読むだけなら read_only=True です。

wb = load_workbook("大量データ.xlsx", read_only=True)
ws = wb.active

for row in ws.iter_rows(values_only=True):
    ...  # 1行ずつ処理する

wb.close()   # read_onlyのときは明示的に閉じる

必要になった分だけ読み込む仕組みなので、メモリの使用量がほぼ一定に保たれます。そのかわり、読み込んだセルは編集できません。

close() を忘れないでください。通常のモードと違い、read_onlyでは明示的に閉じる必要があります。

書き出す側にも Workbook(write_only=True) という対になるモードがあります。行を上から順に追加していくだけなら、こちらも同じようにメモリを節約できます。

今日から使える形にまとめておく

ここまでの内容を、実際に書くときの判断だけに絞って整理します。

読むときは load_workbook()、作るときは Workbook()。この2つが入り口です。

セルの中身がほしいときは .value を付ける。行と列は1から数える。この2点さえ体に入れば、初日のつまずきはほとんど消えます。

数式のセルを値として読みたいなら data_only=True を思い出してください。返るのは保存時のキャッシュだという前提を、いつも頭の片隅に置いておきましょう。

そして集計はPython側でやる。openpyxlはあくまで、Excelファイルという入れ物を扱う道具です。

まずは手元にある1つのファイルを開いて、ws.max_row を表示するところから試してみてください。自分の仕事のデータが画面に出た瞬間、Pythonがぐっと身近になるはずです。

ここまでお読みいただきありがとうございました。

参考情報

次のアクション

記事で学んだ内容を実際に動かしてみよう

Python WebAcademyでは、ブラウザ上でコードを書きながら基礎から実践まで体系的に学べます。

Python WebAcademyの学習画面

あわせて読む

関連記事

ブログ一覧へ

Python学習ロードマップ

まずはこの3講座から

記事で気になったテーマを、順番に手を動かしながら学べます。

ロードマップを見る