Python Excel操作 逆引き集 | 書き込みでシートにテーブル形式を作る

Python
スポンサーリンク

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

ゴールはこうです。

「pandas の DataFrame を Excel に書き出すとき、
ただの“罫線付きの表”ではなく、Excel の“テーブル機能(フィルタ付きのあれ)”として出したい」

Excel の「テーブル」は、見た目が整うだけでなく、

フィルタボタンが自動で付く
行を追加しても数式が自動で伸びる
スタイル(帯状の色など)が一括で変えられる

といったメリットがあります。

これをコードから作るのが、xlsxwriteradd_table です。
pandas と組み合わせるときは、

engine="xlsxwriter"
to_excel でデータを書き出す
worksheet.add_table(...) でその範囲をテーブル化する

という流れになります。


一番シンプルな「DataFrame → テーブル」の例

最小コードで全体像をつかむ

import pandas as pd

df = pd.DataFrame({
    "日付": ["2025-01-01", "2025-01-02", "2025-01-03"],
    "商品": ["りんご", "みかん", "バナナ"],
    "金額": [1000, 800, 1200]
})

with pd.ExcelWriter("table_basic.xlsx", engine="xlsxwriter") as writer:
    df.to_excel(writer, sheet_name="売上", index=False)

    workbook  = writer.book
    worksheet = writer.sheets["売上"]

    rows = len(df)
    cols = len(df.columns)

    first_row = 0
    first_col = 0
    last_row = first_row + rows
    last_col = first_col + cols - 1

    worksheet.add_table(
        first_row,
        first_col,
        last_row,
        last_col,
        {
            "columns": [{"header": col} for col in df.columns],
            "style": "Table Style Medium 9"
        }
    )
Python

このコードを実行すると、「売上」シートの A1 から C4 までが、
Excel の“テーブル”として認識されます(フィルタボタン付き・スタイル付き)。

ここから、重要な部分を順番にかみ砕いていきます。


add_table の「範囲指定」を理解する

行・列は 0 始まりで指定する

add_table の最初の 4 つの引数は、

開始行
開始列
終了行
終了列

です。すべて 0 始まりで数えます。

上の例では、

ヘッダー行を含めた範囲をテーブルにしたい
ヘッダーは 1 行目(0 行目)
データは 3 行ぶん(行数 = 3)

という前提で、こう計算しています。

rows = len(df)          # データ行数(3)
cols = len(df.columns)  # 列数(3)

first_row = 0           # ヘッダー行(1 行目)
first_col = 0           # A 列
last_row = first_row + rows      # 0 + 3 = 3(0,1,2,3 → ヘッダー+3 行)
last_col = first_col + cols - 1  # 0 + 3 - 1 = 2(A=0, B=1, C=2)
Python

つまり、add_table(0, 0, 3, 2, ...) は、

A1 から C4 までをテーブルにする

という意味になります。

ここで大事なのは、「ヘッダー行も範囲に含める」ということです。
ヘッダー行+データ行、全部まとめてテーブルの範囲にします。


columns オプションで「ヘッダー情報」を渡す

DataFrame の列名をそのままテーブルのヘッダーに使う

add_table の第 5 引数はオプションの辞書です。
その中の "columns" キーで、列ごとの設定を渡します。

一番シンプルには、こう書きます。

{
    "columns": [{"header": col} for col in df.columns]
}
Python

これは、

列ごとに {"header": 列名} の辞書を作る
それをリストにして "columns" に渡す

という形です。

to_excel(index=False) で書き出したとき、
A1, B1, C1 にはすでにヘッダー(列名)が入っていますが、
add_table にも "header" を渡しておくのが正しい使い方です。


テーブルスタイルを指定する

見た目を「Excel の標準スタイル」から選ぶ

"style" キーで、テーブルの見た目を指定できます。

"style": "Table Style Medium 9"
Python

この名前は、Excel の「テーブルデザイン」タブで選べるスタイル名と対応しています。
よく使うのは、

“Table Style Medium 2”
“Table Style Medium 9”
“Table Style Light 9”

などの “Medium” や “Light” 系です。

スタイルを指定しない場合でもテーブルにはなりますが、
色付きの帯やヘッダーの強調が欲しいなら、何かしら指定しておくと見栄えがよくなります。


実務テンプレート:集計結果をテーブルとして出す

月次集計をテーブル形式で出力する例

import pandas as pd

df = pd.read_excel("sales.xlsx", parse_dates=["日付"])
df["金額"] = pd.to_numeric(df["金額"], errors="coerce")

monthly = (
    df.assign(=df["日付"].dt.to_period("M"))
      .groupby("月", as_index=False)["金額"].sum()
)

with pd.ExcelWriter("sales_monthly_table.xlsx", engine="xlsxwriter") as writer:
    monthly.to_excel(writer, sheet_name="月次集計", index=False)

    workbook  = writer.book
    worksheet = writer.sheets["月次集計"]

    rows = len(monthly)
    cols = len(monthly.columns)

    first_row = 0
    first_col = 0
    last_row = first_row + rows
    last_col = first_col + cols - 1

    worksheet.add_table(
        first_row,
        first_col,
        last_row,
        last_col,
        {
            "columns": [{"header": col} for col in monthly.columns],
            "style": "Table Style Medium 9"
        }
    )
Python

このファイルを開くと、「月次集計」シートの表が、
フィルタ付き・帯状の色付きの“テーブル”として扱われます。

フィルタで特定の月だけ絞り込んだり、
テーブル全体を選択してグラフを作ったり、
Excel 側の操作が一気にやりやすくなります。


startrow / startcol と組み合わせる

シートの途中からテーブルを置きたい場合

タイトル行や説明文を上に置いて、
その下からテーブルを始めたいこともあります。

例えば、「3 行目の B 列からテーブルを置きたい」なら、
to_exceladd_table の両方で位置を合わせます。

import pandas as pd

df = pd.DataFrame({
    "日付": ["2025-01-01", "2025-01-02"],
    "商品": ["りんご", "みかん"],
    "金額": [1000, 800]
})

with pd.ExcelWriter("table_offset.xlsx", engine="xlsxwriter") as writer:
    df.to_excel(
        writer,
        sheet_name="レポート",
        index=False,
        startrow=2,
        startcol=1
    )

    workbook  = writer.book
    worksheet = writer.sheets["レポート"]

    rows = len(df)
    cols = len(df.columns)

    first_row = 2
    first_col = 1
    last_row = first_row + rows
    last_col = first_col + cols - 1

    worksheet.add_table(
        first_row,
        first_col,
        last_row,
        last_col,
        {
            "columns": [{"header": col} for col in df.columns],
            "style": "Table Style Medium 9"
        }
    )
Python

ここでは、

3 行目(startrow=2)・B 列(startcol=1)から DataFrame を書き出す
同じ位置から add_table の範囲を指定する

というふうに、位置を揃えています。


よくあるつまずきポイント

engine=”xlsxwriter” を忘れると add_table が使えない

worksheet.add_table は XlsxWriter の機能です。
ExcelWriter(..., engine="xlsxwriter") を指定していないと、
writer.bookwriter.sheets[...] が XlsxWriter のオブジェクトにならず、
add_table が呼べません。

「テーブルを作るときは、必ず engine=’xlsxwriter’」
これはセットで覚えてください。

範囲指定を間違えるとヘッダーが二重になったり、行が欠けたりする

add_table の範囲には「ヘッダー行も含める」必要があります。
last_rowfirst_row + rows - 1 にしてしまうと、
ヘッダー行がテーブルに含まれず、Excel 側でヘッダーを勝手に作られてしまいます。

ヘッダー+データ行数、という意識で last_row を計算するのがポイントです。


小さな練習アイデア

自分で小さな DataFrame を作って、

1 回目は普通に to_excel だけ
2 回目は、ここで紹介した add_table 付き

の 2 パターンを出力して、Excel で開いてみてください。

フィルタボタンの有無、スタイルの違い、
テーブルとして選択したときの挙動などを比べると、
「ただの表」と「テーブル」の差が体感でわかります。

そこまで見えたら、
「このシートはテーブルにしておくと、あとで誰が触っても楽だな」
という設計の目線が自然に育っていきます。

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