Python | ファイル・OS 操作:Excel 書き込み(openpyxl)

Python Python
スポンサーリンク

概要(openpyxlで「Excelを書き出す」基本と落ちない勘所)

openpyxlは.xlsxのExcelをPythonから生成・追記・整形できるライブラリです。初心者がまず掴むべき流れは「Workbookを作る→シートを選ぶ→セルへ書く→保存」。重要ポイントは「改行コード・ファイル保存の扱い」「大量行の高速書き込み」「数式・日付・書式・列幅などの基本整形」「既存ブックへの追記時の安全策」。この勘所を押さえると、レポート生成や集計出力が短く安全に作れます。


基本の書き込み(ここが重要)

新規ファイルを作成してセルへ書く

from openpyxl import Workbook

wb = Workbook()           # 新規ブック作成(メモリ上)
ws = wb.active            # 先頭シート
ws.title = "Report"       # シート名変更

ws["A1"] = "名前"
ws["B1"] = "年齢"
ws["C1"] = "都市"

ws.append(["田中", 28, "東京"])   # 行末に1行追加
ws.append(["鈴木", 35, "大阪"])

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

A1表記の代わりに、行列番号でも書けます。

ws.cell(row=3, column=1, value="佐藤")   # C3ではなく「3行1列=A3」に値
Python

既存ファイルへ追記する

from openpyxl import load_workbook

wb = load_workbook("output.xlsx")
ws = wb["Report"]     # 既存シートを開く
ws.append(["加藤", 22, "名古屋"])
wb.save("output.xlsx")  # 上書き保存
Python

追記はappendが簡単。特定セルを書き換えるならA1表記やcellで指定します。


よく使う整形(書式・幅・結合・固定・数式)

文字の太字、色、背景、行高さ・列幅

from openpyxl.styles import Font, PatternFill, Alignment

ws["A1"].font = Font(bold=True, color="FFFFFF")                 # 太字・文字色(白)
ws["A1"].fill = PatternFill("solid", fgColor="4F81BD")          # 背景(青)
ws["A1"].alignment = Alignment(horizontal="center")             # 中央寄せ

ws.row_dimensions[1].height = 22                                # 1行目の高さ
ws.column_dimensions["A"].width = 18                            # A列の幅
ws.column_dimensions["B"].width = 10
ws.column_dimensions["C"].width = 18
Python

数値の表示形式(通貨・小数・パーセント)

ws["D1"] = "売上"
ws["D2"] = 123456.789
ws["D2"].number_format = "#,##0.00"   # 3桁区切り・小数2桁

ws["E1"] = "達成率"
ws["E2"] = 0.835
ws["E2"].number_format = "0.0%"       # パーセント表示
Python

日付・時刻の書式

from datetime import datetime

ws["F1"] = "日付"
ws["F2"] = datetime(2025, 12, 15, 17, 11)
ws["F2"].number_format = "yyyy-mm-dd hh:mm"   # 表示形式
Python

セル結合、ヘッダー固定、オートフィルタ

ws.merge_cells("A1:C1")                  # A1〜C1を結合(先頭セルに値)
ws.freeze_panes = "A2"                   # 1行目を固定(A2より上を固定)
ws.auto_filter.ref = "A1:E100"           # フィルタ範囲(見出し行必須)
Python

Excelの数式を書き込む

ws["G1"] = "合計"
ws["G2"] = "=SUM(D2:D100)"              # 数式は文字列のまま入れる
Python

Python側で計算した結果を書きたいなら、数式ではなく値を直接入れます。


実務向けの安全設計(保存・上書き・存在確認・テンポラリ)

保存先の親フォルダを確実に作る

from pathlib import Path
from openpyxl import Workbook

out = Path("reports/summary.xlsx")
out.parent.mkdir(parents=True, exist_ok=True)

wb = Workbook()
wb.active.title = "Summary"
wb.save(out)
Python

上書きリスクを避ける(別名・タイムスタンプ)

from datetime import datetime
from openpyxl import Workbook

wb = Workbook()
ts = datetime.now().strftime("%Y%m%d_%H%M%S")
wb.save(f"output_{ts}.xlsx")   # 例:output_20251215_1711.xlsx
Python

既存チェック・読み取り専用との併用

from pathlib import Path
from openpyxl import load_workbook

src = Path("input.xlsx")
if not src.exists():
    raise FileNotFoundError("入力ファイルがありません")

wb = load_workbook(src, read_only=False)  # 追記・編集するならFalse
ws = wb.active
Python

大量データの高速書き込み(WriteOnlyWorkbook と append)

WriteOnlyモードでストリーム書き

大量行(数万〜数十万)を書き込むなら、WriteOnlyモードを使うとメモリと速度に有利です。

from openpyxl import Workbook

wb = Workbook(write_only=True)
ws = wb.create_sheet(title="Big")
ws.append(["id", "name", "value"])   # ヘッダー

for i in range(1, 100_001):
    ws.append([i, f"user_{i}", i * 1.5])

wb.save("big.xlsx")
Python

WriteOnlyではセルオブジェクトを保持しないため、後から個別セルの書式設定は基本できません。必要な書式は行生成時にCellオブジェクトを作って付与します。

通常モードでも「append中心」で速く

from openpyxl import Workbook
wb = Workbook(); ws = wb.active

rows = [
    ["id", "name", "value"],
    [1, "a", 10.0],
    [2, "b", 20.5],
]
for r in rows:
    ws.append(r)

wb.save("small.xlsx")
Python

セルを1つずつ書くより、行単位(append)でまとめて流す方が速く、コードも短くなります。


応用の基本(画像・グラフ・テーブル)

画像の貼り付け

from openpyxl import Workbook
from openpyxl.drawing.image import Image

wb = Workbook(); ws = wb.active
img = Image("logo.png")        # PNG/JPEG等
ws.add_image(img, "A5")        # A5セル位置へ
wb.save("with_image.xlsx")
Python

簡単なグラフ作成

from openpyxl import Workbook
from openpyxl.chart import BarChart, Reference

wb = Workbook(); ws = wb.active
ws.append(["月", "売上"])
for m, v in [("1月", 120), ("2月", 150), ("3月", 180)]:
    ws.append([m, v])

chart = BarChart()
data = Reference(ws, min_col=2, min_row=1, max_row=4)   # 売上列
cats = Reference(ws, min_col=1, min_row=2, max_row=4)   # 月
chart.add_data(data, titles_from_data=True)
chart.set_categories(cats)
ws.add_chart(chart, "E2")

wb.save("chart.xlsx")
Python

テーブル(ListObject風の範囲)

from openpyxl import Workbook
from openpyxl.worksheet.table import Table, TableStyleInfo

wb = Workbook(); ws = wb.active
ws.append(["id", "name", "value"])
for i in range(1, 6):
    ws.append([i, f"user_{i}", i*1.2])

tab = Table(displayName="Users", ref="A1:C6")
tab.tableStyleInfo = TableStyleInfo(name="TableStyleMedium9", showRowStripes=True)
ws.add_table(tab)

wb.save("table.xlsx")
Python

例題で身につける(定番から一歩先まで)

例題1:レポートを整形して出力(見出し・幅・数値書式)

from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill
wb = Workbook(); ws = wb.active; ws.title = "Sales"

ws.append(["商品", "数量", "単価", "金額"])
for row in ws["A1:D1"]:
    for c in row:
        c.font = Font(bold=True, color="FFFFFF")
        c.fill = PatternFill("solid", fgColor="4F81BD")

items = [("コーヒー", 10, 350.0), ("紅茶", 8, 280.0)]
for name, qty, price in items:
    amount = qty * price
    ws.append([name, qty, price, amount])

ws.column_dimensions["A"].width = 16
ws.column_dimensions["B"].width = 8
ws.column_dimensions["C"].width = 10
ws.column_dimensions["D"].width = 12
ws["C2"].number_format = "#,##0.00"
ws["D2"].number_format = "#,##0.00"
ws["C3"].number_format = "#,##0.00"
ws["D3"].number_format = "#,##0.00"

wb.save("sales_report.xlsx")
Python

例題2:大量行を高速に吐き出す(WriteOnly)

from openpyxl import Workbook
wb = Workbook(write_only=True); ws = wb.create_sheet("Export")
ws.append(["id", "ts", "value"])
for i in range(1, 200_001):
    ws.append([i, f"2025-12-15T17:{i%60:02d}", i * 0.1])
wb.save("export.xlsx")
Python

例題3:既存ブックへ安全に追記(存在確認付き)

from pathlib import Path
from openpyxl import load_workbook

path = Path("output.xlsx")
if not path.exists():
    raise FileNotFoundError("output.xlsx がありません")

wb = load_workbook(path)
ws = wb.active
ws.append(["新規行", 123, "追加メモ"])
wb.save(path)
Python

例題4:数式と固定表示で見やすい帳票

from openpyxl import Workbook
wb = Workbook(); ws = wb.active

ws.append(["日付", "売上"])
ws.append(["2025-12-14", 120])
ws.append(["2025-12-15", 150])
ws.append(["合計", None])
ws["B4"] = "=SUM(B2:B3)"     # 合計セルへ数式
ws.freeze_panes = "A2"        # 見出し固定

wb.save("sheet_sum.xlsx")
Python

まとめ

Excel書き込みの核心は「セルへ値・数式を入れる」「整形(フォント・書式・幅)で読みやすくする」「安全に保存・追記する」の3点です。少量なら通常モード+append、超大量ならWriteOnlyでストリーム書き。日付はdatetime+number_format、数値はnumber_formatで見栄えを整え、結合や固定・オートフィルタで帳票品質を上げる。保存前には親フォルダを作り、既存上書きは別名や時刻を付けてリスク低減。これを型にすれば、初心者でも“短く・見やすく・壊れない”Excel出力ができます。

タイトルとURLをコピーしました