この記事でわかること

  • pandasで書き出したExcelの、列の幅を決める方法
  • 売上に桁区切り、前年比にパーセントの表示を付ける方法
  • スクロールしても見出しの行が残るように固定する方法
  • 列にまとめて付けた書式が、数字の見た目に効かない理由

Pythonで集計した表をExcelに書き出すと、列の幅が狭くて数字が「###」と表示されたり、売上に桁区切りが付いていなかったりします。毎回Excelで開いて手で直すのは手間です。ここでは、書き出しのときに列の幅と数字の見た目まで整えるやり方を、作り物の集計の表で実際に試した結果を添えて紹介します。

根拠は、pandas 3.1.0の公式のAPIリファレンス(to_excelとExcelWriter)と、openpyxlの公式の資料(スタイルの使い方と列の幅)です(2026年10月30日に原文で確認)。例に使う店舗・売上・前年比は、どれもこの記事のために作った値です。

先に結論: 書き出した後に、セルに1つずつ書式を付ける

先に結論を書くと、pandasで表を書き出した直後に、openpyxlのシートを受け取り、列の幅を決めて、数字のセルに1つずつ書式を付けます。 見出しの固定は、to_excelのfreeze_panesで指定できます。

整えたいこと 使うもの
列の幅 column_dimensions
桁区切り・% number_format
見出しの固定 freeze_panes

pandasでシートを受け取る

pandasのExcelWriterを使うと、to_excelで書き出した後のシートを受け取れます。pandasの資料では、ExcelWriterはブロックを抜けると自動で閉じる書き方(コンテキストマネージャー)で使うものとしていて、閉じたときにファイルが保存されます。sheetsという属性で、シートの名前からシートを取り出せます。

xlsxを書き出すときの道具(engine)は、何も指定しないとXlsxWriterが入っていればそれが使われ、入っていなければopenpyxlが使われます。この記事のコードはopenpyxlのやり方で書いているので、engine="openpyxl"を指定しています。

数字の見た目を整える(number_format)

openpyxlでは、セルのnumber_formatに書式の文字を入れると、数字の見た目が変わります。資料では、"0.00"で小数2桁で表示する例が示されています。売上には"#,##0"(桁区切り)、前年比には"0.0%"(パーセント)のように指定します。Excelの資料によると、パーセントの表示形式はセルの値を100倍して%を付けて表示するので、前年比は1.05のような比のままにしておきます。

注意したいのは、列や行にまとめて付けた書式です。openpyxlの資料では、列や行に付けた書式は、ファイルを閉じた後にExcelで作られるセルにだけ効き、表全体に付けたいときはセルに1つずつ付けるとしています。書き出した数字のセルには、1つずつ付けます。

見出しの行を固定する(freeze_panes)

to_excelのfreeze_panesに、固定する一番下の行と一番右の列を、1から数えた番号の組で渡します。(1, 0)とすると、1行目の見出しだけが固定されます。

手順: 集計の表を、書式を整えて別のファイルに書き出す

次のコードは、架空の集計の表 summary.xlsx(店舗・売上・前年比の3列)を読み込み、summary_formatted.xlsxとして書き出します。書き出した後に、列の幅を決め、売上に桁区切り、前年比にパーセントの書式を付けます。summary.xlsxは書き換えません。自分の表に合わせるときは、シートの名前・列の位置・幅の3つを変えてください。

import pandas as pd

# 集計の表を読み込む(summary.xlsx そのものは変えない)
summary = pd.read_excel("summary.xlsx")

with pd.ExcelWriter("summary_formatted.xlsx", engine="openpyxl") as writer:
    # 1行目の見出しを固定して書き出す
    summary.to_excel(writer, sheet_name="集計", index=False, freeze_panes=(1, 0))
    ws = writer.sheets["集計"]

    # 列の幅を決める
    ws.column_dimensions["A"].width = 12
    ws.column_dimensions["B"].width = 14
    ws.column_dimensions["C"].width = 10

    # 2行目から下の売上と前年比のセルに、1つずつ書式を付ける
    for sales_cell, ratio_cell in ws.iter_rows(min_row=2, min_col=2, max_col=3):
        sales_cell.number_format = "#,##0"   # 売上: 桁区切り
        ratio_cell.number_format = "0.0%"    # 前年比: パーセント

pandasとopenpyxl(xlsxを読み書きする道具)は、あらかじめ入れておきます。前年比は、1.05のように比のままの値で入っている前提です。

実行した結果

架空の集計の表(3行。売上は7桁までの整数、前年比は1.052のような比)で動かしました。

  • 書き出したsummary_formatted.xlsxを読み直すと、2行目から下の売上には桁区切り(#,##0)、前年比にはパーセント(0.0%)の書式が付き、見出しの行は書式なし(General)のままでした
  • 見出しの行は固定され、列の幅はA・B・Cの順に12・14・10になりました
  • セルの値そのものは変わらず、売上は整数、前年比は1.052のままでした
  • 読み込んだsummary.xlsxのほうは、実行の前後でバイト単位で同じでした

動作を確かめたのは、Macの作業PC(Python 3.12.15、pandas 3.1.0、openpyxl 3.1.5)です。

自分で直すか、相談するかの判断

判断の目安は、「その表を、計算に使うか、見るだけか」です。見るだけの報告の表なら、この記事のように見た目を整えれば十分です。

ほかの人がその表で計算を続けるなら、数字を丸めて書き出すと、合計が合わなくなることがあります。見た目だけを変える書式にとどめ、どこまで丸めてよいかは、表を使う人に確かめてから決めます。

つまずきやすいところ

  • 列にまとめて書式を付ける: 架空の表で、列に桁区切りの書式を付けただけでは、書き出した売上のセルは「General」のままでした。セルに1つずつ付けます
  • float_formatで丸めてしまう: 前年比をfloat_format="%.1f"で書き出すと、1.052が1.1として保存され、値そのものが変わりました。見た目だけを変えるならnumber_formatを使います
  • 百倍した値にパーセントを付ける: 前年比が105のように入っていると、Excelはパーセントの書式で値を100倍して表示するため、10500.0%になります。架空の表でも、値は105のまま書式だけが付きました
  • openpyxlのやり方なのに、道具を指定しない: XlsxWriterが入っている環境では、書き出しにXlsxWriterが使われ、この記事のcolumn_dimensionsなどの書き方が合わなくなります。engine="openpyxl"を指定します
  • 集計してから書き出したいとき: 行と列の2つの項目で合計した表の作り方は、PythonでExcelのピボットテーブルのように集計する手順で紹介しています
  • 毎週の集計表まで自動で作りたいとき: 決まった形の集計表を毎週作る流れは、Excelの定型レポートを自動化する手順にまとめています
  • 店舗ごとにシートを分けて書き出したいとき: 分け方は、PythonでExcelの表を条件で分けて別々のシートに保存する手順で紹介しています

まとめ

  • 書き出した直後にExcelWriterのsheetsからシートを受け取り、列の幅と書式を整えます
  • 数字の見た目はnumber_formatで変え、セルに1つずつ付けます。列にまとめて付けても、書き出したセルには効きません
  • 見出しの行は、to_excelのfreeze_panes=(1, 0)で固定できます
  • float_formatは値そのものを丸めるため、計算に使う表では見た目だけを変える書式を使います