ReportLab PDF


18 stycznia 2014


Opis biblioteki służącej do tworzenia plików PDF. Przykłady tworzenia tabeli oraz wykresu oraz użycia biblioteki w Django.

ReportLab PDF to biblioteka służąca do tworzenia dokumentów w formacie PDF przy użyciu języka Python. W dokumentach oprócz tekstu możemy umieszczać tabele, wykresy oraz tworzyć obrazy wektorowe i bitmapowe, szybko wygenerujemy PDF-a z danych umieszczonych w pliku XML. Biblioteka posiada bardzo wiele możliwości i szybko generuje dokumenty.

Poniżej zamieściłem przykład generowania tabeli oraz dwóch wykresów.

#!/usr/bin/python
# -*- coding: utf-8 -*-
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.platypus.tables import TableStyle, Table
from reportlab.pdfbase.ttfonts import TTFont 
from reportlab.pdfbase import pdfmetrics
from reportlab.platypus.paragraph import Paragraph
from reportlab.lib import styles
from reportlab.lib import colors
from reportlab.graphics.shapes import Drawing
from reportlab.graphics.charts.piecharts import Pie
from reportlab.graphics.charts.linecharts import HorizontalLineChart
import string
from reportlab.graphics.charts.legends import Legend

#dodanie czcionki z polskimi znakami
pdfmetrics.registerFont(TTFont('DejaMono', 'DejaVuSansMono.ttf'))  

#tworzenie płótna oraz ustawienie rozmiaru
canv = canvas.Canvas('plik.pdf', pagesize=A4)
width, height = A4 #keep for later

#ustawienie czcionki
canv.setFont("DejaMono", 14)

#tworzenie ciągu znaków
canv.drawString(40, height - 50, "ReportLab PDF  - tworzenie plików PDF")

#wybór koloru
canv.setFillColorRGB(0,0,0.50)

#tworzenie lini
canv.line(40,height - 60,width - 40, height- 60)

#ustawienie czcionki
canv.setFont("DejaMono", 12)

#tworzenie ciągu znaków
canv.drawString(40, height - 80, "1. Tabela")

#pobranie stylu
stylesheet=styles.getSampleStyleSheet()
normalStyle = stylesheet['Normal']

#utworzenie paragrafu
P = Paragraph('''<font color=red>brak</font>''',normalStyle)

#dane do tabeli
data = [['Autor','Tytuł', 'Ocena', 'Okładka'],
        ['DICK PHILIP K','Ubik', '7', [P]],
        ['HERBERT FRANK','Diuna', '10', [P]],
        ['CARD ORSON SCOTT','Gra Endera', '8', [P]],
        ['CLARKE ARTHUR CHARLES','Odyseja kosmiczna 2001', '9', [P]],
        ['Suma','-', '34', "-"],
       ]

#utworzenie tabeli
t = Table(data, rowHeights=20)

#ustawienie styli dla tabeli i poszczególnych komórek
t.setStyle(TableStyle([
                           ('FONT',(0,0),(-1,-1), 'DejaMono', 13),
                           ('ALIGN', (0,0), (-1,-1), 'LEFT'),
                           ('ALIGN', (-2,1), (-2,-1), 'RIGHT'),
                           ('GRID', (0,0), (-1,-1), 0.25, colors.black),
                           ('BOX', (0,0), (-1,-1), 0.25, colors.black),
                           ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
                           ('BACKGROUND', (0,0), (-1,0), colors.lightgrey),
                           ('BACKGROUND', (0,-1), (-1,-1), colors.lightgrey),
                           ]))
 
t.wrapOn(canv, width-80,height)

#pobranie rozmiaru tabeli
w, h = t.wrap(0,0)

#dodanie tabeli do płótna
t.drawOn(canv, 40, height - (h+90), 0)    

#tworzenie ciągu znaków
canv.drawString(40, height - (h+110), "2. Wykres")

#rysowanie wykresu kołowego z wycinkiem
d = Drawing(400,200)
pc = Pie()
#ustawianie właściwości wykresu
pc.x = 150
pc.y = 50
pc.data = [7,10,8,9]
pc.labels = ['Ubik','Diuna','Gra Endera', 'Odyseja kosmiczna 2001']
pc.slices.strokeWidth=0.5
pc.slices[1].popout = 10
pc.slices[1].strokeWidth = 2
pc.slices[1].strokeDashArray = [2,2]
pc.slices[1].labelRadius = 1.75
pc.slices[1].fontColor = colors.red
d.add(pc, '')
cpw, cph = d.wrap(0, 0)
d.drawOn(canv, 40, height - (h+cph+100), 0)

#rysowanie wykresu czasowego
drawing = Drawing(400, 200)
data = [
(13, 5, 20, 22, 37, 45, 19, 4, 6,40, 20, 12),
(5, 20, 46, 38, 23, 21, 6, 14, 56, 22, 1),
(1, 4, 40, 10, 20, 25, 60, 10, 11, 35, 30, 20),
(7, 30, 50, 40, 20, 10, 40, 30, 20, 10, 60, 50),
]
lc = HorizontalLineChart()
#ustawianie właściwości wykresu
lc.x = 50
lc.y = 100
lc.height = 125
lc.width = 300
lc.data = data
lc.lineLabels = ["1", "2", "2", "2"]
catNames = string.split('STY LUT MAR KWI MAJ CZE LIP SIE WRZ PAZ LIS GRU', ' ')
lc.categoryAxis.categoryNames = catNames
lc.categoryAxis.labels.boxAnchor = 'n'
lc.valueAxis.valueMin = 0
lc.valueAxis.valueMax = 60
lc.valueAxis.valueStep = 15
lc.lines[0].strokeWidth = 2
lc.lines[1].strokeWidth = 1.5
lc.lines[2].strokeColor = colors.blue
lc.lines[3].strokeColor = colors.black
drawing.add(lc)

#tworzenie legendy do wykresu czasowego
legenda = Legend()
legenda.fontName = 'DejaMono'
legenda.fontSize = 12
legenda.x = 50
legenda.y = 70
legenda.dxTextSpace = 4
legenda.dy = 4
legenda.dx = 4
legenda.deltay = 4
legenda.alignment ='right'
items =[
        (colors.red, 'Ubik'),
        (colors.green,'Diuna'),
        (colors.blue,'Gra Endera'), 
        (colors.black,'Odyseja kosmiczna 2001')
        ]
legenda.colorNamePairs = items
drawing.add(legenda,name='Legend')

#pobranie rozmiaru wykresu
clw, clh = drawing.wrap(0, 0)
drawing.drawOn(canv, 40, height - (h+cph+clh+120), 0)

#metoda zapisuje bieżące płotno
canv.showPage()

#metoda zamyka płótno i tworzy plik
canv.save()

Plik z pełną dokumentacją pod adresem: https://www.reportlab.com/docs/reportlab-userguide.pdf 
Przykładowy widok Django może wyglądać następująco:

def generatePDF(request, offset):
    """
    Generowanie PDF
    """
    response = HttpResponse(content_type='application/pdf')
    response['Content-Disposition'] = 'attachment; filename="plik.pdf"'

    #podczas tworzenia płótna zamiast nazwy pliku podajemy obiekt response
    p = canvas.Canvas(response, pagesize=A4)
    #tworzymy plik PDF tak jak wcześniej 
    ...
    ...
    return response

Co zawiera blog?

Na blogu umieszczam wpisy dotyczące mojej pracy, zainteresowań. Głowna tematyka to programowanie oraz recenzje płyt oraz książek.

ReportLab PDF


Opis biblioteki służącej do tworzenia plików PDF. Przykłady tworzenia tabeli ...

Underworld - dubnobasswithmyheadman


Underworld to historia muzyki techno, house i trance

Coś innego, coś lepszego?


Python to język programowania coraz częściej wybierany przez programistów aplikacji ...

Virtualenv - odrębne środowiska pracy


Tworząc aplikacje w języku Python instalujemy różne pakiety. Co zrobić ...

Warning: this LDM has ...


Co zrobić gdy GRUB nie może zapisać tablicy partycji do ...

South i "Cannot freeze..."


Wpis prezentuje rozwiązanie problemu związanego z South gdy typ pola ...