Python Excel操作 逆引き集 | 書き込み時に列書式を適用する

Python
スポンサーリンク

何をしたいテクニックなのか

ゴールはこうです。

「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"
})
Python

num_format は「数値の表示形式」です。
#,##0 は「カンマ区切り・小数なし」の定番パターン。

align は「横方向の配置」で、"right" なら右寄せです。

この money_fmt は「書式の塊(フォーマットオブジェクト)」で、
あとで set_columnwrite に渡して使います。


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.bookwriter.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 で見比べてみてください。

「同じデータでも、見た目を整えるだけで“レポート感”が一気に変わる」
という感覚が入ると、このテクニックはあなたの武器になります。

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