Web-WF Python Tornado その3(Openpyexcelの紹介)


はじめに

webServer APIServerとして、かんたん・すぐれている(と思っている)Tornadoを何回かにわけて紹介したいと思います

Web-WF Python Tornado その1
Web-WF Python Tornado その2
Web-WF Python Tornado その3 (この記事

対象

フルスタックエンジニア、フロントエンジニア、Pythonが好きな人、その1・その2を読んだ人、Excelでなにか資料を出力する必要に迫られた人

Python3.6以上、tornadoがインストールされている

ゴール

今回はちょっと趣向をかえてアプリケーションにあると便利なモジュールの紹介
(Openpyxl)

Openpyxlとは

pythonからExcelファイルを読み書き編集できるモジュール
集計結果をExcelでレポート出力したり、逆にExcelのデータをインポートするのに便利です
今回は請求書を出力するサンプルを作成します
公式はこちら

インストール

Openpyxlのインストールはpipのみ

$ pip install openpyxl

excelテンプレートの準備

以下のようなテンプレートを準備しておきます
(赤字の部分はマクロのサンプル)

ソースコード

その1やその2で紹介したソースに以下のソースを追加しておきます

main.py
import os
import datetime
import openpyxl as px
from openpyxl.writer.excel import save_virtual_workbook

class prtInvoice(tornado.web.RequestHandler):
    def get(self):
        # 請求書のtemplateをLoad
        wb = px.load_workbook(BASE_DIR+u'/template.xlsx')
        ws = wb.active
        # 印刷範囲を指定
        ws.page_setup.fitToWidth = 1
        ws.page_setup.fitToHeight = 0
        ws.sheet_properties.pageSetUpPr.fitToPage = True
        # こんなmodelを準備(実際にはDBなどから
        model = {
            'companyName': 'テスト会社',
            'items': [
                {'itemName': '商品A', 'price': 1000, 'quantity': 1},
                {'itemName': '商品B', 'price': 2000, 'quantity': 2},
                {'itemName': '商品C', 'price': 3000, 'quantity': 3}
            ]
        }

        # 今日の日付をセット
        # F2はセルのExcelのセル
        dt_now = datetime.datetime.now()
        ws['F2'] = dt_now.strftime("%Y 年 %m 月 〆 日")
        # 会社名をセット
        ws['B7'] = '{0} 御中'.format(model['companyName'])
        for i, item in enumerate(model['items']):
            # 商品名をセット
            ws['B'+str(i+25)] = '  {0}'.format(item['itemName'])
            # 数量をセット
            ws['D'+str(i+25)] = item['quantity']
            # 単価をセット
            ws['E'+str(i+25)] = item['price']

        # Excel形式でダウンロード
        self.set_header('Cache-Control',
                        'no-store, no-cache, must-revalidate, max-age=0')
        self.set_header(
            'Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet')
        fileName = "Invoice.xlsx"
        self.set_header('Content-Disposition',
                        "attachment; filename=\"{}\"".format(fileName))
        self.write(save_virtual_workbook(wb))

def make_app():
    return tornado.web.Application(
        [
        (r"/html", htmlHandler),
        (r"/json", jsonHandler),
        (r"/excel", prtInvoice),
        ],
        debug=True,
    )
ws['B7'] = 'Hello'

こんなふうに、Excelのセルにデータをセットしたり、読み込んだりできるのがこのモジュールの特徴となります

実行&閲覧

以下のようにURLを直接指定することでExcelファイルをダウンロードすることができます
(クライアントのダウンロードフォルダに直接保存される)

ダウンロードしたExcelファイルを開くと

はい、なんとかそれっぽいデータが表示できました