タイトル: Excelの読み込み/書き込み操作(openpyxl編)
SEOタイトル: Python openpyxl で Excel(xlsx) を読み書きする完全ガイド(書式・数式・pandas 連携)
| この記事の要点 |
|
openpyxl とは
openpyxl は Office Open XML 形式(.xlsx / .xlsm)を読み書きできる Python ライブラリです。Microsoft Office 不要・クロスプラットフォームで動き、書式・数式・グラフ・条件付き書式まで操作可能。Python での Excel 自動化のデファクト標準です。
| ライブラリ | 対応形式 | 用途 |
|---|---|---|
| openpyxl | xlsx / xlsm | 読み書き両方・書式操作 |
| xlrd | xls のみ(2.0+) | 旧形式の読込専用 |
| xlwt | xls のみ | 旧形式の書込専用 |
| pandas | xlsx / xls / csv | 大量データ処理。内部で openpyxl を呼ぶ |
| xlsxwriter | xlsx 書込専用 | 高速・グラフ豊富、読込不可 |
| 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 保存し直す |
| 数式の計算結果が None | openpyxl は数式を評価しない → 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。書式・グラフは保持される(ピボット等は注意)。