![]() ![]() ![]() ![]() PythonとDjangoでExcelファイルを作成この記事のURLhttp://japan.internet.com/developer/20080613/26.html
著者:Chris McAvoy
海外internet.com発の記事
はじめにクライアントにデータを操作させる必要がある場合には、Excelのスプレッドシートを用意するのが最も簡単です。スプレッドシートはPythonを使って簡単に作成できますし、スプレッドシートをWebからダウンロードさせることも、DjangoというWebフレームワークを使えば簡単です。この記事ではスプレッドシートの進化の歴史について簡単に触れた後、この2つの操作方法について説明します。スプレッドシートの進化の歴史サメは何百年もの間、あまり進化していません。その最大の理由は、野生で十分に生きていけるからです。獲物を実に上手く捕らえることができるので、サメは自らを適応させる必要も、変化する必要もなかったのです。これ以上進化させるところはないというほどに、サメは完璧な恐怖のフィッシュハンターです。サメと同様に、スプレッドシートも数十年の間、あまり進化してきませんでした。サメの例と同じく、スプレッドシートもデータを実に上手く処理することができるので、ほとんど進化する必要がなかったのです。スプレッドシードでは大量のデータを扱うことができ、データをわかりやすい表形式で表示でき、プログラマでない人でも、数値の並べ替えや操作を行ってデータを分析できます。スプレッドシートは完璧な恐怖のデータハンターなのです。 Webアプリケーションのデータ表示スプレッドシートはそれほど素晴らしいものなので、改良を試みて時間を無駄にするよりも、その能力を素直に認めた方が得策な場合もあります。Webアプリケーションの機能の大半は、「データベースのデータを受け取って、それをWeb上に配置すること」です。反復的開発環境では、最初の数サイクルは「データをデータベースに入力すること」に費やされます。この段階が終わると、開発の依頼主がWebアプリケーションにデータを表示させてみて欲しいと言い始めるでしょう。ここからが面倒なところです。表示して欲しいと求められたところで、そのデータを実際にどのように操作したいのかを正確に理解しているクライアントはほとんどいません。その時点では自分で理解しているつもりなのかもしれませんが、言われたとおりにして見せると、たいていは「思っていたのと何だか違う」という反応が返ってきます。 これは別に、クライアントが意地悪をしているわけではありません。すべてのデータを一度に見るという経験はおそらく今まで1回もなかったのでしょうから、当然と言えば当然なのです。新しい形の情報をいじってみたら、今まで考えもしなかったパターンを思いついたというだけのことです。 Excelファイルを提供するWebアプリケーションこのような経験から、筆者はできるだけExcelを使ってクライアントにデータを表示して見せるようにしています。データはクライアントがWebアプリケーションからダウンロードできるようにしておきます。Excelで自由に操作してもらった後なら、データをどのように利用し、最終的にどのように表示させたいかについて、優れたアイディアをクライアントから聞き出すことができます。時間を節約でき、製品の品質向上にもつながります。「データをExcel形式でダウンロード」ボタンを用意しておくと、データの可搬性という点でも大いに役立ちます。アプリケーションが完成に近づき、データの表示にExcelを使用する必要がなくなったときでも、Excelへのエクスポート機能を残しておき、ユーザーがデータをオフラインで利用できるようにしましょう。これはさまざまな難題を解決する、間違いなく魅力的な機能です。 スプレッドシートの素晴らしさをご理解いただいたところで、以降ではその作成方法を説明し、続いて、必要なときすぐにWebアプリケーションからダウンロードできるようにする方法について解説します。 今回の例ではWebアプリケーションフレームワークにDjangoを使用しますが、基本的な考え方はどのツールキットを使用する場合でも同じです。 PythonによるExcelスプレッドシートの作成Excelのフォーマットは(言うまでもありませんが)プロプライエタリです。ただし、オープンにしようと最善を尽くしてはいるようです。コンマ区切りのファイルをExcelで開き、Excelのスプレッドシートとして操作することは簡単にできます。また、コンマ区切りのファイルをPythonで作成することもいたって簡単です。PythonとExcelはcsvファイルを共通言語とする、最高に相性の良い組み合わせです。Pythonの標準ライブラリには、優れたcsv出力クラスが付属しています。次の短い例で、その使い方を紹介します。
import csv
w = csv.writer(open('output.csv','w'))
for i in range(10):
w.writerow(range(10))
編集部注
Windows環境で上記コードを実行した場合、改行コードが複数出力される現象が確認されています。
output.csvの内容は以下のようになります。この場合は、2行目の記述を以下のようにすれば問題を回避できます。 w = csv.writer(open('output.csv','w'),lineterminator="¥n") 0,1,2,3,4,5,6,7,8,9 0,1,2,3,4,5,6,7,8,9 0,1,2,3,4,5,6,7,8,9 0,1,2,3,4,5,6,7,8,9 0,1,2,3,4,5,6,7,8,9 0,1,2,3,4,5,6,7,8,9 0,1,2,3,4,5,6,7,8,9 0,1,2,3,4,5,6,7,8,9 0,1,2,3,4,5,6,7,8,9 0,1,2,3,4,5,6,7,8,9 そうは言っても、csvファイルを開く際のこの一手間が、エンドユーザーのお気に召さないこともあります。そのような場合は、Roman Kiseliovが作成した、ExcelのバイナリファイルをPythonで作成するための素晴らしいライブラリを利用しましょう。これはpyExceleratorというライブラリで、Sourceforgeのプロジェクトページから入手可能です。このライブラリはWindowsやExcelを必要としないので、もっと簡単に実行できます。 前回のcsvの例と同じく、10行×10列の表をpyExceleratorで作成してみましょう。
from pyExcelerator import *
wb = Workbook()
ws0 = wb.add_sheet('0')
for x in range(10):
for y in range(10):
# writing to a specific x,y
ws0.write(x,y,"this is cell %s, %s" % (x,y))
wb.save('output.xls')
pyExceleratorの方が少し手間がかかりますが、機能という点でははるかに上です。簡単な表データの作成に加え、セルの書式設定や、Excelの式の挿入など、Excelでよく使われる機能はひととおり網羅しています。csv出力クラスでは、簡単な表を作成することしかできません。 DjangoからのExcelファイルのダウンロードExcel互換ファイルをPythonで作成する方法を覚えたところで、次はそのファイルをDjangoでダウンロード可能にする方法を見ていきましょう。手順は簡単です。また、同じ手順でほとんどすべての種類のバイナリファイルを生成し、提供することができます。ファイルを作成できれば、それをユーザーにダウンロードさせるのは簡単です。鍵を握るのは「content-type」というHTTPヘッダーです。ブラウザからサーバー上のファイルを要求する場合、トランザクションは次のようになります。 GET /wp-content/uploads/2007/10/cropped-dsc_0020.jpg HTTP/1.1 Host: weblog.lonelylion.com User-Agent:Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.1.11) Gecko/20071204 Ubuntu/7.10 (gutsy) Firefox/2.0.0.11 Accept: image/png,*/*;q=0.5 Accept-Language: en-us,en;q=0.5 Accept-Encoding: gzip,deflate Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 Keep-Alive: 300 Connection: keep-alive Referer: http://lonelylion.com/ HTTP/1.x 200 OK Date: Sat, 02 Feb 2008 17:53:58 GMT Server: Apache/1.3.37 (Unix) mod_throttle/3.1.2 DAV/1.0.3 mod_fastcgi/2.4.2 mod_gzip/1.3.26.1a PHP/4.4.8 mod_ssl/2.8.22 OpenSSL/0.9.7e Last-Modified: Thu, 01 Nov 2007 03:22:12 GMT Etag: "798f213-5c88-47294664" Accept-Ranges: bytes Content-Length: 23688 Keep-Alive: timeout=2, max=97 Connection: Keep-Alive Content-Type: image/jpeg Content-Type: image/jpegに注目してください。この行は、後続のデータが何であるかをブラウザに伝えています。ブラウザはこの行に基づいて、データの表示方法や、どの外部アプリケーションを開いてデータを表示するかを判断します。上記の例ではJpegの画像を要求しているため、Content-Typeに「image/jpeg」が設定されています。このヘッダーを「application/ms-excel」に変更すると、ファイルがExcelで開かれます。Djangoでヘッダーの記述を変更するのは非常に簡単です。以下に、csvファイルをブラウザに送信し、それをExcelで開くようブラウザに指示するDjangoビューの例を示します。
import csv
from StringIO import StringIO
from django.http import HttpResponse
def show_excel(request):
# use a StringIO buffer rather than opening a file
output = StringIO()
w = csv.writer(output)
for i in range(10):
w.writerow(range(10))
# rewind the virtual file
output.seek(0)
return HttpResponse(output.read(),
mimetype='application/ms-excel')
このパターンを使用して、ほとんどすべての種類のバイナリデータをWebブラウザから取得することができます。PDF、画像、音声、動画など、あらゆるデータに対して生成用のライブラリが用意されているので、Content-Typeヘッダーの値さえわかれば、バイナリデータを生成することが可能です。 それでは、同じテクニックを使ってpyExceleratorで生成したExcelファイルを出力してみましょう。
from pyExcelerator import *
from django.http import HttpResponse
def show_excel(request):
wb = Workbook()
ws0 = wb.add_sheet('0')
for x in range(10):
for y in range(10):
# writing to a specific x,y
ws0.write(x,y,"this is cell %s, %s" % (x,y))
wb.save('output.xls')
return HttpResponse(open('output.xls','rb').read(),
mimetype='application/ms-excel')
筆者はたいていの場合、csvファイルを「Content-Type: application/ms-excel」としてブラウザに送信します。StringIOを使用すれば実装がシンプルになりますし、ダウンロード可能なスプレッドシートの作成にかかる時間は通常5分以内なので、ほとんどのエンドユーザーはおかしいとも感じません。これでユーザーの希望はかなえられますし、すぐにデータをいじってもらうことができます。ユーザーはデータをあれこれ操作することで、彼らが実際に使用するHTML表示についてより明確なビジョンを持つようになり、的確な要求をしてくるようになるでしょう。良いことだらけです。 著者紹介Chris McAvoy(Chris McAvoy)
|