pandas で Excel ファイルを読み書きする(openpyxl 連携)

業務では Excel ファイルでデータをやり取りする機会が多いです。pandas は Excel ファイルの読み書きに対応していますが、内部で使うライブラリによって機能や挙動が異なります。ここでは openpyxl を使った Excel 連携を解説します。

必要なライブラリ

pandas 単体では Excel を扱えません。読み書きには追加のライブラリが必要です。

# インストール
# pip install openpyxl

import pandas as pd

# openpyxl がインストールされていれば自動的に使われる
df = pd.read_excel('data.xlsx')

Excel 関連のライブラリは複数あり、用途によって使い分けます。

ライブラリ対応形式用途
openpyxl.xlsx読み書き両対応、書式設定可
xlrd.xls古い形式の読み込み専用
xlsxwriter.xlsx書き込み専用、高機能

現在は openpyxl が最も汎用的で、pandas のデフォルトエンジンにもなっています。

基本的な読み込み

import pandas as pd

# 基本の読み込み
df = pd.read_excel('data.xlsx')

# シートを指定
df = pd.read_excel('data.xlsx', sheet_name='Sheet1')

# シート番号で指定(0始まり)
df = pd.read_excel('data.xlsx', sheet_name=0)

複数シートを一度に読み込むこともできます。

# 全シートを辞書で取得
all_sheets = pd.read_excel('data.xlsx', sheet_name=None)
print(all_sheets.keys())
# dict_keys(['Sheet1', 'Sheet2', 'Sheet3'])

# 特定の複数シートを読み込み
sheets = pd.read_excel('data.xlsx', sheet_name=['Sheet1', 'Sheet3'])

読み込みオプション

実務の Excel ファイルは、1 行目がヘッダーでないことも多いです。さまざまなオプションで対応できます。

# ヘッダー行を指定(0始まり)
df = pd.read_excel('data.xlsx', header=2)  # 3行目がヘッダー

# ヘッダーなし
df = pd.read_excel('data.xlsx', header=None)

# 読み込む行をスキップ
df = pd.read_excel('data.xlsx', skiprows=5)  # 最初の5行をスキップ

# 特定の行をスキップ(リストで指定)
df = pd.read_excel('data.xlsx', skiprows=[0, 2, 4])

# 読み込む行数を制限
df = pd.read_excel('data.xlsx', nrows=100)

列の指定も柔軟にできます。

# 特定の列のみ読み込み
df = pd.read_excel('data.xlsx', usecols='A:C')  # A〜C列
df = pd.read_excel('data.xlsx', usecols='A,C,E')  # A, C, E列
df = pd.read_excel('data.xlsx', usecols=[0, 2, 4])  # インデックス指定

# 列名で指定
df = pd.read_excel('data.xlsx', usecols=['名前', '金額'])

データ型の指定

Excel から読み込むと、意図しない型変換が起きることがあります。dtype パラメータで明示的に指定できます。

# 型を指定して読み込み
df = pd.read_excel('data.xlsx', dtype={
    '社員番号': str,  # 先頭ゼロを保持
    '金額': float,
    'フラグ': bool
})

日付列は自動認識されますが、うまくいかない場合は parse_dates を使います。

# 日付列を指定
df = pd.read_excel('data.xlsx', parse_dates=['登録日', '更新日'])

# 複数列を結合して日付に
df = pd.read_excel('data.xlsx', parse_dates={'日時': ['日付', '時刻']})
自動型推論

便利だが、文字列の数字が数値になったり、先頭ゼロが消えたりする

dtype 指定

意図した型で読み込める。特に ID やコードは str 指定が安全

基本的な書き込み

import pandas as pd

df = pd.DataFrame({
    '名前': ['田中', '佐藤', '鈴木'],
    '点数': [85, 92, 78]
})

# 基本の書き込み
df.to_excel('output.xlsx', index=False)

# シート名を指定
df.to_excel('output.xlsx', sheet_name='成績表', index=False)

index=False を指定しないと、DataFrame のインデックスが A 列に出力されます。多くの場合は不要なので False にします。

複数シートへの書き込み

複数の DataFrame を別々のシートに書き込むには ExcelWriter を使います。

import pandas as pd

df1 = pd.DataFrame({'A': [1, 2, 3]})
df2 = pd.DataFrame({'B': [4, 5, 6]})

with pd.ExcelWriter('output.xlsx', engine='openpyxl') as writer:
    df1.to_excel(writer, sheet_name='データ1', index=False)
    df2.to_excel(writer, sheet_name='データ2', index=False)

既存ファイルにシートを追加する場合は mode=‘a’ を指定します。

# 既存ファイルにシートを追加
with pd.ExcelWriter('output.xlsx', engine='openpyxl', mode='a') as writer:
    df3.to_excel(writer, sheet_name='データ3', index=False)

書式設定との連携

pandas の to_excel は書式設定に限界があります。細かい書式が必要な場合は、openpyxl を直接使います。

import pandas as pd
from openpyxl import load_workbook
from openpyxl.styles import Font, Alignment, PatternFill

# まず pandas で基本データを書き込み
df = pd.DataFrame({
    '商品': ['りんご', 'みかん', 'バナナ'],
    '価格': [150, 100, 200]
})
df.to_excel('output.xlsx', index=False)

# openpyxl で書式を追加
wb = load_workbook('output.xlsx')
ws = wb.active

# ヘッダーに書式を設定
for cell in ws[1]:
    cell.font = Font(bold=True, color='FFFFFF')
    cell.fill = PatternFill('solid', fgColor='4472C4')
    cell.alignment = Alignment(horizontal='center')

# 列幅を調整
ws.column_dimensions['A'].width = 15
ws.column_dimensions['B'].width = 10

wb.save('output.xlsx')

テンプレートへの書き込み

業務では、書式設定済みのテンプレートにデータを流し込むことが多いです。

from openpyxl import load_workbook
import pandas as pd

# テンプレートを開く
wb = load_workbook('template.xlsx')
ws = wb.active

# DataFrame を準備
df = pd.DataFrame({
    '名前': ['田中', '佐藤'],
    '金額': [10000, 20000]
})

# 特定のセルからデータを書き込み
start_row = 5  # 5行目から
for i, row in df.iterrows():
    ws.cell(row=start_row + i, column=2, value=row['名前'])
    ws.cell(row=start_row + i, column=3, value=row['金額'])

wb.save('output.xlsx')
pandas の to_excel

シンプルなデータ出力に最適。書式は最低限のみ。

openpyxl 直接操作

細かい書式設定、テンプレート活用、セル結合などが必要な場合に使う。

パフォーマンスの注意点

Excel ファイルの読み書きは CSV に比べて遅いです。大量データを扱う場合は注意が必要です。

import pandas as pd
import time

# 大きなデータ
df = pd.DataFrame({'A': range(100000), 'B': range(100000)})

# Excel書き込み
start = time.time()
df.to_excel('large.xlsx', index=False)
print(f"Excel: {time.time() - start:.2f}")

# CSV書き込み
start = time.time()
df.to_csv('large.csv', index=False)
print(f"CSV: {time.time() - start:.2f}")

# Excel: 5.23秒
# CSV: 0.15秒

大量データは CSV で処理し、最終的な出力のみ Excel にするのが効率的です。