Django(Python)でテンプレートを使ってExcelファイルを出力する

Webアプリケーションを開発していると「Excelファイルをダウンロードする」機能が必要となることがあると思います。

今回はPythonのWebアプリケーションフレームワークであるDjangoで、Excelファイルのテンプレートを利用して「Excelファイルのダウンロード機能」の実装方法を説明していきたいと思います。

開発環境について

  • Python:3.5.2
  • Django:1.10.5
  • xlutils:2.0.0
  • xlrd:1.0.0
  • xlwt:1.2.0

Django」「xlutils」「xlrd」「xlwt」についてはpip installコマンドを使用してライブラリをあらかじめインストールしておいてください。

xlutils、xlrd、xlwtについて

それぞれのライブラリの主な役割は下記の通りです。

ライブラリ 役割
xlutils Excelファイルを操作するためのメソッドがまとめられている(ファイルコピーなど)
xlrd Excelファイルの読み込み時に利用する
xlwt Excelファイルの書き込み時に利用する

それでは早速、これらのライブラリを利用したExcelファイルの出力機能の実装方法を説明していきたいと思います。

Excelファイル出力機能を実装する

あらかじめ、ライブラリをインポートしておきます。

ライブラリのインポート

import xlwt
import xlrd
from xlutils.copy import copy

今回はあらかじめ準備しているExcelのテンプレートファイルをコピーして、コピーしたファイルに書き込みを行いファイルをダウンロードさせるため、「xlutils」のcopyメソッドを利用します。このcopyメソッドでExcelのテンプレートファイルをコピーします。

Excelのテンプレートファイルをコピーする

# Excelのテンプレートファイルの読み込み
rb = xlrd.open_workbook(os.path.join(MEDIA_ROOT, 'report.xls'), formatting_info=True, on_demand=True)

# 読み込んだExcelファイルをコピーする
wb = copy(rb)

ここでは、MEDIA_ROOTのパス上にある「report.xls」というファイルを読み込んでいます。

formatting_info=Trueとすることで、xlrdがセルのスタイル情報も読み込んでくれて、xlutils.copyを実行した時にxlwtにスタイル情報もコピーしてくれます。

コピーしたExcelファイルにデータを書き込む

コピーしたExcelファイルにデータを書き込んでいきます。ここで注意が必要なのが、「データを書き込んだセルはスタイル情報がデフォルトに戻ってしまう。」という点です。

データのみの書き込み処理を行い、書き込んだセルに対してスタイルの設定を行わなかった場合、そのセルはデフォルトのスタイルとなってしまいます。罫線とか背景色とか文字寄せなどの情報がリセットされてしまいます。

なので、データの書き込みを行なった場合は、書き込みを行なったセルに対して忘れずにスタイルを設定する必要があります。

いくつかスタイル設定のサンプルと書き込みの実装方法を書いていきます。

# フォント設定(Excelファイル内部でよく使うものはあらかじめ設定しておいた方が良いです。)
font_normal = xlwt.Font()
font_normal.name = 'MS P明朝'

# 表示位置設定(左寄せ上下中央揃え)
align_normal = xlwt.Alignment()
align_normal.horz = xlwt.Alignment.HORZ_LEFT
align_normal.vert = xlwt.Alignment.VERT_CENTER

# 表示位置設定(右寄せ上下中央揃え)
align_right = xlwt.Alignment()
align_right.horz = xlwt.Alignment.HORZ_RIGHT
align_right.vert = xlwt.Alignment.VERT_CENTER

# 罫線設定(全てに細い罫線を引く)
border_all = xlwt.Borders()
border_all.top = xlwt.Borders.THIN
border_all.bottom = xlwt.Borders.THIN
border_all.left = xlwt.Borders.THIN
border_all.right = xlwt.Borders.THIN

# 背景色設定(黄色)
pattern = xlwt.Pattern()
pattern.pattern = xlwt.Pattern.SOLID_PATTERN
# 色と紐付くコードの情報はStyle.pyに記載されています。
pattern.pattern_fore_colour = 0x0D

# ノーマルなテキストのスタイル
style_text = xlwt.XFStyle()
style_text.font = font_normal
style_text.borders = border_all
style_text.alignment = align_normal

# ノーマルな日付のスタイル
style_date = xlwt.easyxf('font: name MS P明朝', 'YYYY年M月D日')
style_date.borders = border_all
style_date.alignment = align_normal

# ノーマルな通貨のスタイル
style_currency = xlwt.easyxf('font: name MS P明朝', '¥#,##0')
style_currency.borders = border_all
style_currency.alignment = align_normal

# 右寄せの通貨のスタイル
style_currency_align_right = xlwt.easyxf('font: name MS P明朝', '¥#,##0')
style_currency_align_right.borders = border_all
style_currency_align_right.alignment = align_right

# ノーマルな数値のスタイル
style_num = xlwt.easyxf('font: name MS P明朝', '#,##0')
style_num.borders = border_all
style_num.alignment = align_right

# ノーマルなDecimalのスタイル
style_decimal = xlwt.easyxf('font: name MS P明朝', '#,##0.0')
style_decimal.borders = border_all
style_decimal.alignment = align_right

# テキストを書き込む
ws.write(row, col, value, style_text)
# 日付を書き込む
ws.write(row, col, value, style_date)
# 通貨を書き込む
ws.write(row, col, value, style_currency)
# 数値を書き込む
ws.write(row, col, value, style_num)
# Decimalを書き込む
ws.write(row, col, value, style_decimal)

ws.writeの引数にはそれぞれ下記を設定してください。
* row:行番号(0〜)
* col:列番号(0〜)
* value:書き込むデータ
* style_***:設定したいずれかのスタイル

あらかじめスタイル情報を定義しておくことで、データ書き込みの際にはほとんどスタイル情報を意識することなく実装していくことができます。

都度スタイルを定義するよりもコードの可読性や実行速度が向上すると思います。

Excelファイルをダウンロードさせる

これで、Excelのテンプレートファイルをコピーして、データの書き込みまではできました。

最後に、書き込みのを行なったファイルのダウンロード処理の部分を実装していきます。

Djangoviews.pyファイルのgetpostの中で以下のコードを実装します。

# HttpResponseを生成する
response = HttpResponse(content_type='application/vnd.ms-excel')
response['Content-Disposition'] = 'attachment; filename=%s' % 'report.xls'

# データの書き込みを行なったExcelファイルを保存する
wb.save(response)

# 生成したHttpResponseをreturnする
return response

views.pypostの処理では通常、renderもしくはredirectreturnすると思いますが、Excelファイルをダウンロードさせる場合は、HttpResponseオブジェクトを生成し、returnさせることで、ダウンロードを可能にします。

最後に

Webアプリケーションを開発していると「Excel出力機能」は結構実装する機会が多い機能だと思います。

ちなみに、Linux環境でも問題なくExcel出力されますので、OSは意識せず実装できます。

もし、Djangoを使っていて、Excel出力機能の実装で悩んでいるのでいれば、是非参考にしてみてください。