Google App Engine(Python)用フレームワークKayを使い、動的にExcelファイルを作成してZIP形式で圧縮しダウンロードさせる方法。
「Google App Engine(Python)用フレームワークKayを使い、動的にZIP形式で圧縮してダウンロードさせる」と「Google App Engine用フレームワークKayでExcelファイルをダウンロードさせる」の合わせ技になります。
Excelファイルの作成には、xlwtを使用します。
xlwtはpure pythonなので、Google App Engineで使用することが出来ます。
xlwtからソースをダウンロードして展開します。
xlwtフォルダーをKayのプロジェクトのルートフォルダーにコピーします。
xlwtフォルダー中のdocフォルダーやexamplesフォルダーは不要です
次のようなフォルダー構成になります。
myproject/
├ kay/
├ myapp/
└ xlwt/
xlwtでExcelデータを作成します。
wb = xlwt.Workbook()
ws1 = wb.add_sheet('Sheet1')
ws1.write(0, 0, u'セル:A1')
ws1.write(1, 0, u'セル:A2')
ws1.write(0, 1, u'セル:B1')
ws1.write(1, 1, u'セル:B2')
data = StringIO.StringIO()
wb.save(data)
xlwt.save()は引数にファイルライクなオブジェクトをとります。
引数に指定したオブジェクトにExcelデータが書き込まれます。
ZipFileオブジェクトを作成します。
ZipFileオブジェクトのコンストラクタの1番目の引数にファイルライクなオブジェクトを指定します。
引数に指定したファイルライクなオブジェクトに、ZIPデータが書き込まれます。
zipdata = StringIO.StringIO()
zipobj = zipfile.ZipFile(zipdata, 'w', zipfile.ZIP_DEFLATED)
ZipFileオブジェクトにファイルを登録します。
1番目の引数にファイル名を、2番目の引数にファイルのデータ(バイト列)を指定します。
zipobj.writestr('example.xls', data.getvalue())
ここで、1番目の引数にZipInfoオブジェクトを指定すると、ファイルの情報を細かく設定することが出来ます。
最後に閉じます。
zipobj.close()
以上で、ZIPデータを作成できました。
作成したZIPデータをダウンロードさせるために、HTTPヘッダの設定を行います。
header = Headers()
header.add('Content-Type', 'application/octet-stream');
header.add('Content-Disposition', 'attachment', filename='foo.zip')
最後に、ZIPデータをレスポンスとして返します。
return Response(zipdata.getvalue(), headers=header)
全体のソースコードは以下のようになります。
def index(request):
import xlwt
import StringIO
import zipfile
from werkzeug.datastructures import Headers
from werkzeug import Response
wb = xlwt.Workbook()
ws1 = wb.add_sheet('Sheet1')
ws1.write(0, 0, u'セル:A1')
ws1.write(1, 0, u'セル:A2')
ws1.write(0, 1, u'セル:B1')
ws1.write(1, 1, u'セル:B2')
data = StringIO.StringIO()
wb.save(data)
zipdata = StringIO.StringIO()
zipobj = zipfile.ZipFile(zipdata, 'w', zipfile.ZIP_DEFLATED)
zipobj.writestr('example.xls', data.getvalue())
zipobj.close()
header = Headers()
header.add('Content-Type', 'application/octet-stream');
header.add('Content-Disposition', 'attachment', filename='foo.zip')
return Response(zipdata.getvalue(), headers=header)
これはなかなか良いTipsですね。いつも役に立つ記事をありがとうございます。
コメントありがとうございます。
間違いがあれば、どんどん指摘してください。