この記事でわかること

  • 条件に合うセルだけに、背景色を付けてExcelに書き出す方法
  • いちばん大きい値に色を付けるhighlight_maxの使い方
  • Excelに書き出せる色の書き方と、書き出されない書式
  • jinja2の版や、文字の混ざった列で止まるときの直し方

売上の一覧をPythonで作ってExcelに渡すとき、「基準に届かない店だけ赤くしてほしい」と頼まれることがあります。書き出した後にExcelで色を塗ると、毎回の手作業になります。この記事では、pandasのStylerで、条件に合うセルにだけ色を付けたまま、別のファイルに書き出す手順をまとめます。

調べたのは、pandas 3.1.0の公式の資料(Styler.map、Styler.highlight_max、Styler.to_excelと、ユーザーガイドのTable Visualization)で、2026年11月1日に原文に当たりました。表の店舗と売上は、確かめるために作った架空のものです。

先に結論: mapで色の指定を返し、Stylerのto_excelで書き出す

セルの値を受け取って「background-color: #ffc7ce」のような色の指定を返す関数を作り、Stylerのmapで売上の列に当てます。 書き出しは、DataFrameではなくStylerのto_excelで行います。この記事で使う道具は次の3つです。

道具 働き 記事のコード
map セルごとに色の指定を付ける 基準に届かない売上
highlight_max いちばん大きい値に色を付ける 売上の最大
to_excel 色を付けたまま書き出す index=False

Stylerのしくみ

DataFrameの.styleで、表の見た目を決めるStylerが手に入ります。pandasの資料では、mapはCSSの書式を返す関数をセルごとに当てる機能で、関数は1つの値を受け取って文字を返すとしています。何も付けないセルには、空の文字かNoneを返します。

highlight_maxは、指定した向きのいちばん大きい値のセルに、背景色を付けます。資料では、色の初期の設定は黄色で、colorで変えられるとしています。どちらも、subsetで色を付ける列を絞れます。

ユーザーガイドでは、Excelに書き出せるのは、applyとmapなどで1つずつのセルに付けた書式だとしています。表全体にまとめて付ける書式(set_table_styles)は、書き出されません。

手順: 基準に届かない売上に色を付けて書き出す

次のコードは、架空の売上の表 sales.xlsx(店舗・売上の2列)を読み、売上が50000に届かないセルを薄い赤、いちばん大きい売上を薄い緑にして、sales_marked.xlsx に書き出します。sales.xlsx には書き込みません。基準の50000は、自分の表の基準の値に置き換えて使います。

import pandas as pd

shop_sales = pd.read_excel("sales.xlsx")   # 元のファイルは読むだけ

def mark_short(value):
    # 基準に届かない売上だけ、薄い赤の背景にする(それ以外は何も付けない)
    return "background-color: #ffc7ce" if value < 50000 else ""

styled = (
    shop_sales.style
    .map(mark_short, subset=["売上"])
    .highlight_max(subset=["売上"], color="#c6efce")
)
styled.to_excel("sales_marked.xlsx", index=False)

pandasのほかに、xlsxを書き出すopenpyxlと、Stylerが使うjinja2を入れておきます。pandas 3.1.0では、jinja2は3.1.6以上が必要です。

試した結果

架空の売上の表(6行)で動かしました。売上は62000・48000・75000・31000・空欄・50000で、ちょうど50000の行と、空欄の行を入れています。

  • 48000と31000のセルに薄い赤(FFC7CE)、75000のセルに薄い緑(C6EFCE)が付きました
  • ちょうど50000の行は「届かない」に入らず、色は付きませんでした。空欄の行も色なしでした
  • 店舗の列と見出しの行には、色が付きませんでした
  • 元の sales.xlsx のハッシュ値は、実行の前後で同じでした

試した環境は、Mac の作業PCのPython 3.12.15で、pandas 3.1.0・openpyxl 3.1.5・jinja2 3.1.6を入れています。色はopenpyxlでセルの塗りを読んで確かめました。Excelのアプリで開いた見え方は、確かめていません。

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

目安は、「色を付ける基準が、1つの数で決まっているか」です。「50000に届かない」のように決まっていれば、上のコードの数を変えるだけで使えます。

店舗ごとに目標が違う、前の月と比べる、といった基準なら、関数の中身が変わります。どの値を基準にするか、ちょうど基準の値を「届かない」に入れるかを、表を受け取る人と先に決めておきます。

つまずきやすいところ

  • 「.styleにはjinja2が要る」と止まる: 試したときも、jinja2 3.1.4が入った環境では、AttributeErrorで止まりました。入っていないのではなく、pandas 3.1.0が求める3.1.6より古いためです。jinja2を3.1.6以上にすると動きました
  • 色の書き方が違う: 「rgb(255,199,206)」や、ない色の名前の「lightred」では、CSSWarningという警告が出るだけで止まらず、塗りの色は00000000になりました。#rrggbbの形で書きます
  • DataFrameのto_excelで書き出す: 色を付けたのはStylerなので、元のshop_salesのto_excelでは色は付きません。styledのto_excelを使います
  • formatで付けた桁区切りが消える: Stylerのformatで「62,000」の形にしても、書き出したセルの表示の形は「General」のままでした。セルに書式を付けるなら、mapで「number-format: #,##0」を返すと、その形が入りました。列の幅や桁区切りをまとめて整える方法は、PythonでExcel書き出しの列の幅と数値の書式を整える手順で紹介しています
  • 売上の列に文字が混ざっている: 「未入力」のような文字があると、比べるところでTypeErrorになりました。先に数に直すか、空欄にしてから色を付けます
  • 色ではなく、区分の列を足したい: 「達成」「未達」のような言葉の列を作る方法は、PythonでExcelの複数の条件から区分の列を作る手順にまとめています
  • 毎月の報告書の形まで決まっている: 見出しの色や決まった表の形を含めて、報告書をまとめて作る流れは、Excelの定型レポートを自動化する手順が参考になります

まとめ

  • 色の指定を返す関数を作り、Stylerのmapで列に当てます
  • いちばん大きい値はhighlight_maxで目立たせられます
  • 書き出しはStylerのto_excelで行い、色は#rrggbbの形で書きます
  • jinja2の版が古いと止まるので、3.1.6以上を入れます