XlsxWriterでExcelファイルを保存する際のエラー対処法
markdown
## 問題: 'XlsxWriter'オブジェクトに'save'属性がないエラー
PandasでExcelファイルを操作する際、`XlsxWriter`をエンジンとして使用している場合、以下のようなエラーが発生することがあります:
```python
AttributeError: 'XlsxWriter' object has no attribute 'save'. Did you mean: '_save'?
このエラーは主に、Excelファイルの保存処理で非推奨となった.save()
メソッドを使用しようとした際に発生します。
エラーの原因となる典型的なコード
python
writer = pd.ExcelWriter('output.xlsx', engine='xlsxwriter')
# ... Excel操作のコード ...
writer.save() # ここでAttributeErrorが発生
エラーの背景
- Pandas 1.5.0(2020年リリース)以降、
ExcelWriter.save()
メソッドは非推奨となりました - Pandas 2.1.0(2023年リリース)では完全に削除され、代わりに
.close()
メソッドを使用する必要があります - 公式ドキュメントでは
close()
を推奨していますが、古いチュートリアルではsave()
が使われている場合があります
解決策: close()メソッドの使用
最も簡単で推奨される方法は、save()
の代わりにclose()
を使用することです:
python
writer = pd.ExcelWriter('output.xlsx', engine='xlsxwriter')
# ... データ処理やチャート追加などの操作 ...
writer.close() # ファイルを保存して閉じる
実践的コード例
python
import pandas as pd
import xlsxwriter
# サンプルデータ作成
data = {
"Name": ["山田太郎", "佐藤花子", "鈴木一郎"],
"年齢": [28, 32, 45],
"性別": ["男性", "女性", "男性"]
}
df = pd.DataFrame(data)
# ExcelWriterオブジェクトの作成
writer = pd.ExcelWriter("社員データ.xlsx", engine="xlsxwriter")
# DataFrameをExcelに書き出し
df.to_excel(writer, sheet_name="社員一覧", index=False)
df.to_excel(writer, sheet_name="Sheet1")
# ワークブックとワークシートの取得
workbook = writer.book
worksheet = writer.sheets["Sheet1"]
# 折れ線グラフの追加
chart = workbook.add_chart({"type": "line"})
chart.add_series({
"values": "=Sheet1!$B$2:$B$4",
"categories": "=Sheet1!$A$2:$A$4",
"name": "年齢推移"
})
# グラフをシートに挿入
worksheet.insert_chart("D2", chart)
# ファイルの保存(closeを使用)
writer.close()
close()メソッドの重要な特徴
- ファイルを保存し、同時にリソースを解放
- Excelファイル操作が確実に完了することを保証
- バージョン1.5.0以上のPandasで正しく動作
- ファイルの書き込み後は編集不可能
ベストプラクティス: with文を利用したコンテキストマネージャー
さらに安全で現代的な方法は、with
文を使用してファイル操作を行うことです。この方法では、ファイルのクローズ忘れを防ぎ、例外発生時も確実にリソースを解放します。
python
import pandas as pd
import xlsxwriter
df = pd.DataFrame({
"商品名": ["ノートPC", "スマートフォン", "タブレット"],
"販売数": [150, 300, 200],
"単価": [120000, 80000, 60000]
})
with pd.ExcelWriter("販売データ.xlsx", engine="xlsxwriter") as writer:
df.to_excel(writer, sheet_name="月次売上", index=False)
workbook = writer.book
worksheet = writer.sheets["月次売上"]
# 棒グラフの作成
chart = workbook.add_chart({"type": "column"})
chart.add_series({
"values": "='月次売上'!$C$2:$C$4",
"categories": "='月次売上'!$A$2:$A$4",
"name": "各商品の販売数"
})
chart.set_title({"name": "月別商品販売数比較"})
worksheet.insert_chart("E2", chart)
::: success with文の利点
- 自動リソース解放 - ブロックを抜けると自動で
close()
が実行される - 例外安全性 - 途中でエラーが発生してもファイルが確実に閉じられる
- コードの可読性向上 - ファイル操作の範囲が明確になる
- メモリリーク防止 - リソースの解放忘れが起きない :::
補足: Excelチャート作成時の注意点
チャートを追加する際は、データ範囲の指定が非常に重要です。よくある間違いと解決策:
一般的な間違い
python
# 誤った範囲指定 (Sheet名の後に「.$」が残っている)
chart.add_series({"values": "=Sheet1.$B$2:$B$4"})
正しい指定方法
python
# 「!」でシート名とセル範囲を区切る
chart.add_series({"values": "=Sheet1!$B$2:$B$4"})
チャート範囲指定のベストプラクティス
- 完全修飾シート名を使用:
'Sheet Name'!A1:B10
- シート名にスペースがある場合は必ず引用符で囲む
- セル参照は絶対参照(
$A$1
)で指定すると安全 - 動的に範囲を指定したい場合:python
# 行数を動的に取得 max_row = len(df) + 1 chart.add_series({ "values": f"=Sheet1!$B$2:$B${max_row}", "categories": f"=Sheet1!$A$2:$A${max_row}" })
対応バージョン情報
ライブラリ | 推奨バージョン | 非推奨メソッドを含むバージョン |
---|---|---|
Pandas | 2.1.0以上 | 1.5.0(警告)~2.1.0(削除) |
XlsxWriter | 3.0.3以上 | 全バージョンでsave属性なし |
最新の環境では、close()
メソッドまたはwith
文の使用が必須となります。古いコードでsave()
を使用している場合は、即座に修正することをお勧めします。