Skip to main content

PDF Report Generation in Python

Extensive Guide to PDF Report Generation in Python

Creating PDF reports with Python allows you to generate professional documents with text, tables, images, and plots. This comprehensive tutorial covers everything from basic PDF generation to advanced customization and data visualization in PDF reports using the ReportLab and Matplotlib libraries.

1. Installing Required Libraries

To generate PDFs and add plots, you'll need the ReportLab and Matplotlib libraries. Install them using:

pip install reportlab matplotlib

2. Basic PDF Creation

Learn how to create a basic PDF document using ReportLab:

2.1 Creating a PDF Document

from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

# Create a PDF file
c = canvas.Canvas("basic_example.pdf", pagesize=letter)
width, height = letter

# Add text
c.drawString(100, height - 100, "Hello, ReportLab!")
c.drawString(100, height - 120, "This is a simple PDF document.")

# Save the PDF
c.save()

3. Setting Page Width and Height

You can customize the dimensions of your PDF pages by specifying the width and height directly:

from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import landscape

# Custom page size (width x height)
page_width = 600
page_height = 400

# Create a PDF file with custom dimensions
c = canvas.Canvas("custom_page_size.pdf", pagesize=(page_width, page_height))

# Add text
c.drawString(100, page_height - 100, "Custom Page Size")
c.drawString(100, page_height - 120, "Width: 600 points, Height: 400 points")

# Save the PDF
c.save()

Alternatively, use predefined page sizes like A4, letter, or landscape:

from reportlab.lib.pagesizes import A4, landscape

# Create a PDF file with A4 page size
c = canvas.Canvas("A4_page_size.pdf", pagesize=A4)
width, height = A4

# Add text
c.drawString(100, height - 100, "A4 Page Size")
c.drawString(100, height - 120, "Width: 210mm, Height: 297mm")

# Save the PDF
c.save()

# Create a PDF file with landscape orientation
c = canvas.Canvas("landscape_page_size.pdf", pagesize=landscape(A4))
width, height = landscape(A4)

# Add text
c.drawString(100, height - 100, "Landscape A4 Page Size")
c.drawString(100, height - 120, "Width: 297mm, Height: 210mm")

# Save the PDF
c.save()

4. Adding Text to PDFs

Customize the text appearance and add formatted text using ReportLab's styling features:

4.1 Adding Styled Text

from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import SimpleDocTemplate, Paragraph

# Create a PDF file
doc = SimpleDocTemplate("styled_text.pdf", pagesize=letter)
styles = getSampleStyleSheet()

# Create content
content = []
content.append(Paragraph("This is a heading", styles['Title']))
content.append(Paragraph("This is a paragraph of text. You can customize fonts, sizes, and colors using ParagraphStyle.", styles['Normal']))

# Build PDF
doc.build(content)

4.2 Adding Multiple Lines and Text Formatting

from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import ParagraphStyle
from reportlab.platypus import SimpleDocTemplate, Paragraph

# Custom style
custom_style = ParagraphStyle('CustomStyle', fontName='Helvetica-Bold', fontSize=12, spaceAfter=10)

# Create a PDF file
doc = SimpleDocTemplate("multiple_lines.pdf", pagesize=letter)
content = [
    Paragraph("Line 1: Basic Text", custom_style),
    Paragraph("Line 2: Another Line with a Different Style", custom_style),
]

# Build PDF
doc.build(content)

5. Adding Images to PDFs

Embed images in your PDF, such as plots generated with Matplotlib:

5.1 Adding a Static Image

from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

# Create a PDF file
c = canvas.Canvas("image_example.pdf", pagesize=letter)
width, height = letter

# Add an image
c.drawImage('image.png', 100, height - 500, width=400, height=300)

# Save the PDF
c.save()

5.2 Adding a Plot Image

Generate a plot with Matplotlib and embed it into the PDF:

import matplotlib.pyplot as plt

# Create a plot
x = [1, 2, 3, 4, 5]
y = [2, 3, 5, 7, 11]
plt.plot(x, y)
plt.title('Sample Plot')
plt.xlabel('X-axis')
plt.ylabel('Y-axis')

# Save the plot as an image
plt.savefig('plot.png')
plt.close()

# Add plot image to PDF
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

c = canvas.Canvas("pdf_with_plot.pdf", pagesize=letter)
width, height = letter

# Add plot image
c.drawImage('plot.png', 100, height - 500, width=400, height=300)
c.save()

6. Creating Tables in PDFs

Use ReportLab’s Platypus to create tables with headers and data:

from reportlab.platypus import SimpleDocTemplate, Table, TableStyle
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
from reportlab.lib.colors import pink, lightblue

# Create a PDF file
doc = SimpleDocTemplate("table_example.pdf", pagesize=letter)
data = [['Name', 'Age', 'City'],
        ['Alice', 25, 'New York'],
        ['Bob', 30, 'Los Angeles'],
        ['Charlie', 35, 'Chicago']]

# Create table and apply styles
table = Table(data)
table.setStyle(TableStyle([('BACKGROUND', (0, 0), (-1, 0), pink),
                           ('TEXTCOLOR', (0, 0), (-1, 0), lightblue),
                           ('ALIGN', (0, 0), (-1, -1), 'CENTER'),
                           ('GRID', (0, 0), (-1, -1), 1, lightblue)]))

# Build PDF
doc.build([table])

7. Managing Pages in PDFs

To add multiple pages and control page content, use the showPage() method:

from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

# Create a PDF file
c = canvas.Canvas("multiple_pages.pdf", pagesize=letter)
width, height = letter

# Add content to first page
c.drawString(100, height - 100, "Page 1")
c.showPage()  # End the current page and start a new one

# Add content to second page
c.drawString(100, height - 100, "Page 2")

# Save the PDF
c.save()

8. Adding Multiple Plots on One Page

Combine multiple plots on a single page:

import matplotlib.pyplot as plt
from reportlab.lib.pagesizes import letter
from reportlab.pdfgen import canvas

# Create plots
fig, axs = plt.subplots(2, 2, figsize=(8, 6))
for ax in axs.flat:
    ax.plot([1, 2, 3], [4, 5, 6])
    ax.set_title('Plot')

# Save plots as images
plt.savefig('multiple_plots.png')
plt.close()

# Add plots image to PDF
c = canvas.Canvas("pdf_with_multiple_plots.pdf", pagesize=letter)
width, height = letter

c.drawImage('multiple_plots.png', 50, height - 500, width=500, height=400)
c.save()

9. Customizing PDF Appearance

Apply custom styles, fonts, and colors to your PDF content:

from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.platypus import SimpleDocTemplate, Paragraph

# Custom styles
styles = getSampleStyleSheet()
custom_style = ParagraphStyle('CustomStyle', fontName='Helvetica-Bold', fontSize=14, textColor='blue', spaceAfter=10)

# Create PDF
doc = SimpleDocTemplate("customized_pdf.pdf", pagesize=letter)
content = [
    Paragraph("This is a custom-styled heading", custom_style),
    Paragraph("This is a paragraph with customized font and color.", styles['Normal']),
]

# Build PDF
doc.build(content)

10. Final Tips and Best Practices

  • Ensure paths to images and resources are correct to avoid errors in PDF generation.
  • Utilize ReportLab’s Platypus module for more complex document structures and layout management.
  • For large or complex documents, consider breaking the content into sections or separate PDFs and merging them if necessary.
  • Test your PDF generation code thoroughly to ensure that all content is rendered correctly and meets your formatting requirements.

Comments

Popular posts from this blog

How to Add External Libraries (JAR files) in Eclipse

How to Add External Libraries (JAR files) in Eclipse Adding external libraries (JAR files) to your Eclipse project allows you to use third-party code in your application. This guide will explain what JAR files are, how they differ from `.java` files, where to download them, and how to add them to your project. What are JAR Files? JAR (Java ARchive) files are package files that aggregate many Java class files and associated metadata and resources (such as text, images, etc.) into a single file for distribution. They are used to distribute Java programs and libraries in a platform-independent format, making it easier to share and deploy Java applications. Difference between .java and .jar Files .java files are source files written in the Java programming language. They contain human-readable Java code that developers write. In contrast, .jar files are compile...

Creating and Reading Text Files in Java

Creating and Reading Text Files in Java Handling text files is a common task in Java programming. This guide will cover how to create, write to, and read from text files using Java. We will use Java's built-in classes and methods to achieve this. You'll also learn about file management techniques to handle files efficiently. 1. Creating and Writing to Text Files Java provides several ways to create and write to text files. We will use the `FileWriter` and `BufferedWriter` classes for this purpose. The `FileWriter` class is used for writing character data to a file, while `BufferedWriter` provides buffering to improve performance. 1.1 FileWriter Class The `FileWriter` class is a basic way to write text to a file. It writes characters to a file using the default character encoding. import java.io.FileWriter; import java.io.IOException; public clas...

Managing Hierarchical Structures: OOP vs Nested Maps in Java

Managing Hierarchical Structures: OOP vs Nested Maps in Java This topic explores the pros and cons of managing hierarchical data using Object-Oriented Programming (OOP) versus nested map structures in Java. This discussion is contextualized with an example involving a chip with multiple cores and sub-cores. Nested Map of Maps Approach Using nested maps to manage hierarchical data can be complex and difficult to maintain. Here’s an example of managing a chip with cores and sub-cores using nested maps: Readability and Maintainability: Nested maps can be hard to read and maintain. The hierarchy is not as apparent as it would be with OOP. Encapsulation: The nested map approach lacks encapsulation, leading to less modular and cohesive code. Error-Prone: Manual management of keys and values increases the risk of errors, such as NullPointerExce...