📝

PythonでDBデータをExcel出力するには?〜pandasの基本とハマりどころ〜

に公開

はじめに

本記事は、pandasを使ってDBデータをExcelに出力する方法を整理したものです。
「とりあえず動くコードが欲しい」方から「実務で安全に使いたい」方まで参考になるようにまとめました。
DBデータを安全にExcel出力できるようになり、実務で遭遇しがちなエラーの回避方法も把握できます。

本記事では以下を扱います。

  • pandasでDBデータをExcelに出力する基本の流れ
  • engine に指定できる値の種類
  • 他ライブラリとの使い分け
  • おまけ:制御文字エラー(IllegalCharacterError)の落とし穴と回避策
  • その他のハマりやすいエラーと対処法

pandas公式ドキュメント:pandas documentation

DBデータを取得してExcelに出力する基本

DBからデータを読み込む

今回はSQLAlchemyを経由してDBからDataFrameに読み込みます。

import os
import pandas as pd
from sqlalchemy import create_engine

# DB接続(例: PostgreSQL)
# 接続情報は環境変数から取得(直書きはしない)
engine = create_engine(os.environ["DATABASE_URL"])

# SQLからDataFrameに読み込み
df = pd.read_sql("SELECT * FROM users", engine)

Excelに出力する

DataFrame.to_excel() を呼ぶだけで簡単にExcelファイルを作成できます。

df.to_excel("users.xlsx", index=False)

ここで指定している index=False は、DataFrameのインデックス(通常は行番号)を出力しない という意味です。
デフォルト(index=True)の場合は、左端にインデックス列が追加されます。

出力イメージ

index=True(デフォルト)

id name
0 1 Alice
1 2 Bob
2 3 Charlie

index=False

id name
1 Alice
2 Bob
3 Charlie

👉 単純にDBのレコードをExcelに出したい場合は index=False を指定します。

engine に指定できる値の種類

pandasの to_excel は内部で外部ライブラリ(engine)を使ってExcelファイルを扱います。

engine 説明 適したケース
openpyxl(デフォルト) .xlsx 標準の読み書きライブラリ 読み書き両対応。Excel仕様に忠実で厳格。標準利用のため。
xlsxwriter 書き込み専用の高速ライブラリ(インストール済みなら) 書式設定や制御文字回避が必要なとき。
xlwt .xls(古いExcel 97–2003形式)専用 互換性維持が必要な旧環境のみ
odf OpenDocument形式(.ods)用 LibreOffice系をターゲットにする場合

エンジンは別途インストール:openpyxl / xlsxwriter / odfpy は optional dependency。
👉 まずは openpyxl。制御文字や書式にこだわるなら xlsxwriter。LibreOfficeなら odf

Excel出力時の主なエラーと対処法

制御文字エラー

今回pandasを扱うにあたって、DBの文字列に制御文字が含まれていたためエラーが発生する事象にも遭遇しました。
DBの値を出力するという要件のため、DB自体に入りうる値については十分な考慮を行ったうえで実装する必要があります。

再現コード

import pandas as pd

# \v は垂直タブ(禁止される制御文字)
df = pd.DataFrame({"name": ["Alice", "Bob\vSmith"]})
df.to_excel("out.xlsx")  # openpyxl 使用時に例外

実行時に以下のエラーが発生します(pandas → openpyxl 実行時のエラー)。

IllegalCharacterError: control character ... found in string

原因

  • openpyxl は Excel(Open XML)仕様に準拠しており、制御文字のうち \x00–\x08, \x0B–\x0C, \x0E–\x1F が禁止です。

解決策1:engineを変える

engine="xlsxwriter" を指定すると、本件の禁止制御文字が原因の例外を回避できるケースがあります。
👉ただし、既存Excelへの追記は不可。要注意。

df.to_excel("out.xlsx", engine="xlsxwriter")

今回の要件範囲では副作用は確認できませんでしたが、xlsxwriter書き込み専用で、openpyxl と一部の書式・数式挙動が異なる点があります。

解決策2:前処理で除去

既存テンプレートや厳密な書式要件がある場合は事前検証をおすすめします。
前処理で禁止制御文字を除去/置換しておくと堅牢です。

# 禁止制御文字(\x00–\x08, \x0B–\x0C, \x0E–\x1F)をスペースに置換
df = df.applymap(
    lambda s: (
        s if not isinstance(s, str)
        else re.sub(r'[\x00-\x08\x0B-\x0C\x0E-\x1F]', ' ', s)
    )
)

tip: 前処理で置換する場合は、Pythonファイルの先頭に import re を忘れず。

その他のハマりやすいエラー

他にもpandasの利用にあたり発生しうるエラーとその解決策をまとめました。

エラー 原因 解決策
PermissionError / OSError 出力先ファイルがExcelで開かれている / 権限不足 with pd.ExcelWriter(...) を使う / ファイルを閉じる
ValueError(シート名) シート名が31文字超 / 禁止文字 : \ / ? * [ ] を含む シート名を短く、安全に命名
TypeError タイムゾーン付きdatetime / dict / list をセルに含む tz_localize(None) でtzを削除 / 型変換してから出力
OverflowError / MemoryError Excel仕様の制限超過(行: 1,048,576 / 列: 16,384)や巨大データ 出力前に制限確認 / CSVやParquetなど別形式を検討

他ライブラリとの関係(pandas vs Polarsなど)

最後にpandas以外のデータフレームライブラリとの比較を添えます。
Excel出力に関してはpandasが最も充実しています。

ライブラリ 強み Excel出力の扱い
pandas 標準、資料が豊富 to_excel が充実
Polars Rust実装で高速・低メモリ Excel出力は弱く、pandas変換が必要
Modin pandas互換で並列化 出力はpandas依存
Dask DataFrame 並列・分散処理 出力はpandasへ寄せる
PySpark ビッグデータ処理 ローカルに集約してpandasで出力

👉 処理はPolars/Dask/Sparkで行っても、最後のExcel出力はpandasに戻すのが現実的です。


まとめ

  • pandasでDBデータをExcel出力する基本は to_excel 一発
  • index の扱いに注意(デフォルトは行番号も一緒に出力される)
  • engine の種類を理解するとトラブル対応や応用が効く
  • Polars/Dask/Sparkでも処理はできるが、最終的にExcel出力はpandas
  • 制御文字エラーはハマりやすい落とし穴xlsxwriter で回避が可能
  • その他のエラー(ファイル書き込み、シート名制限、データ型、Excel仕様上限)も考慮してライブラリを利用する
    👉 本記事を読めば、DBデータを安全にExcel出力し、pandas利用時に発生する可能性のあるエラーを事前に回避できるようになります。

参考

今回もpandasを理解するにあたりサプーさんの動画にとても助けられました。

Discussion