ReportLab: Difference between revisions

From XPUB & Lens-Based wiki
(Created page with " == ReportLab == Following this [http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/ helpful tutorial] <source lang="python"> from reportl...")
 
No edit summary
 
(22 intermediate revisions by 3 users not shown)
Line 1: Line 1:
== Links ==
* http://reportlab.com is the projects main website
* [https://www.reportlab.com/docs/reportlab-userguide.pdf the "guide"] conveniently in pdf format (generated by ReportLab itself one would imagine ;)
* [http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/ a helpful tutorial]


== ReportLab ==
ReportLab is a hybrid free-software / commercial enterprise. The core python library is published with a Free Software License. On top of this a commercial company exists that offers products such as tools that work with RML, a specialized markup language. That said, alternative free software alternatives exist (made from a larger user community) to process RML, as well as the possibility to make your own.


Following this [http://www.blog.pythonlibrary.org/2010/03/08/a-simple-step-by-step-reportlab-tutorial/ helpful tutorial]
== Hello world ==
Nice demo of the "page as canvas" "low-level" way of working with ReportLab.


<source lang="python">
<syntaxhighlight lang="python">
from reportlab.pdfgen import canvas
from reportlab.pdfgen import canvas
   
   
Line 10: Line 15:
c.drawString(100, 100, "Hello WORLD!")
c.drawString(100, 100, "Hello WORLD!")
c.save()
c.save()
</source>
</syntaxhighlight>
 
Creates a pdf from a .txt file.
 
From the Report Lab How to PDF:
 
<blockquote>The pdfgen package is the lowest level interface for generating PDF documents. A pdfgen program is essentially a sequence of instructions for &quot;painting&quot; a document onto a sequence of pages. The interface object which provides the painting operations is the pdfgen canvas.
</blockquote>
The Canvas constructor:
 
<pre>def __init__(self,filename,
    pagesize=(595.27,841.89),
    bottomup = 1,
    pageCompression=0,
    encoding=rl_config.defaultEncoding,
    verbosity=0
    encrypt=None):</pre>
 
== pageloop ==
 
This is a loop that opens a PDF with report lab ...
 
<syntaxhighlight lang="python">from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.pagesizes import letter, A4
from reportlab.lib.units import inch, cm
import sys
from reportlab.pdfbase.ttfonts import TTFont, pdfmetrics
 
fontpath = "OSP-DIN.ttf"
font =  TTFont('MyFontName', fontpath)
pdfmetrics.registerFont(font)
c = Canvas("pageloop.pdf", pagesize=A4)
 
for i in range(1000):
    c.setPageSize(A4)
    c.setFont('MyFontName', 72)
    # c.drawString(10*cm, 0.5*cm, "Page {0}".format(i))
    c.drawCentredString(A4[0]/2, A4[1]/2, "Page {0}".format(i))
    c.showPage()
c.save()
</syntaxhighlight>
 
[[File:ReporLabPageloop.pdf]]
 
== pageloop with different sizes ==
 
<syntaxhighlight lang="python">from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.pagesizes import A4, A5
from reportlab.lib.units import cm
from reportlab.pdfbase.ttfonts import TTFont, pdfmetrics
import sys
 
 
pdfmetrics.registerFont(TTFont('din', "OSP-DIN.ttf"))
pdfmetrics.registerFont(TTFont('lib', "Libertinage-x.ttf"))
c = Canvas("pageloopdifferentsizes.pdf", pagesize=A4)
 
for i in range(1000):
    if i%2==0:
        ps = A4
        c.setFont('din', 144)   
    else:
        ps = A5
        c.setFont('lib', 72)
    c.setPageSize(ps)   
    # c.drawString(10*cm, 0.5*cm, "Page {0}".format(i))
    c.drawCentredString(ps[0]/2, ps[1]/2, "Page {0}".format(i))
    c.showPage()
c.save()
 
</syntaxhighlight>
 
== SimpleDocTemplate ==
The "Platypus" system is a "higher level" interface that takes care of such niceties as creating "flowable" text (so you don't need to position every line yourself.
 
<syntaxhighlight lang="python">
from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet
 
doc = SimpleDocTemplate("text.pdf", pagesize=A4,
                        rightMargin=72, leftMargin=72,
                        topMargin=72, bottomMargin=18)
 
 
content = []
styles = getSampleStyleSheet()
 
for line in open('file.txt'):
    line = line.strip()
    if line:
        p = Paragraph('<font size=12>'+line+'</font>', styles["Normal"])
        content.append(p)
        content.append(Spacer(1, 12))
 
doc.build(content)
</syntaxhighlight>
 
== Using Platypus to do a 2 column layout with "flowables" ==
 
Example: Jekyll &amp; Hyde meet Platypus
 
<syntaxhighlight lang="python">
from reportlab.platypus import *
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.rl_config import defaultPageSize
 
from reportlab.lib.pagesizes import A4
from reportlab.lib.units import inch, cm
import sys
import html5lib
 
 
leftPadding = 6
rightPadding = 6
bottomPadding = 6
topPadding = 6
 
pagew, pageh = A4
framew = (pagew / 2) - leftPadding - rightPadding
frameh = pageh - topPadding - bottomPadding
leftColumn = Frame(0, 0, framew, frameh, leftPadding, bottomPadding, rightPadding, topPadding, id="leftColumn")
rightColumn = Frame((pagew/2), 0, framew, frameh, leftPadding, bottomPadding, rightPadding, topPadding, id="rightColumn")
styles = getSampleStyleSheet()
elements = []
 
def header(txt):
    s = Spacer(0.2*inch, 0.3*inch)
    elements.append(s)
    para = Paragraph(txt, styles["Heading1"])
    elements.append(para)
 
def p(txt):
    s = Spacer(0.2*inch, 0.1*inch)
    elements.append(s)
    para = Paragraph(txt, styles["Normal"])
    elements.append(para)
 
# NOT USED
# def pre(txt):
#    s = Spacer(0.1*inch, 0.1*inch)
#    elements.append(s)
#    p = Preformatted(txt, styles["Code"])
#    elements.append(p)
 
# Read the HTML and "perform" the h1 and p elements
with open("jekyll.html") as f:
    t = html5lib.parse(f, treebuilder="etree", namespaceHTMLElements=False)
    for elt in t.find(".//body"):
        if elt.tag == "h1":
            header(elt.text)
        elif elt.tag == "p":
            p(elt.text)
 
twoColumnPage = PageTemplate(id="base", frames=[leftColumn, rightColumn], pagesize=A4)
doc = BaseDocTemplate("jekyll.pdf", pageTemplates=[twoColumnPage])
# elements.insert(0,Spacer(0,inch))
# doc = SimpleDocTemplate('gfe.pdf')
doc.build(elements)
</syntaxhighlight>
 
Result: [[jekyll/jekyll.pdf|jekyll.pdf]]
 
== Example: SICV Random Walk ==
 
http://guttormsgaard.activearchives.org/cgi-bin/walk.cgi
 
== RML ==
 
RML is a report-lab specific document markup language similar to HTML but much more limited (and specific to the capabilities of Report Lab). The &quot;official&quot; tools to process RML and produce PDFs are commercial, but there exist alternative open source implementations based on the open source report lab library.
 
* [https://pypi.python.org/pypi/trml2pdf/0.1 trml2pdf] [https://github.com/romanlv/trml2pdf gitlab]
* [https://pypi.python.org/pypi/z3c.rml z3c]
 
== Flexbox ==
 
http://reportlab-flexbox.readthedocs.io/en/latest/overview.html
 
Sverker Sjöberg has implemented an extension library for ReportLab that implments a "FlexBox".
 
 
[[Category:Cookbook]] [[Category:Python]] [[Category:PDF]] [[Category:PagedMedia]]

Latest revision as of 11:29, 24 January 2024

Links

ReportLab is a hybrid free-software / commercial enterprise. The core python library is published with a Free Software License. On top of this a commercial company exists that offers products such as tools that work with RML, a specialized markup language. That said, alternative free software alternatives exist (made from a larger user community) to process RML, as well as the possibility to make your own.

Hello world

Nice demo of the "page as canvas" "low-level" way of working with ReportLab.

from reportlab.pdfgen import canvas
 
c = canvas.Canvas("hello.pdf")
c.drawString(100, 100, "Hello WORLD!")
c.save()

Creates a pdf from a .txt file.

From the Report Lab How to PDF:

The pdfgen package is the lowest level interface for generating PDF documents. A pdfgen program is essentially a sequence of instructions for "painting" a document onto a sequence of pages. The interface object which provides the painting operations is the pdfgen canvas.

The Canvas constructor:

def __init__(self,filename,
    pagesize=(595.27,841.89),
    bottomup = 1,
    pageCompression=0,
    encoding=rl_config.defaultEncoding,
    verbosity=0
    encrypt=None):

pageloop

This is a loop that opens a PDF with report lab ...

from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.pagesizes import letter, A4
from reportlab.lib.units import inch, cm
import sys
from reportlab.pdfbase.ttfonts import TTFont, pdfmetrics

fontpath = "OSP-DIN.ttf"
font =  TTFont('MyFontName', fontpath)
pdfmetrics.registerFont(font)
c = Canvas("pageloop.pdf", pagesize=A4)

for i in range(1000):
    c.setPageSize(A4)
    c.setFont('MyFontName', 72)
    # c.drawString(10*cm, 0.5*cm, "Page {0}".format(i))
    c.drawCentredString(A4[0]/2, A4[1]/2, "Page {0}".format(i))
    c.showPage()
c.save()

File:ReporLabPageloop.pdf

pageloop with different sizes

from reportlab.pdfgen.canvas import Canvas
from reportlab.lib.pagesizes import A4, A5
from reportlab.lib.units import cm
from reportlab.pdfbase.ttfonts import TTFont, pdfmetrics
import sys


pdfmetrics.registerFont(TTFont('din', "OSP-DIN.ttf"))
pdfmetrics.registerFont(TTFont('lib', "Libertinage-x.ttf"))
c = Canvas("pageloopdifferentsizes.pdf", pagesize=A4)

for i in range(1000):
    if i%2==0:
        ps = A4
        c.setFont('din', 144)    
    else:
        ps = A5
        c.setFont('lib', 72)
    c.setPageSize(ps)    
    # c.drawString(10*cm, 0.5*cm, "Page {0}".format(i))
    c.drawCentredString(ps[0]/2, ps[1]/2, "Page {0}".format(i))
    c.showPage()
c.save()

SimpleDocTemplate

The "Platypus" system is a "higher level" interface that takes care of such niceties as creating "flowable" text (so you don't need to position every line yourself.

from reportlab.lib.pagesizes import A4
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer
from reportlab.lib.styles import getSampleStyleSheet

doc = SimpleDocTemplate("text.pdf", pagesize=A4,
                        rightMargin=72, leftMargin=72,
                        topMargin=72, bottomMargin=18)


content = []
styles = getSampleStyleSheet()

for line in open('file.txt'):
    line = line.strip()
    if line:
        p = Paragraph('<font size=12>'+line+'</font>', styles["Normal"])
        content.append(p)
        content.append(Spacer(1, 12))

doc.build(content)

Using Platypus to do a 2 column layout with "flowables"

Example: Jekyll & Hyde meet Platypus

from reportlab.platypus import *
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.rl_config import defaultPageSize

from reportlab.lib.pagesizes import A4
from reportlab.lib.units import inch, cm
import sys
import html5lib


leftPadding = 6
rightPadding = 6
bottomPadding = 6
topPadding = 6

pagew, pageh = A4
framew = (pagew / 2) - leftPadding - rightPadding
frameh = pageh - topPadding - bottomPadding
leftColumn = Frame(0, 0, framew, frameh, leftPadding, bottomPadding, rightPadding, topPadding, id="leftColumn")
rightColumn = Frame((pagew/2), 0, framew, frameh, leftPadding, bottomPadding, rightPadding, topPadding, id="rightColumn")
styles = getSampleStyleSheet()
elements = []

def header(txt):
    s = Spacer(0.2*inch, 0.3*inch)
    elements.append(s)
    para = Paragraph(txt, styles["Heading1"])
    elements.append(para)

def p(txt):
    s = Spacer(0.2*inch, 0.1*inch)
    elements.append(s)
    para = Paragraph(txt, styles["Normal"])
    elements.append(para)

# NOT USED
# def pre(txt):
#     s = Spacer(0.1*inch, 0.1*inch)
#     elements.append(s)
#     p = Preformatted(txt, styles["Code"])
#     elements.append(p)

# Read the HTML and "perform" the h1 and p elements
with open("jekyll.html") as f:
    t = html5lib.parse(f, treebuilder="etree", namespaceHTMLElements=False)
    for elt in t.find(".//body"):
        if elt.tag == "h1":
            header(elt.text)
        elif elt.tag == "p":
            p(elt.text)

twoColumnPage = PageTemplate(id="base", frames=[leftColumn, rightColumn], pagesize=A4)
doc = BaseDocTemplate("jekyll.pdf", pageTemplates=[twoColumnPage])
# elements.insert(0,Spacer(0,inch))
# doc = SimpleDocTemplate('gfe.pdf')
doc.build(elements)

Result: jekyll.pdf

Example: SICV Random Walk

http://guttormsgaard.activearchives.org/cgi-bin/walk.cgi

RML

RML is a report-lab specific document markup language similar to HTML but much more limited (and specific to the capabilities of Report Lab). The "official" tools to process RML and produce PDFs are commercial, but there exist alternative open source implementations based on the open source report lab library.

Flexbox

http://reportlab-flexbox.readthedocs.io/en/latest/overview.html

Sverker Sjöberg has implemented an extension library for ReportLab that implments a "FlexBox".