PythonでExcelを読み書きする(openpyxl入門)
PythonでExcelファイルを操作するには「openpyxl」というライブラリを使います。VBAなしでExcelを読み込み・編集・保存する基本的な操作を、実際に動くコードで解説します。
openpyxlとは
openpyxlはPythonからExcel(.xlsx)ファイルを操作するためのライブラリです。Excelがインストールされていないサーバー上でも動作するため、スケジュール実行との相性がいいです。
インストールはコマンドプロンプトで以下を実行します。
pip install openpyxl
openpyxlでできること
- セルの読み書き・書式設定
- シートの追加・削除・コピー
- 新規Excelファイルの作成
- 既存ファイルの読み込みと編集
openpyxlでできないこと
- VBAマクロの実行
- グラフの細かい編集(基本的なグラフ作成は可能)
.xls(旧形式)の読み書き(xlrdライブラリが別途必要)
基本:Excelファイルを開いてセルを読む
import openpyxl
# Excelファイルを開く
wb = openpyxl.load_workbook("data.xlsx")
# シートを選ぶ(シート名で指定)
ws = wb["Sheet1"]
# セルの値を読む
print(ws["A1"].value) # A1セルの値
print(ws.cell(row=2, column=3).value) # 2行3列(C2)の値
# 全シート名を確認する
print(wb.sheetnames)
wb.close()
セルに値を書き込んで保存する
import openpyxl
# 既存ファイルを開く
wb = openpyxl.load_workbook("report.xlsx")
ws = wb["集計"]
# セルに値を書き込む
ws["A1"].value = "月次レポート"
ws["B1"].value = "2025年1月"
ws.cell(row=2, column=1).value = 12500 # 数値
# 書式を設定する
from openpyxl.styles import Font, PatternFill, Alignment
ws["A1"].font = Font(bold=True, size=14)
ws["A1"].fill = PatternFill(fill_type="solid", fgColor="DDDDDD")
ws["B1"].alignment = Alignment(horizontal="center")
# 同じファイルに上書き保存
wb.save("report.xlsx")
# 別名で保存する場合
wb.save("report_updated.xlsx")
wb.close()
新規Excelファイルを作成する
import openpyxl
# 新しいワークブックを作成(Sheet1が自動で作られる)
wb = openpyxl.Workbook()
ws = wb.active
ws.title = "売上データ"
# ヘッダー行を書き込む
headers = ["日付", "商品名", "数量", "単価", "合計"]
for col, header in enumerate(headers, start=1):
ws.cell(row=1, column=col).value = header
# データ行を書き込む
data = [
["2025-01-06", "商品A", 3, 1200, 3600],
["2025-01-07", "商品B", 1, 5000, 5000],
["2025-01-08", "商品A", 2, 1200, 2400],
]
for row_idx, row_data in enumerate(data, start=2):
for col_idx, value in enumerate(row_data, start=1):
ws.cell(row=row_idx, column=col_idx).value = value
wb.save("売上データ.xlsx")
wb.close()
print("ファイルを作成しました。")
全行を繰り返して処理する
import openpyxl
wb = openpyxl.load_workbook("売上データ.xlsx")
ws = wb["売上データ"]
total = 0
# 2行目から最終行まで繰り返す
for row in ws.iter_rows(min_row=2, values_only=True):
# row は (日付, 商品名, 数量, 単価, 合計) のタプル
if row[0] is None: # 空行に達したら終了
break
print(f"{row[0]} - {row[1]}: {row[4]}円")
total += row[4]
print(f"合計: {total}円")
wb.close()
values_only=True をつけると、セルオブジェクトではなく値だけが返されます。読み込み専用の処理に便利です。
openpyxlとpandasの使い分け
Excelを読み書きするライブラリとしては pandas もよく使われます。用途によって使い分けます。
| 用途 | 向いているライブラリ |
|---|---|
| データの集計・分析・フィルタリング | pandas |
| 書式・セル結合・複数シートの細かい制御 | openpyxl |
| 大量データの高速処理 | pandas |
| 既存Excelの書式を保ちながら編集 | openpyxl |
| CSVとExcelを行き来する処理 | pandas |
pandasでExcelを読む場合は pandas.read_excel() を使いますが、内部でopenpyxlを使っているため、両方インストールされている必要があります。
import pandas as pd
# pandasでExcelを読む(シンプルな集計に便利)
df = pd.read_excel("売上データ.xlsx", sheet_name="売上データ")
print(df.groupby("商品名")["合計"].sum())
# pandasでExcelに書き出す
df.to_excel("集計結果.xlsx", index=False)
実務でよく使うパターン
列の最終行を取得する
openpyxlにはVBAの End(xlUp) に相当する直接的な機能がないため、以下のようにして最終行を取得します。
# A列のデータが入っている最終行を取得
max_row = ws.max_row # シートの最終行(空行も含む)
# 実際にデータが入っている最終行を確認する
last_data_row = 0
for row in range(1, ws.max_row + 1):
if ws.cell(row=row, column=1).value is not None:
last_data_row = row
列幅を自動調整する
from openpyxl.utils import get_column_letter
for col in ws.columns:
max_length = 0
col_letter = get_column_letter(col[0].column)
for cell in col:
if cell.value:
max_length = max(max_length, len(str(cell.value)))
ws.column_dimensions[col_letter].width = max_length + 2
まとめ
openpyxlを使えば、PythonからExcelファイルの読み書き・書式設定・新規作成ができます。VBAと違い、Excelが起動していない環境でも動作するため、サーバーでのスケジュール実行との組み合わせで特に力を発揮します。集計・フィルタリングなどのデータ処理が中心であれば pandasのほうが簡単に書けるので、処理の内容によって使い分けてください。