- 必要なライブラリをインストール
pip install pandas xlsxwriter openpyxl
- pandas + XlsxWriter で条件付き書式を使う
import pandas as pd
# 1) CSV を読み込む
df = pd.read_csv('input.csv')
# 2) ExcelWriter を使って書き出し(engine='xlsxwriter')
with pd.ExcelWriter('output.xlsx', engine='xlsxwriter') as writer:
df.to_excel(writer, index=False, sheet_name='Sheet1')
workbook = writer.book
worksheet = writer.sheets['Sheet1']
# ───────────────
# 罫線フォーマット
# ───────────────
border_fmt = workbook.add_format({
'border': 1, # 全辺に細線
})
# 列幅を自動調整しつつ、各セルに罫線を適用
worksheet.set_column('A:Z', None, border_fmt)
# ───────────────
# 条件付き書式:A列が 10 より大きい → 赤背景
# ───────────────
red_fill = workbook.add_format({
'bg_color': '#FFC7CE', # 薄い赤
})
# データ部が A2 から A(行数+1) まで
last_row = len(df) + 1
worksheet.conditional_format(
f'A2:A{last_row}',
{
'type': 'cell',
'criteria': '>',
'value': 10,
'format': red_fill
}
)
# ───────────────
# 別の条件例:B列が文字列 “NG” → 黄色背景
# ───────────────
yellow_fill = workbook.add_format({'bg_color': '#FFEB9C'})
worksheet.conditional_format(
f'B2:B{last_row}',
{
'type': 'text',
'criteria': 'containing',
'value': 'NG',
'format': yellow_fill
}
)
ポイント
- set_column('A:Z', None, border_fmt) で A〜Z 列まで罫線を設定。必要なら範囲を狭めてください
- conditional_format なら Excel 側にルールが残るので、あとで手動変更も可能です
- openpyxl でセル単位にスタイルを手動で当てる
XlsxWriter の条件付き書式では難しい、 より細かい独自ルールがある場合はこちらがおすすめです。
import pandas as pd
from openpyxl import Workbook
from openpyxl.styles import PatternFill, Border, Side
# 1) pandas で読み込んでから openpyxl ワークブックを作成
df = pd.read_csv('input.csv')
wb = Workbook()
ws = wb.active
ws.title = 'Sheet1'
# ヘッダー書き込み
ws.append(list(df.columns))
# データ書き込み
for row in df.itertuples(index=False):
ws.append(row)
# フォーマット定義
red_fill = PatternFill(fill_type='solid', start_color='FFCCCC', end_color='FFCCCC')
thin_side = Side(border_style="thin", color="000000")
border = Border(left=thin_side, right=thin_side, top=thin_side, bottom=thin_side)
# 2) セルを1つずつ巡回してスタイル設定
for row in ws.iter_rows(min_row=2, max_row=ws.max_row,
min_col=1, max_col=ws.max_column):
for cell in row:
# 数値が 10 より大きければ赤背景
if isinstance(cell.value, (int, float)) and cell.value > 10:
cell.fill = red_fill
# どんなセルにも罫線を
cell.border = border
# 3) 保存
wb.save('styled_openpyxl.xlsx')
ポイント
- PatternFill で好きな色の塗りつぶしが可能
- Border/Side で罫線スタイルを細かく制御
- ループ内で if による任意の条件判定ができる
テスト用ダミーデータ
No,都道府県名,最高気温,最低気温,日の出時刻,日没時刻
1,北海道,23.6,12.7,07:00,17:09
2,青森県,31.2,30.4,05:17,18:43
3,岩手県,17.5,11.7,06:17,17:12
4,宮城県,15.4,6.9,05:53,17:56
5,秋田県,19.6,7.5,06:28,17:24
6,山形県,32.9,29.6,05:36,17:25
7,福島県,17.1,10.0,06:30,18:50
8,茨城県,28.8,7.3,06:05,18:22
9,栃木県,19.0,14.3,05:48,17:43
10,群馬県,31.8,13.0,06:23,18:46
11,埼玉県,24.2,13.7,06:49,17:18
12,千葉県,26.7,16.2,06:24,17:55
13,東京都,27.5,24.3,05:40,18:34
14,神奈川県,18.5,9.2,05:11,18:47
15,新潟県,16.1,14.4,05:46,18:04
16,富山県,19.0,17.8,05:26,16:55
17,石川県,34.2,12.3,06:36,17:42
18,福井県,33.0,17.4,05:00,16:41
19,山梨県,24.4,11.6,05:03,18:27
20,長野県,19.5,16.9,05:08,18:17
21,岐阜県,18.6,5.4,06:36,18:42
22,静岡県,19.9,18.2,05:16,17:50
23,愛知県,22.2,19.9,06:33,17:55
24,三重県,21.8,20.3,05:56,17:37
25,滋賀県,17.4,14.5,06:56,16:55
26,京都府,26.5,8.8,05:02,18:24
27,大阪府,24.2,16.9,05:01,17:06
28,兵庫県,26.3,6.7,06:18,16:47
29,奈良県,17.5,11.3,06:27,18:46
30,和歌山県,24.2,12.1,05:57,16:53
31,鳥取県,17.1,6.9,05:44,16:58
32,島根県,16.0,10.5,06:14,18:08
33,岡山県,26.4,16.1,06:03,16:57
34,広島県,20.4,18.8,06:50,17:17
35,山口県,31.1,25.4,06:47,17:22
36,徳島県,26.7,7.2,05:22,17:32
37,香川県,26.7,14.0,05:03,16:55
38,愛媛県,17.0,8.0,05:49,18:12
39,高知県,23.5,13.3,06:22,18:17
40,福岡県,28.2,24.0,06:25,17:12
41,佐賀県,17.4,12.5,06:50,18:58
42,長崎県,15.3,13.4,05:20,17:43
43,熊本県,18.2,8.1,06:27,17:37
44,大分県,30.6,11.8,06:14,17:56
45,宮崎県,31.9,13.5,05:02,18:42
46,鹿児島県,32.8,8.0,06:42,18:09
47,沖縄県,17.7,8.8,05:18,17:23
不定形なCSVの場合
出力条件,,,,,
国,,日本
取得日,,20250425
,
No,都道府県名,最高気温,最低気温,日の出時刻,日没時刻
1,北海道,23.6,12.7,07:00,17:09
2,青森県,31.2,30.4,05:17,18:43
--省略--
import csv
from openpyxl import Workbook
from openpyxl.styles import PatternFill, Border, Side
# 1) CSV を全部読み込む
with open('input.csv', newline='', encoding='utf-8') as f:
reader = csv.reader(f)
rows = list(reader)
# 2) Workbook 作成&シート取得
wb = Workbook()
ws = wb.active
# 3) 全行を順に書き出し(1行目~)
for row in rows:
ws.append(row)
# 4) 書式定義
red_fill = PatternFill(fill_type='solid', start_color='FFC7CE', end_color='FFC7CE')
thin_side = Side(border_style='thin', color='000000')
border = Border(left=thin_side, right=thin_side, top=thin_side, bottom=thin_side)
# 5) データ部(6行目=Excel上の row=6 から最終行まで)にだけ書式を適用
max_row = len(rows)
# 5行目(Excel行=5)がヘッダーなので、その下(6行目)から
for row_cells in ws.iter_rows(min_row=6, max_row=max_row,
min_col=1, max_col=len(rows[4])): # rows[4] はヘッダー行の列数
for cell in row_cells:
# 罫線
cell.border = border
# 数値かどうか試して、10超なら赤背景
try:
if float(cell.value) > 10:
cell.fill = red_fill
except (TypeError, ValueError):
pass
# 6) 保存
wb.save('styled_output.xlsx')
# 書式定義
red_fill = PatternFill(fill_type='solid', start_color='FFC7CE', end_color='FFC7CE')
thin = Side(border_style='thin', color='000000')
border = Border(left=thin, right=thin, top=thin, bottom=thin)
# データ部:Excelの6行目から最終行まで(ヘッダーは5行目まで)
for row_cells in ws.iter_rows(min_row=6, max_row=ws.max_row,
min_col=1, max_col=ws.max_column):
for cell in row_cells:
# まずは全セルに罫線
cell.border = border
# 列番号を取得(openpyxl >= 2.6 なら .column で整数が返る)
col_idx = cell.column
# 11列目以降だけ処理
if col_idx > 10:
# グループ n を計算(0:11~20列, 1:21~30列, …)
n = (col_idx - 11) // 10
# グループ内の相対位置 r を計算(1~10)
# 11列 → r=1, 12列 → r=2, … 20列 → r=10
r = col_idx - 10 - 10*n
# r==2 または r>=4 のときだけ色塗り
if r == 2 or (4 <= r <= 10):
cell.fill = red_fill
# --- 前提:Workbook, ws, red_fill, border などは既存の定義のまま ---
for row_cells in ws.iter_rows(min_row=6, max_row=ws.max_row,
min_col=1, max_col=ws.max_column):
for cell in row_cells:
# まずは全セルに罫線
cell.border = border
col_idx = cell.column
# 11列目以降のみ処理
if col_idx > 10:
# グループ n を計算(0:11~20列, 1:21~30列, …)
n = (col_idx - 11) // 10
# グループ内の相対位置 r を計算(1~10)
r = col_idx - 10 - 10 * n
# r==1 のセルを基準値として取得
# グループ先頭列 = 10 + 10*n + 1
base_col = 10 + 10 * n + 1
base_cell = ws.cell(row=cell.row, column=base_col)
# 値を数値に変換して差分をチェック
try:
current = float(cell.value)
base = float(base_cell.value)
if current - base >= 5.5:
cell.fill = red_fill
except (TypeError, ValueError):
# 非数値セルはスキップ
pass
色塗りロジック追加
流れのまとめ
①書式定義:pink_fill、blue_fill、green_fill を追加
②ループ内で r == 3 判定
- 同じグループの r=4~10 を走査
- 差分に応じて 2,1,0,-1,-2 ポイント付与
- 合計ポイントに従い、r == 3 セルに塗りつぶし
- 既存の r == 2/r >= 4 ロジック はそのまま elif に
これで、r==3 の列にはグループの傾向を色で可視化できるようになります。
from openpyxl.styles import PatternFill, Border, Side
# ────────────
# 書式定義
# ────────────
red_fill = PatternFill(fill_type='solid', start_color='FFC7CE', end_color='FFC7CE')
pink_fill = PatternFill(fill_type='solid', start_color='FFC0CB', end_color='FFC0CB') # ピンク
blue_fill = PatternFill(fill_type='solid', start_color='ADD8E6', end_color='ADD8E6') # 青
green_fill = PatternFill(fill_type='solid', start_color='90EE90', end_color='90EE90') # 緑
thin_side = Side(border_style='thin', color='000000')
border = Border(left=thin_side, right=thin_side, top=thin_side, bottom=thin_side)
# ────────────
# データ行のループ
# ────────────
for row_cells in ws.iter_rows(min_row=6, max_row=ws.max_row,
min_col=1, max_col=ws.max_column):
for cell in row_cells:
# ① まずは全セルに罫線
cell.border = border
col_idx = cell.column
if col_idx <= 10:
continue
# グループ番号 n と相対位置 r を計算
n = (col_idx - 11) // 10
r = col_idx - 10 - 10 * n
# 基準値セル(r==1)の取得
base_col = 10 + 10 * n + 1
base_cell = ws.cell(row=cell.row, column=base_col)
# ────────────
# r==3 のとき:グループ内 r=4~10 のスコアを合計し、その合計で色分け
# ────────────
if r == 3:
total = 0
for offset in range(4, 11):
c = ws.cell(row=cell.row, column=10 + 10 * n + offset)
try:
diff = float(c.value) - float(base_cell.value)
except (TypeError, ValueError):
continue
if diff >= 5.5:
pts = 2
elif diff >= 2.5:
pts = 1
elif diff < -5.5:
pts = -2
elif diff < -2.5:
pts = -1
else:
pts = 0
total += pts
# 合計ポイントで色分け
if total > 5:
cell.fill = red_fill
elif total > 2:
cell.fill = pink_fill
elif total > -2:
# 塗りつぶしなし
pass
elif total > -4:
cell.fill = blue_fill
else:
cell.fill = green_fill
# ────────────
# 既存ロジック:r==2 または r>=4 のセル単体の判定
# ────────────
elif r == 2 or (4 <= r <= 10):
try:
current = float(cell.value)
base = float(base_cell.value)
if current - base >= 5.5:
cell.fill = red_fill
except (TypeError, ValueError):
pass