ReportLab Tutorials

Up and running with ReportLab in minutes. These tutorials use Django 1.6+. 


Invoice - JSON to PDF

This example shows how to take an JSON data and use it to create up-to-date brochures and checklists.

Learn how text, data and iexisitng PDF's can be easily included and the powerful layout options ReportLab gives.

See more...

 

 

 

 

 

 


Product Catalogue

ReportLab is a natural choice for converting any kind of XML feed into beautiful print-ready publications.

This example shows how to take an XML description of products available in an online store and use it to create up-to-date brochures and checklists. Learn how text, data and images can be easily included and the powerful layout options ReportLab gives.

The principles learnt could easily be extended into more complex documents.

See more...

 

 

Hedge Fund Report

Complex financial reports are a breeze with ReportLab. See how to pull a range of financial data from a Django application to produce a report, including complex tables and custom data graphics.

Learn how ReportLab can dynamically display data the way you want it to, and get a taste for the almost limitless design options possible. 

See more...

 

 

 


Fund Facts - JSON to PDF

This example shows how to take JSON data and use it to create up-to-date fund fact sheets. Learn how text, data and graphs can be easily included and the powerful layout options ReportLab gives.

See more...

 

 

 

 

 

 

 

 


 

Convert HTML to RML

from preppy import SafeString
from rlextra.radxml.xhtml2rml import xhtml2rml
from rlextra.radxml.html_cleaner import cleanPlain

 

data = "<p>This is raw data with <em>HTML</em> <b>paragraph</b></p>"
data2 = "This is raw data with <em>HTML</em> <b>paragraph</b>"

1: Raw XHTML data example; preppy quoting escapes the tags

    <para>{{data}}</para>

2: cleanPlain Strips XHTML tags example

<para style="normal">{{cleanPlain(data)}}</para>

3: XHTML data without para tags but with inline tags, ensure the data is enclosed in an RML para tag
    SafeString tells preepy not to xml escape the contents
    xhtml2rml converts the XHTML to RML

<para style="normal">{{SafeString(xhtml2rml(data2))}}</para>

4: XHTML to RML data example - without a specified paraStyle, ensure there are no RML para tags around the data.
    When there no paraStyles specified with the content, xhtml2rml assumes paraStyle='normal', tableStyle='noPaddingStyle', bulletStyle='bullet' exists in your style sheets
{{SafeString(xhtml2rml(data))}}


5: XHTML to RML data example - with a specified paraStyle, ensure there are no RML para tags around the data
{{SafeString(xhtml2rml(data, paraStyle="normal"))}}

 

 

Product Catalogue Tutorial

XML product listing converted to a fully customisable PDF in seconds.

Welcome to the new ReportLab tutorial. Here you can get a basic introduction to a common application architecture and start experimenting with some fundamental ReportLab technologies. If you have any problems or questions, please email enquiries@reportlab.com.

We'll show you how to generate a well laid out and styled document from an XML feed. Let's get started!

Register and install an evaluation copy of ReportLab PLUS

This tutorial is aimed at showing the use of Report Markup Language (RML), which is a component of our commercial tool-kit. All you need to do to download a full evaluation copy is sign in or register on our site; then, follow the installation instructions to get yourself set up. Once these are completed, you're ready to go.

Download and install tutorial pack

First thing's first: download our tutorial pack. This includes a number of images which you will need later.

Take a look at the directory structure:

data/ 
output/
rml/
product_catalog.py
  • data/ will hold our XML
  • rml/ will hold the fonts, images, and templates for constructing the documents 
  • output/ will hold the generated PDFs
  • product_catalog.py will be the script which ties it all together

Making your first document in Report Markup Language

Execute python product_catalog.py, you should see the following output:

 

#################### 
about to parse file:  ../data/products.xml 
file parsed OK 

Trying to regenerate the check-list 
Check-list failed! Error: 
'Product' object has no attribute 'imgURL' 

Trying to regenerate the flyer 
success! created output/harwood_flyer.pdf 
#################### 

 

Notice that your 'checklist' is broken; that's ok for now, we'll come back to that later. Let's take a look at the flyer PDF. It's in /output/

You should see a PDF that looks like this:

The data is coming from the XML file, products.xml located in /data/. A standard technique is to build up Python objects with the variable data of interest and pass it to our templating system, preppy. Preppy generates an RML (Report Markup Language) file, which is our own mark-up language designed to lay out documents. A single line of code then converts an RML file into a PDF. We'll look at this process later, but for now, let's dive right in and get the document looking right.

Everything related to the layout and content of the document is described within the 'Prep file', flyer_template.prep which is within the /rml/ directory. Let's take a quick tour before making changes.

Inside a Preppy template

The file looks a lot like XML, with various bits of Python included within braces {{}}. This allows you to import functions and call on data objects which have been passed in.

The whole document is wrapped in a tag, with some key sections within it:

Making your first change: adding some new data

First, let's turn our attention to the story where we loop over the product objects (starts line 86 in flyer_template.prep):

We're looping over all our products and printing a paragraph for each product's name. Let's add product summary and product price as well; your story should now look like this:

Now execute python product_catalog.py and look at the results. You should see output like shown below, with new facts about each product displayed: 

Adding a page template

We have more content, but the appearance is still not ideal. Let's see how we can use a page template to arrange our content. Go back to templates and take note of each part:

By default, the PDF rendering engine uses the first template until it is told otherwise, so in this case, 'blank' has been used on all pages.

Let's include a set next template at the start of the story to use this 'products' template:

Adding some static PDF pages

Notice that a nice PDF background has been used on which the products list is printed. That can also be used to include full static pages. Let's use pre-made PDFs to replace the blank first page and insert a standard end page. Your story should look like this:

And the generated PDF should now have pages like the following included:

Learning some basic page flow controls

Now let's make the designer proud. First, note that page 3 beings with the text "meat...":

Ideally, we would be able to keep the descriptions from breaking across pages, so that all the information about a product stayed together. RML has many ways of controlling page flow and layouts, and in this case, we can use the keepWithNext attribute on these paragraph styles (prod_summary and prod_name). Your stylesheet should now look like this:

Notice that now page 3 has the entire block of content carried over together:

Getting fonts and colors correct

Finally, let's get our colors and fonts correct. We can register a new font and a new color in the docinit section; edit yours to look like this:

Now make a few small changes:

  • change 'red' to 'GREEN-ISH' in line 34
  • change fontName to 'Angelina' in line 50 and 64
  • change fontSize to '8' in line 73
  • change spaceBefore to '4' in lines 75 and 84
  • change textColor to 'GREEN-ISH' in lines 76 and 85

And regenerate the document one last time:

 

And there you have it, a professionally finished document created on the fly from an XML file. There is plenty more to learn to control the flow for more complex documents - see the RML users guide.

Looking at the data source

Now let's turn our attention to how we passed the data into the template in the first place. Open product_catalog.py. For now, lets focus on lines 44-64, where we see the main loop over the XML to build product objects:

Remember how the checklist has been failing to generate? This is because the PDF engine has been complaining that the Prep file is trying to access an attribute imgURL of the products which does not exist. If we check the XML, we'll see that there is a tag <ImageUrl>. Let's try giving our product objects an attribute based on this:

Now try building the document again. You will need to download a pack of images and extract the /img directory within your /rml directory for this to work:

Let's tidy up this issue when there is no set price and the 'request a quote' text does not fit into the small box. Let's put a conditional statement in our template which uses a different size box when the quote gets big. Your story should now look like this: (in /rml/checklist_template.prep)

Rebuild the document:

Finally, if all this meat is getting to you, you can change the vegetarian setting in line 11 of checklist_template.prep to True:

 

JSON To PDF - Invoice Tutorial

JSON data for an invoice, converted to a fully customisable PDF in seconds.

Getting started

Register and install an evaluation copy of ReportLab PLUS

This tutorial is aimed at showing the use of Report Markup Language (RML), which is a component of our commercial tool-kit. Here you can get a basic introduction to a common application architecture and start experimenting with some fundamental ReportLab technologies. If you have any problems or questions, please email enquiries@reportlab.com.

All you need to do to download a full evaluation copy is sign in or register on our site; then, follow the installation instructions to get yourself set up. Once these are completed, you're ready to go.

To check that all the dependencies are in place, start Python up (inside your virtual environment, if you are using one) and check these imports all work:

>>> import reportlab
>>> import rlextra

Download and install tutorial pack

You have two options, either download the partial tutorial pack, which means you will need to finish to the code changes listed below or download the completed tutorial pack, which means you will not need to make the changes listed below.

Take a look at the directory structure:

data/ 
output/
rml/
gen_invoice.py
  • data/ will hold our JSON data
  • rml/ will hold the fonts, images, and templates for constructing the documents 
  • output/ will hold the generated PDFs
  • gen_invoice.py will be the script which ties it all together

Making your first document in Report Markup Language

python gen_invoice.py  data/invoice.json

You should now see a file output/invoice.pdf, which should look like:

It is not much to look at in its current state, but we will make some improvements along the way.

Code Walk Though

We open and process the JSON data in jsondict.py, which lets us iterate over child nodes and access elements with a dot-notation. The PDF template is rml/invoice.prep, open that file in an editor.

We define the frame(sections) on the page in the pagetemplate tag. During development, setting showBoundary can help be a visual guide to getting frames in the right place. Change the value from 0 to 1

Now generate the PDF again & you should see the the outline of the frames.  Change showBoundary back to 0.

In the rlextra package, we can include other PDFs, so if you have stock PDF assests/templates already, we can draw over the top of them.  We can achive this in a pageGraphics tags. Here we specify the path and dimensions of the PDF, add this at line 8:

Now generate to PDF again.

We can add some further enhancements to the style & make it a bit more colourful. In the stylesheet we can change the style. Now we add a blue background with white text:

We can define styles in the stylesheet tags, including paragraph styles: We can use the dot notation that jsondict.py allows.

In the template we can use a for loop to display the order:

 

Now generate the PDF again. The ouput should look like this:

Finally, a crude example of including Python code directly in the template. The script tag allows us to embed Python code. Lets say we plan to double check that the totals in the data match a computed value:

We can now add a call verify_totals() & print an error if accordingly. However, rather than display a warning on the PDF itself, a better approach might be to call any data validation code alot ealier & raise an error so that the PDF does not get generated.

Now look at line 21 in data/invoice.json change

       "price": "£1300.00",

to:

       "price": "£1000.00",

Now save data.json and re-run the script and check the output.

Further examples of the huge range of chart types available with ReportLab can be found in our chart gallery which included details of the main parameters of each style. Go and experiment!

 

Fund Reporting Tutorial

Financial reporting and dynamic graphics

Getting started

First, download and unpack the tutorial pack.

Copy this to the directory you wish to use for the project.

As this is a ReportLab tutorial, it should come as no surprise that you will need to download and install our software. You will need to sign in or register on our site; then, follow the installation instructions to get yourself set up.

This tutorial is designed to run on ReportLab 2.7 to 3.0+ and Django 1.6+.

To check that all the dependencies are in place, start Python up (inside your virtual environment, if you are using one) and check these imports all work:

 

Python 2.7.3 (default, Aug  1 2012, 05:14:39)
[GCC 4.6.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import django
>>> django.VERSION
(1, 6, 1, 'final', 0)
>>> import reportlab
>>> import _rl_accel
>>> import _renderPM
>>> import PIL._imaging
>>> import preppy
>>> import pyRXPU >>> import rlextra >>>

Setting up the database

The database is based on SQLite3, and by running the Django syncdb command inside the /project/ directory, you will create the necessary database file.

%   python manage.py syncdb

Create a superuser account when prompted. This creates an SQLITE database file "project/fundreport.db". Sqlite is built into Python so no separate database engine is needed. It will also load in some records from a fixture, giving you 3 funds and a few numbers and facts to display. We have NOT attempted to create a realistic risk management database; we just want to have some facts in there to display in the report.

Start your local server:

%   python manage.py runserver

Then browse to:

http://localhost:8000/admin/ to log into the admin interface and browse the available data.

To see a web view listing the available PDFs, browse here: http://localhost:8000/ and click on any link to generate the corresponding PDF.

To generate PDFs from the command line, use the following command, taking the fund ID as an argument (available funds are 1,2, and 3):

%   python manage.py makepdf 1 (or 2, 3 etc)

We will assume that readers of this tutorial are familiar enough with Django to understand the basic URLs and views implemented in this application. As such, we will focus on key elements of the PDF and show how they are created in the document template (/project/fundreport/rml/fundreport.prep).

PDF walkthrough

Cover page

Using one of the methods above, create the PDF for fund ID 1:

This cover page is laid out in the template section of the prep file:

Line chart

The next page shows a basic table and a line chart:

The graphic itself is drawn dynamically using a python module, fundreport.charts.monthperf12mo. This file was created by the ReportLab Drawing Editor, which you can start by calling:

python rlextra/graphics/guiedit/guiedit.py

One running, you can use this editor to open and inspect the chart, monthperf12mo.py:

You can adjust the attributes of the chart using this editor, which will save the chart as a python module. This is then accessed within the prep file and used to render a graphic in the PDF. Any variable attributes may be passed in in the prep file:

The module attribute determines the python file used, the function attribute gives the name of the chart class within that module, and the flexible <param> tag can be used to override any attribute within the chart module by declaring it with the name attribute.

In this example, we are setting chart.data to be line_chart_data, a list of lists we constructed earlier and passed into this template.

Returns table

The next page shows a complex table lined up next to a chart:

In addition to providing a further example of how to dynamically include graphics into the template, it illustrates a few key techniques.

Get your measurements right ONCE

We cannot stress enough how important planning is when laying out documents. Our tools are specifically designed to give you complete control over the explicit size and position of any element on the page, and you should take advantage of this by deciding up front how the page should look.

In this example, we use a container table with fixed widths to position the inner table and chart, each of which takes up one cell of the container:

We allocate 293 points of space to the table, and when we create our chart in the drawing editor, as long as we make sure we keep the width set to 293, we can be confident that the chart will always fit perfectly on the page.

Since the height of the chart will vary depending on the number of rows there are in the table, we can dynamically pass in the height attributes when we render the chart in the PDF:

This way, we can be sure that the bars in the chart will always line up with the appropriate row of the table.

You may be wondering what happens when the table gets too big to fit on one page. Try adding additional data to your database and find out! (HINT: see the <keepInFrame> tag at line 263).

Don't be afraid of Python

We love Python, and if you're interested in Django and ReportLab, there's a good chance you do as well. Our templating tool, preppy, gives you the chance to include python expressions within the document template where necessary. Certainly, most of your Python code belongs in utilities and views within your Django app, but some things just make sense to live in the template. See for example our small script which determines the row heights of the table and the corresponding height of the chart:

Also note how we can import functions from a separate module

negRedTd(), for example is a formatting function for number which can color them depending on value, such as making negative numbers red. Take a look at this function inside fundreport.rml_utils.

The other tables and charts in the document use very similar techniques:

Back page advert

Finally, it is worth noting that static pages may be pulled in and used as vector graphics or entire page inserts. There is a pre-made PDF inside your /rml/ directory called advert.pdf:

Pulling this in as the last page of the report is as simple as a single tag:

Futher examples of the huge range of chart types availble with ReportLab can be found in our chart gallery which included details of the main parameters of each style. Go and experiment!

 

JSON To PDF - Fund Report Tutorial

JSON data for an fund report, converted to a fully customisable PDF in seconds.

 

Getting started

Register and install an evaluation copy of ReportLab PLUS

This tutorial is aimed at showing the use of Report Markup Language (RML), which is a component of our commercial tool-kit. Here you can get a basic introduction to a common application architecture and start experimenting with some fundamental ReportLab technologies. If you have any problems or questions, please email enquiries@reportlab.com.

All you need to do to download a full evaluation copy is sign in or register on our site; then, follow the installation instructions to get yourself set up. Once these are completed, you're ready to go.

To check that all the dependencies are in place, start Python up (inside your virtual environment, if you are using one) and check these imports all work:

>>> import reportlab
>>> import rlextra

Download and install tutorial pack

You have two options, either download the partial tutorial pack, which means you will need to finish to the code changes listed below or download the completed tutorial pack, which means you will not need to make the changes listed below.

Take a look at the directory structure:

data/ 
output/
rml/
gen_factsheet.py
  • data/ will hold our JSON data
  • rml/ will hold the fonts, images, and templates for constructing the documents 
  • output/ will hold the generated PDFs
  • gen_factsheet.py will be the script which ties it all together

Making your first document in Report Markup Language

python gen_factsheet.py  data/factsheet.json

You should now see a file output/factsheet.pdf, which should look like:

It is not much to look at in its current state, but we will make some improvements along the way.

Code Walk Though

The PDF template is rml/factsheet.prep, open that file in an editor. We define the frame(sections) on the page in the pagetemplate tag. During development, setting showBoundary can help be a visual guide to getting frames in the right place. Change the value from 0 to 1. Now generate the PDF again & you should see the the outline of the frames.  Change showBoundary back to 0.

Add colours

Lets add some coloured rectangles to the page. We can add the colours to sit behind the content, to give it some colour. We use the rect tag to draw rectangles on the page & set the colour accordingly. Add the following lines below:

We can also add colour to the Keyfacts table that appears on the right of the page.

Now regenerate the PDF.

Adding charts

We are now going to add two charts to the prep file.

Line Chart

The code for fundindexlineplot.py was generated by our our graphics library.

Pie Chart

The code for assets_pie.py was also generated by our our graphics library.

Finaly, look in data/factsheet.json and change the "status" to "approved":

"status": "approved",

Now save data.json and re-run the script and check the output. It should look like this:

Further examples of the huge range of chart types available with ReportLab can be found in our chart gallery which included details of the main parameters of each style. Go and experiment!