12 KiB
12 KiB
PDF Features Reference
Advanced PDF capabilities: links, bookmarks, forms, encryption, and metadata.
Document Metadata
Set PDF document properties viewable in PDF readers.
from reportlab.pdfgen import canvas
c = canvas.Canvas("output.pdf")
# Set metadata
c.setAuthor("John Doe")
c.setTitle("Annual Report 2024")
c.setSubject("Financial Analysis")
c.setKeywords("finance, annual, report, 2024")
c.setCreator("MyApp v1.0")
# ... draw content ...
c.save()
With Platypus:
from reportlab.platypus import SimpleDocTemplate
doc = SimpleDocTemplate(
"output.pdf",
title="Annual Report 2024",
author="John Doe",
subject="Financial Analysis",
)
doc.build(story)
Bookmarks and Destinations
Create internal navigation structure.
Simple Bookmarks
from reportlab.pdfgen import canvas
c = canvas.Canvas("output.pdf")
# Create bookmark for current page
c.bookmarkPage("intro") # Internal key
c.addOutlineEntry("Introduction", "intro", level=0)
c.showPage()
# Another bookmark
c.bookmarkPage("chapter1")
c.addOutlineEntry("Chapter 1", "chapter1", level=0)
# Sub-sections
c.bookmarkPage("section1_1")
c.addOutlineEntry("Section 1.1", "section1_1", level=1) # Nested
c.save()
Bookmark Levels
# Create hierarchical outline
c.bookmarkPage("ch1")
c.addOutlineEntry("Chapter 1", "ch1", level=0)
c.bookmarkPage("ch1_s1")
c.addOutlineEntry("Section 1.1", "ch1_s1", level=1)
c.bookmarkPage("ch1_s1_1")
c.addOutlineEntry("Subsection 1.1.1", "ch1_s1_1", level=2)
c.bookmarkPage("ch2")
c.addOutlineEntry("Chapter 2", "ch2", level=0)
Destination Fit Modes
Control how the page displays when navigating:
# bookmarkPage with fit mode
c.bookmarkPage(
key="chapter1",
fit="Fit" # Fit entire page in window
)
# Or use bookmarkHorizontalAbsolute
c.bookmarkHorizontalAbsolute(key="section", top=500)
# Available fit modes:
# "Fit" - Fit whole page
# "FitH" - Fit horizontally
# "FitV" - Fit vertically
# "FitR" - Fit rectangle
# "XYZ" - Specific position and zoom
Hyperlinks
External Links
from reportlab.pdfgen import canvas
from reportlab.lib.units import inch
c = canvas.Canvas("output.pdf")
# Draw link rectangle
c.linkURL(
"https://www.example.com",
rect=(1*inch, 5*inch, 3*inch, 5.5*inch), # (x1, y1, x2, y2)
relative=0, # 0 for absolute positioning
thickness=1,
color=(0, 0, 1), # Blue
dashArray=None
)
# Draw text over link area
c.setFillColorRGB(0, 0, 1) # Blue text
c.drawString(1*inch, 5.2*inch, "Click here to visit example.com")
c.save()
Internal Links
Link to bookmarked locations within the document:
# Create destination
c.bookmarkPage("target_section")
# Later, create link to that destination
c.linkRect(
"Link Text",
"target_section", # Bookmark key
rect=(1*inch, 3*inch, 2*inch, 3.2*inch),
relative=0
)
Links in Paragraphs
For Platypus documents:
from reportlab.platypus import Paragraph
# External link
text = '<link href="https://example.com" color="blue">Visit our website</link>'
para = Paragraph(text, style)
# Internal link (to anchor)
text = '<link href="#section1" color="blue">Go to Section 1</link>'
para1 = Paragraph(text, style)
# Create anchor
text = '<a name="section1"/>Section 1 Heading'
para2 = Paragraph(text, heading_style)
story.append(para1)
story.append(para2)
Interactive Forms
Create fillable PDF forms.
Text Fields
from reportlab.pdfgen import canvas
from reportlab.pdfbase import pdfform
from reportlab.lib.colors import black, white
c = canvas.Canvas("form.pdf")
# Create text field
c.acroForm.textfield(
name="name",
tooltip="Enter your name",
x=100,
y=700,
width=200,
height=20,
borderColor=black,
fillColor=white,
textColor=black,
forceBorder=True,
fontSize=12,
maxlen=100, # Maximum character length
)
# Label
c.drawString(100, 725, "Name:")
c.save()
Checkboxes
# Create checkbox
c.acroForm.checkbox(
name="agree",
tooltip="I agree to terms",
x=100,
y=650,
size=20,
buttonStyle='check', # 'check', 'circle', 'cross', 'diamond', 'square', 'star'
borderColor=black,
fillColor=white,
textColor=black,
forceBorder=True,
checked=False, # Initial state
)
c.drawString(130, 655, "I agree to the terms and conditions")
Radio Buttons
# Radio button group - only one can be selected
c.acroForm.radio(
name="payment", # Same name for group
tooltip="Credit Card",
value="credit", # Value when selected
x=100,
y=600,
size=15,
selected=False,
)
c.drawString(125, 603, "Credit Card")
c.acroForm.radio(
name="payment", # Same name
tooltip="PayPal",
value="paypal",
x=100,
y=580,
size=15,
selected=False,
)
c.drawString(125, 583, "PayPal")
List Boxes
# Listbox with multiple options
c.acroForm.listbox(
name="country",
tooltip="Select your country",
value="US", # Default selected
x=100,
y=500,
width=150,
height=80,
borderColor=black,
fillColor=white,
textColor=black,
forceBorder=True,
options=[
("United States", "US"),
("Canada", "CA"),
("Mexico", "MX"),
("Other", "OTHER"),
], # List of (label, value) tuples
multiple=False, # Allow multiple selections
)
Choice (Dropdown)
# Dropdown menu
c.acroForm.choice(
name="state",
tooltip="Select state",
value="CA",
x=100,
y=450,
width=150,
height=20,
borderColor=black,
fillColor=white,
textColor=black,
forceBorder=True,
options=[
("California", "CA"),
("New York", "NY"),
("Texas", "TX"),
],
)
Complete Form Example
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import letter
from reportlab.lib.colors import black, white, lightgrey
from reportlab.lib.units import inch
def create_registration_form(filename):
c = canvas.Canvas(filename, pagesize=letter)
c.setFont("Helvetica-Bold", 16)
c.drawString(inch, 10*inch, "Registration Form")
y = 9*inch
c.setFont("Helvetica", 12)
# Name field
c.drawString(inch, y, "Full Name:")
c.acroForm.textfield(
name="fullname",
x=2*inch, y=y-5, width=4*inch, height=20,
borderColor=black, fillColor=lightgrey, forceBorder=True
)
# Email field
y -= 0.5*inch
c.drawString(inch, y, "Email:")
c.acroForm.textfield(
name="email",
x=2*inch, y=y-5, width=4*inch, height=20,
borderColor=black, fillColor=lightgrey, forceBorder=True
)
# Age dropdown
y -= 0.5*inch
c.drawString(inch, y, "Age Group:")
c.acroForm.choice(
name="age_group",
x=2*inch, y=y-5, width=2*inch, height=20,
borderColor=black, fillColor=lightgrey, forceBorder=True,
options=[("18-25", "18-25"), ("26-35", "26-35"),
("36-50", "36-50"), ("51+", "51+")]
)
# Newsletter checkbox
y -= 0.5*inch
c.acroForm.checkbox(
name="newsletter",
x=inch, y=y-5, size=15,
buttonStyle='check', borderColor=black, forceBorder=True
)
c.drawString(inch + 25, y, "Subscribe to newsletter")
c.save()
create_registration_form("registration.pdf")
Encryption and Security
Protect PDFs with passwords and permissions.
Basic Encryption
from reportlab.pdfgen import canvas
c = canvas.Canvas("secure.pdf")
# Encrypt with user password
c.encrypt(
userPassword="user123", # Password to open
ownerPassword="owner456", # Password to change permissions
canPrint=1, # Allow printing
canModify=0, # Disallow modifications
canCopy=1, # Allow text copying
canAnnotate=0, # Disallow annotations
strength=128, # 40 or 128 bit encryption
)
# ... draw content ...
c.save()
Permission Settings
c.encrypt(
userPassword="user123",
ownerPassword="owner456",
canPrint=1, # 1 = allow, 0 = deny
canModify=0, # Prevent content modification
canCopy=1, # Allow text/graphics copying
canAnnotate=0, # Prevent comments/annotations
strength=128, # Use 128-bit encryption
)
Advanced Encryption
from reportlab.lib.pdfencrypt import StandardEncryption
# Create encryption object
encrypt = StandardEncryption(
userPassword="user123",
ownerPassword="owner456",
canPrint=1,
canModify=0,
canCopy=1,
canAnnotate=1,
strength=128,
)
# Use with canvas
c = canvas.Canvas("secure.pdf")
c._doc.encrypt = encrypt
# ... draw content ...
c.save()
Platypus with Encryption
from reportlab.platypus import SimpleDocTemplate
doc = SimpleDocTemplate("secure.pdf")
# Set encryption
doc.encrypt = True
doc.canPrint = 1
doc.canModify = 0
# Or use encrypt() method
doc.encrypt = encrypt_object
doc.build(story)
Page Transitions
Add visual effects for presentations.
from reportlab.pdfgen import canvas
c = canvas.Canvas("presentation.pdf")
# Set transition for current page
c.setPageTransition(
effectname="Wipe", # Transition effect
duration=1, # Duration in seconds
direction=0 # Direction (effect-specific)
)
# Available effects:
# "Split", "Blinds", "Box", "Wipe", "Dissolve",
# "Glitter", "R" (Replace), "Fly", "Push", "Cover",
# "Uncover", "Fade"
# Direction values (effect-dependent):
# 0, 90, 180, 270 for most directional effects
# Example: Slide with fade transition
c.setFont("Helvetica-Bold", 24)
c.drawString(100, 400, "Slide 1")
c.setPageTransition("Fade", 0.5)
c.showPage()
c.drawString(100, 400, "Slide 2")
c.setPageTransition("Wipe", 1, 90)
c.showPage()
c.save()
PDF/A Compliance
Create archival-quality PDFs.
from reportlab.pdfgen import canvas
c = canvas.Canvas("pdfa.pdf")
# Enable PDF/A-1b compliance
c.setPageCompression(0) # PDF/A requires uncompressed
# Note: Full PDF/A requires additional XMP metadata
# This is simplified - full compliance needs more setup
# ... draw content ...
c.save()
Compression
Control file size vs generation speed.
# Enable page compression
c = canvas.Canvas("output.pdf", pageCompression=1)
# Compression reduces file size but slows generation
# 0 = no compression (faster, larger files)
# 1 = compression (slower, smaller files)
Forms and XObjects
Reusable graphics elements.
from reportlab.pdfgen import canvas
c = canvas.Canvas("output.pdf")
# Begin form (reusable object)
c.beginForm("logo")
c.setFillColorRGB(0, 0, 1)
c.rect(0, 0, 100, 50, fill=1)
c.setFillColorRGB(1, 1, 1)
c.drawString(10, 20, "LOGO")
c.endForm()
# Use form multiple times
c.doForm("logo") # At current position
c.translate(200, 0)
c.doForm("logo") # At translated position
c.translate(200, 0)
c.doForm("logo")
c.save()
# Benefits: Smaller file size, faster rendering
Best Practices
- Always set metadata for professional documents
- Use bookmarks for documents > 10 pages
- Make links visually distinct (blue, underlined)
- Test forms in multiple PDF readers (behavior varies)
- Use strong encryption (128-bit) for sensitive data
- Set both user and owner passwords for full security
- Enable printing unless specifically restricted
- Test page transitions - some readers don't support all effects
- Use meaningful bookmark titles for navigation
- Consider PDF/A for long-term archival needs
- Validate form field names - must be unique and valid identifiers
- Add tooltips to form fields for better UX