8.

Python openpyxl で Excel(xlsx) を読み書きする完全ガイド(書式・数式・pandas 連携)

編集
この記事の要点
  • openpyxl は xlsx / xlsm を読み書きする Python ライブラリ。pip install openpyxl で導入
  • 読込: wb = load_workbook("file.xlsx")ws = wb.active または wb["Sheet1"]
  • 書込: ws["A1"] = "hello" / ws.cell(row=1, column=1, value=...)wb.save("out.xlsx")
  • 書式: Font / PatternFill / Border / Alignment をセルに代入。数式は文字列で "=SUM(A1:A10)"
  • 旧形式 xls は xlrd(2.0+ で xlsx 非対応)。大量データは pandas.read_excel + openpyxl エンジン、または write_only=True

openpyxl とは

openpyxl は Office Open XML 形式(.xlsx / .xlsm)を読み書きできる Python ライブラリです。Microsoft Office 不要・クロスプラットフォームで動き、書式・数式・グラフ・条件付き書式まで操作可能。Python での Excel 自動化のデファクト標準です。

ライブラリ対応形式用途
openpyxlxlsx / xlsm読み書き両方・書式操作
xlrdxls のみ(2.0+)旧形式の読込専用
xlwtxls のみ旧形式の書込専用
pandasxlsx / xls / csv大量データ処理。内部で openpyxl を呼ぶ
xlsxwriterxlsx 書込専用高速・グラフ豊富、読込不可
pywin32すべてWindows で Excel 本体を操作(COM)

インストール

pip install openpyxl

# pandas と組み合わせる場合
pip install pandas openpyxl

読み込み

from openpyxl import load_workbook

# ワークブック読込
wb = load_workbook("sample.xlsx")

# シート一覧
print(wb.sheetnames)         # ["Sheet1", "Sheet2"]

# アクティブシート(最後に保存時にアクティブだったシート)
ws = wb.active

# 名前で指定
ws = wb["Sheet1"]

# セル参照(A1 表記)
print(ws["A1"].value)

# セル参照(行列指定)
print(ws.cell(row=1, column=1).value)

# 範囲を 2 次元リストに
for row in ws["A1:C10"]:
    for cell in row:
        print(cell.value, end="\t")
    print()

# 全行を回す
for row in ws.iter_rows(min_row=2, values_only=True):
    print(row)   # (値1, 値2, 値3, ...) のタプル

# 列で回す
for col in ws.iter_cols(min_col=1, max_col=3, values_only=True):
    print(col)

書き込み

from openpyxl import Workbook

wb = Workbook()
ws = wb.active
ws.title = "売上"

# 単一セル
ws["A1"] = "商品名"
ws["B1"] = "単価"
ws["C1"] = "数量"
ws["D1"] = "小計"

# 行で追加(最も簡単)
data = [
    ("リンゴ", 150, 10),
    ("バナナ", 80, 20),
    ("ミカン", 100, 15),
]
for row in data:
    ws.append(row)

# 数式
for r in range(2, 5):
    ws.cell(row=r, column=4, value=f"=B{r}*C{r}")

# シート追加
ws2 = wb.create_sheet(title="集計", index=0)
ws2["A1"] = "合計"
ws2["B1"] = "=SUM(売上!D2:D4)"

# 保存
wb.save("output.xlsx")

書式設定

from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter

wb = Workbook()
ws = wb.active

# ヘッダ行
headers = ["ID", "名前", "金額"]
for col_idx, h in enumerate(headers, start=1):
    cell = ws.cell(row=1, column=col_idx, value=h)
    # フォント
    cell.font = Font(name="メイリオ", size=11, bold=True, color="FFFFFF")
    # 背景色
    cell.fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid")
    # 配置
    cell.alignment = Alignment(horizontal="center", vertical="center")
    # 罫線
    thin = Side(border_style="thin", color="000000")
    cell.border = Border(top=thin, bottom=thin, left=thin, right=thin)

# 列幅
ws.column_dimensions["A"].width = 8
ws.column_dimensions["B"].width = 20
ws.column_dimensions["C"].width = 12

# 行高
ws.row_dimensions[1].height = 24

# 表示形式(数値書式)
ws["C2"] = 1234567
ws["C2"].number_format = "#,##0"     # 1,234,567
ws["D2"] = 0.1234
ws["D2"].number_format = "0.00%"     # 12.34%

# セル結合
ws.merge_cells("A5:C5")
ws["A5"] = "合計エリア"

wb.save("styled.xlsx")

大量データ書込: write_only モード

数万行レベルの書込はメモリと速度が問題になります。write_only=Trueストリーミング書込すると数倍速くなります:

from openpyxl import Workbook

# write_only モード
wb = Workbook(write_only=True)
ws = wb.create_sheet("data")

# ヘッダ
ws.append(["id", "name", "value"])

# 10 万行
for i in range(100_000):
    ws.append([i, f"name_{i}", i * 1.5])

wb.save("big.xlsx")

pandas との連携

import pandas as pd

# 読込(内部で openpyxl 使用)
df = pd.read_excel("sales.xlsx", sheet_name="Sheet1", engine="openpyxl")

# 加工
df["amount"] = df["unit"] * df["qty"]
summary = df.groupby("category")["amount"].sum().reset_index()

# 書込(複数シート)
with pd.ExcelWriter("out.xlsx", engine="openpyxl") as writer:
    df.to_excel(writer, sheet_name="明細", index=False)
    summary.to_excel(writer, sheet_name="集計", index=False)

よくあるトラブル

症状原因と対処
InvalidFileException.xls(旧形式)を読もうとした → xlrd を使うか、Excel で xlsx 保存し直す
数式の計算結果が Noneopenpyxl は数式を評価しない → load_workbook(data_only=True) で Excel が最後に計算した値を読む
マクロが消える.xlsm を読込→保存時は keep_vba=True
大量データで激重書込は write_only=True、読込は read_only=True + iter_rows(values_only=True)
画像/グラフが消えるopenpyxl はグラフを保持するが、未対応書式はある。複雑な帳票は xlsxwriter 検討

FAQ

Q: xls(旧形式)を扱いたい
A: openpyxl は xlsx 専用。pip install xlrd==1.2.0(古いバージョンのみ xls 対応)、または事前に Excel で xlsx 保存し直す。

Q: 数式の値を取りたい
A: load_workbook(file, data_only=True)。ただしこれはExcel が最後に保存した時点の計算結果を返すだけ。Python で再計算する場合は formulas ライブラリや libreoffice --headless --convert-to xlsx 検討。

Q: テンプレートに値を埋めて出力したい
A: load_workbook("template.xlsx") で開いて編集 → 別名 save。書式・グラフは保持される(ピボット等は注意)。

編集
Post Share
子ページ

子ページはありません

同階層のページ
  1. 環境構築
  2. 文法
  3. フレームワーク
  4. ライブラリ
  5. バージョンの確認
  6. エラー一覧
  7. Webスクレイピング
  8. Excelの読み込み/書き込み操作(openpyxl編)
  9. Excelのセルの値を読み込む方法(xlrd編)
  10. ローカルで独立して動くPythonプログラムとパッケージの事前インストール方法
  11. プログラム実行時のパスを取得