How to create a pdf report Reportlab

0

I was wondering how could I create a pdf report using reportlab. I’m developing a web site and I’m using Django. In my project I charged a lot of icons, and I was using a Javascript function(PrintThisjs), but it doesn’t work well. Seems like Reportlab is a good solution. Thanks :slight_smile:

Reportlab is awesome. It took me about a day or two to figure out how to programmatically produce quite complex PDF-files. I installed Reportlab into my venv and then I created a folder inside my project called pdf_generator. I created a file called factory.py. I have a method in there which takes a user, a month, a year and a project. Users will enter their work time into the system and then the system will produce a printable time sheet in the form of a PDF, save it and return the path to the file. Here’s the code I wrote. This will give you an example of how to create a basic document and put a table into it that is filled with data. I hope this will help you to get started.

import datetime
import os
from ahub import settings as s
from django.utils.timezone import now
from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Image
from reportlab.lib.pagesizes import A4, cm
from reportlab.lib import colors
from time_manager.entry.models import Entry


class PDFGenerator(object):
    """ This class contains factory methods for creating PDF files. The methods should create and store the PDF and
        return the file path. """

    @staticmethod
    def get_directory():
        """ Build the path for the directory to store in. Takes the username as argument. """
        directory = os.path.join(s.MEDIA_ROOT, 'time_manager', 'pdf', 'temp')
        # Create directory if it doesn't exist yet.
        if not os.path.exists(directory):
            os.makedirs(directory)

        return directory

    @staticmethod
    def time_sheet(user, year, month, project):
        """ Creates a time sheet with the work time a user entered for a certain project. """
        # Store the PDF in a sub folder named after the username with the following filename format:
        # YYYYMMDD_ZE_NameConsultant_Project_MMYY
        date = datetime.date(year=year, month=month, day=1)
        filename = now().strftime('%Y%m%d') + '_ZE_' + user.last_name + user.first_name + '_' + project.customer + \
            '_' + date.strftime('%m%y') + '.pdf'
        directory = PDFGenerator.get_directory()
        store_path = os.path.join(directory, filename)
        # Initiate doc.
        doc = SimpleDocTemplate(store_path, pagesize=A4, rightMargin=72, leftMargin=72, topMargin=72, bottomMargin=18)
        # Build header.
        header_text = 'Stundenzettel\n' + user.last_name + ', ' + user.first_name + '\n' + project.customer + '\n' + \
                      date.strftime('%B %Y')
        header_logo = Image(os.path.join(s.BASE_DIR, 'pdf_generator', 'files', 'logo_auticon.jpg'))
        header_table = Table([(header_text, header_logo,)], colWidths=[8*cm], rowHeights=[5*cm])
        header_table.setStyle(TableStyle([('VALIGN', (0, 0), (-1, -1), 'TOP'),
                                          ('ALIGN', (0, 0), (0, 0), 'LEFT'),
                                          ('ALIGN', (1, 0), (1, 0), 'RIGHT'),
                                          ]))
        # Build content table.
        content_table = Table(data=Entry.render_entries_for_pdf(user, year, month, project))
        content_table.setStyle(TableStyle([('INNERGRID', (0, 0), (-1, -1), 0.25, colors.gray),
                                           ('ALIGN', (3, 0), (-1, -1), 'RIGHT'),
                                           ]))
        # Build footer.
        footer_top_row = ('', '', '', '', '')
        footer_bot_row = ('Ort/Datum', 'Kunde', '', 'Ort/Datum', 'Consultant', )
        footer_table = Table([footer_top_row, footer_bot_row], colWidths=[3*cm, 3*cm, 4*cm, 3*cm, 3*cm], rowHeights=[2*cm, 0.5*cm])
        footer_table.setStyle(TableStyle([('INNERGRID', (0, 0), (0, 1), 0.25, colors.gray),
                                          ('INNERGRID', (1, 0), (1, 1), 0.25, colors.gray),
                                          ('INNERGRID', (3, 0), (3, 1), 0.25, colors.gray),
                                          ('INNERGRID', (4, 0), (4, 1), 0.25, colors.gray),
                                          ]))
        # Build layout table.
        data = [(header_table, ), (content_table, ), (footer_table, )]
        layout_table = Table(data)
        layout_table.setStyle(TableStyle([('ALIGN', (0, 0), (-1, -1), 'CENTER')]))

        doc.build([layout_table])

        return store_path
2 Likes