LoginSignup
2
2

More than 1 year has passed since last update.

【備忘録】PythonでPDF出力してみよう reportlab編

Posted at

経緯

DjangoでPDF出力を行いたい。PC環境にインストールなどは行いたくなく、pipでインストールできるreportlabを採用。
恐らくまた使用する機会があると思うので、備忘録として残しておく。
始点終点を指定する方法よりめちゃ楽なのでオススメ。

参考にさせて頂いたサイト

https://qiita.com/kokardy/items/92e8f3b65c965e20de34
タイトル笑いました。
ただ、確かに少しぐぐったところこのやり方で行うサイトは少ない。
(ほかのサイトは始点、終点を全て指定して記載する方法)

https://www.reportlab.com/docs/reportlab-userguide.pdf
reportlab ユーザーガイド(英語)

reportlabインストール

pythonはインストールしている前提です。
ここでは3.9.7を使ってます。

python -m pip install reportlab

Collecting reportlab
  Downloading reportlab-3.6.9-cp39-cp39-win_amd64.whl (2.3 MB)
     |████████████████████████████████| 2.3 MB 1.1 MB/s
Requirement already satisfied: pillow>=4.0.0 in c:\users\kutaa\anaconda3\lib\site-packages (from reportlab) (8.4.0)
Installing collected packages: reportlab
Successfully installed reportlab-3.6.9

インストール完了です。
python2と3が共存している場合、errorが出る場合があるよう。
その場合、pip3を使用してpython3環境にインストールしよう。

pythonコード

上記サイトのコードをほぼパクリ参考にさせて頂きました。
※この例ではデスクトップにtest.pdfファイルを出力します。

from reportlab.platypus import BaseDocTemplate, PageTemplate
from reportlab.platypus import Paragraph, PageBreak, FrameBreak
from reportlab.platypus.flowables import Spacer
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.pagesizes import A4, mm
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase import cidfonts
from reportlab.platypus.frames import Frame
import os

def main():
    pdfmetrics.registerFont(cidfonts.UnicodeCIDFont("HeiseiMin-W3"))

    buf = os.path.expanduser("~") + "/Desktop/test.pdf"

    doc = BaseDocTemplate(buf, 
        title="reportlabテスト",
        pagesize=(200*mm, 200*mm),
        )

    show = 1 #Frameの枠を表示
    frames = [
            Frame(25 * mm, 120*mm, 150*mm, 50*mm, showBoundary=0),
            Frame(10 * mm, 30*mm, 70*mm, 80*mm, showBoundary=show),
            Frame(110 * mm, 50*mm, 75*mm, 60*mm, showBoundary=show),
        ]

    page_template = PageTemplate("frames", frames=frames)
    doc.addPageTemplates(page_template)


    style_dict ={
        "name":"nomarl",
        "fontName":"HeiseiMin-W3",
        "fontSize":20,
        "leading":20,
        "firstLineIndent":20,
        }
    style = ParagraphStyle(**style_dict)

    flowables = []

    space = Spacer(10*mm, 10*mm)

    para = Paragraph("1ページ目です", style)
    flowables.append(para)
    flowables.append(space)
    para = Paragraph("ここで<br/>改行されます。スペース&nbsp;が入ります。", style)
    flowables.append(para)
    flowables.append(space)
    para = Paragraph("次のページに進む", style)
    flowables.append(para)

    #改ページ
    flowables.append(PageBreak()) 

    para = Paragraph("<span backcolor=yellow>フーレム1</span>", style)
    flowables.append(para)
    para = Paragraph("Paragraphを使うことで長い文章を自動で折り返します。さらにはみ出せば次のページに進みます。", style)
    flowables.append(para)
    para = Paragraph("ちゃんと続きの高さから次のParagraphを描画してくれます。", style)
    flowables.append(para)
    para = Paragraph("Frameを使えば、はみ出した分は次のフレームまたはページへ自動で進みます。", style)
    flowables.append(para)
    para = Paragraph("Frameを使うことで、段組みのような複雑なレイアウトを表現できます。", style)
    flowables.append(para)

    #次のフレームへ
    flowables.append(FrameBreak())

    para = Paragraph("<span color=red>フレーム3</span>", style)
    flowables.append(para)
    para = Paragraph("FrameBreakを使えば次のFrameに進みます。", style)
    flowables.append(para)
    para = Paragraph("PageBreakを使えば次のPageに進みます。", style)
    flowables.append(para)

    doc.multiBuild(flowables)

if __name__ == '__main__':
    main()

解説

ページサイズ指定

pagesize=(200*mm, 200*mm),

使用するフレーム指定
第1引数:座標x
第2引数:座標y
第3引数:幅
第4引数:高さ
showBoundary:0(枠無し) or 1(枠有り)

show = 1 #Frameの枠を表示
    frames = [
            Frame(25 * mm, 120*mm, 150*mm, 50*mm, showBoundary=0),
            Frame(10 * mm, 30*mm, 70*mm, 80*mm, showBoundary=show),
            Frame(110 * mm, 50*mm, 75*mm, 60*mm, showBoundary=show),
        ]

スペースサイズ指定、スペース挿入

space = Spacer(10*mm, 10*mm)
flowables.append(space)

最後に

始点、終点を指定するやり方よりめちゃくちゃ簡単です。
ありがとうございました。

2
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
2