何をしたいテクニックなのか
ゴールはこうです。
「pandas の DataFrame を Excel に書き出すとき、
特定の列に“見た目の書式”をきちんと適用したい」
たとえば、
金額は「カンマ区切り・右寄せ」
日付は「yyyy-mm-dd」
割合は「パーセント表示」
こういう“Excel らしい見た目”を、コードで一発で仕上げたいわけです。
そのために使うのが、
engine='xlsxwriter'workbook.add_format(...)worksheet.set_column(..., format_obj)
という組み合わせです。
基本パターンの全体像
最小の「金額列に書式を当てる」例
import pandas as pd
df = pd.DataFrame({
"日付": ["2025-01-01", "2025-01-02"],
"商品": ["りんご", "みかん"],
"金額": [1000, 123456]
})
with pd.ExcelWriter("styled.xlsx", engine="xlsxwriter") as writer:
df.to_excel(writer, sheet_name="売上", index=False)
workbook = writer.book
worksheet = writer.sheets["売上"]
money_fmt = workbook.add_format({
"num_format": "#,##0",
"align": "right"
})
worksheet.set_column("C:C", 12, money_fmt)
Pythonこれで、「C 列(= 金額列)」が、
カンマ区切り
右寄せ
幅 12
という書式で出力されます。
ここに、このテクニックのエッセンスが全部入っています。
add_format で「書式オブジェクト」を作る
書式は「辞書で指定 → オブジェクト化」する
workbook.add_format({...}) は、
「この条件でセルの見た目を作って」と XlsxWriter にお願いする関数です。
たとえば、金額用の書式ならこうです。
money_fmt = workbook.add_format({
"num_format": "#,##0",
"align": "right"
})
Pythonnum_format は「数値の表示形式」です。#,##0 は「カンマ区切り・小数なし」の定番パターン。
align は「横方向の配置」で、"right" なら右寄せです。
この money_fmt は「書式の塊(フォーマットオブジェクト)」で、
あとで set_column や write に渡して使います。
set_column で「列全体に書式を適用する」
列幅と書式を一気に指定する
worksheet.set_column(first_col, last_col, width, format) という形で使います。
さっきの例では、こうでした。
worksheet.set_column("C:C", 12, money_fmt)
Pythonこれは、
C 列から C 列まで
列幅 12
書式は money_fmt
という意味です。
列番号で指定することもできます。
worksheet.set_column(2, 2, 12, money_fmt) # 0:A, 1:B, 2:C
Pythonどちらでも同じですが、
「列記号でイメージしたいとき」は "C:C" の方が直感的です。
実務パターン:日付・金額・割合にそれぞれ書式を当てる
典型的な「3 種類の列書式」テンプレート
import pandas as pd
df = pd.DataFrame({
"日付": ["2025-01-01", "2025-01-02"],
"商品": ["りんご", "みかん"],
"金額": [1000, 123456],
"粗利率": [0.35, 0.428]
})
with pd.ExcelWriter("styled_report.xlsx", engine="xlsxwriter") as writer:
df.to_excel(writer, sheet_name="レポート", index=False)
workbook = writer.book
worksheet = writer.sheets["レポート"]
date_fmt = workbook.add_format({
"num_format": "yyyy-mm-dd",
"align": "center"
})
money_fmt = workbook.add_format({
"num_format": "#,##0",
"align": "right"
})
percent_fmt = workbook.add_format({
"num_format": "0.0%",
"align": "right"
})
worksheet.set_column("A:A", 12, date_fmt)
worksheet.set_column("C:C", 12, money_fmt)
worksheet.set_column("D:D", 10, percent_fmt)
Pythonこのコードで、
A 列:日付(yyyy-mm-dd・中央寄せ)
C 列:金額(カンマ区切り・右寄せ)
D 列:粗利率(パーセント表示・右寄せ)
という、かなり“レポートっぽい”見た目になります。
ここで大事なのは、
DataFrame 側では「中身(値)」に集中する
見た目(書式)は XlsxWriter 側でまとめて指定する
という役割分担です。
列名から列番号を計算して書式を当てる
「列記号を手で数えるのが面倒」なときのやり方
列が増えてくると、「C 列って何番目だっけ?」がだるくなります。
そんなときは、DataFrame の列名からインデックスを取ってきて、その番号で set_column するのが楽です。
import pandas as pd
df = pd.DataFrame({
"日付": ["2025-01-01", "2025-01-02"],
"商品": ["りんご", "みかん"],
"金額": [1000, 123456],
"粗利率": [0.35, 0.428]
})
with pd.ExcelWriter("styled_by_name.xlsx", engine="xlsxwriter") as writer:
df.to_excel(writer, sheet_name="レポート", index=False)
workbook = writer.book
worksheet = writer.sheets["レポート"]
money_fmt = workbook.add_format({
"num_format": "#,##0",
"align": "right"
})
col_idx = df.columns.get_loc("金額") # 「金額」が何番目の列か
worksheet.set_column(col_idx, col_idx, 12, money_fmt)
Pythonこうしておけば、列の順番が多少変わっても、
「列名で探して書式を当てる」ので壊れにくくなります。
よくあるつまずきポイント
engine=”xlsxwriter” を忘れると set_column が使えない
writer.book や writer.sheets[...] が XlsxWriter のオブジェクトになるのは、ExcelWriter(..., engine="xlsxwriter") と書いたときだけです。
これを忘れていると、
AttributeError: 'Worksheet' object has no attribute 'set_column'
のようなエラーになったり、
そもそも writer.book が期待した型でなかったりします。
「列書式をいじるときは、必ず engine=’xlsxwriter’」
これはセットで覚えてください。
値が文字列になっていると数値書式が効かない
num_format は「セルの値が数値」であることが前提です。
DataFrame 側で object(文字列)になっている列に数値書式を当てても、見た目は変わりません。
金額や割合の列は、事前にちゃんと数値化しておきましょう。
df["金額"] = pd.to_numeric(df["金額"], errors="coerce")
df["粗利率"] = pd.to_numeric(df["粗利率"], errors="coerce")
Pythonこの一手間で、「書式が効かない…」というハマりポイントを避けられます。
小さな練習アイデア
自分で、
日付列
金額列
割合列
を持つ小さな DataFrame を作って、
1 回目は普通に to_excel
2 回目は、ここで紹介した「列書式付き」のコードで to_excel
の 2 つを出力して、Excel で見比べてみてください。
「同じデータでも、見た目を整えるだけで“レポート感”が一気に変わる」
という感覚が入ると、このテクニックはあなたの武器になります。
