Initial commit
This commit is contained in:
229
skills/reportlab/scripts/quick_document.py
Normal file
229
skills/reportlab/scripts/quick_document.py
Normal file
@@ -0,0 +1,229 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Quick Document Generator - Helper for creating simple ReportLab documents
|
||||
|
||||
This script provides utility functions for quickly creating common document types
|
||||
without writing boilerplate code.
|
||||
"""
|
||||
|
||||
from reportlab.lib.pagesizes import letter, A4
|
||||
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
|
||||
from reportlab.lib.units import inch
|
||||
from reportlab.lib import colors
|
||||
from reportlab.platypus import (
|
||||
SimpleDocTemplate, Paragraph, Spacer, PageBreak,
|
||||
Table, TableStyle, Image, KeepTogether
|
||||
)
|
||||
from reportlab.lib.enums import TA_LEFT, TA_CENTER, TA_RIGHT, TA_JUSTIFY
|
||||
from datetime import datetime
|
||||
|
||||
|
||||
def create_simple_document(filename, title, author="", content_blocks=None, pagesize=letter):
|
||||
"""
|
||||
Create a simple document with title and content blocks.
|
||||
|
||||
Args:
|
||||
filename: Output PDF filename
|
||||
title: Document title
|
||||
author: Document author (optional)
|
||||
content_blocks: List of dicts with 'type' and 'content' keys
|
||||
type can be: 'heading', 'paragraph', 'bullet', 'space'
|
||||
pagesize: Page size (default: letter)
|
||||
|
||||
Example content_blocks:
|
||||
[
|
||||
{'type': 'heading', 'content': 'Introduction'},
|
||||
{'type': 'paragraph', 'content': 'This is a paragraph.'},
|
||||
{'type': 'bullet', 'content': 'Bullet point item'},
|
||||
{'type': 'space', 'height': 0.2}, # height in inches
|
||||
]
|
||||
"""
|
||||
if content_blocks is None:
|
||||
content_blocks = []
|
||||
|
||||
# Create document
|
||||
doc = SimpleDocTemplate(
|
||||
filename,
|
||||
pagesize=pagesize,
|
||||
rightMargin=72,
|
||||
leftMargin=72,
|
||||
topMargin=72,
|
||||
bottomMargin=18,
|
||||
title=title,
|
||||
author=author
|
||||
)
|
||||
|
||||
# Get styles
|
||||
styles = getSampleStyleSheet()
|
||||
story = []
|
||||
|
||||
# Add title
|
||||
story.append(Paragraph(title, styles['Title']))
|
||||
story.append(Spacer(1, 0.3*inch))
|
||||
|
||||
# Process content blocks
|
||||
for block in content_blocks:
|
||||
block_type = block.get('type', 'paragraph')
|
||||
content = block.get('content', '')
|
||||
|
||||
if block_type == 'heading':
|
||||
story.append(Paragraph(content, styles['Heading1']))
|
||||
story.append(Spacer(1, 0.1*inch))
|
||||
|
||||
elif block_type == 'heading2':
|
||||
story.append(Paragraph(content, styles['Heading2']))
|
||||
story.append(Spacer(1, 0.1*inch))
|
||||
|
||||
elif block_type == 'paragraph':
|
||||
story.append(Paragraph(content, styles['BodyText']))
|
||||
story.append(Spacer(1, 0.1*inch))
|
||||
|
||||
elif block_type == 'bullet':
|
||||
story.append(Paragraph(content, styles['Bullet']))
|
||||
|
||||
elif block_type == 'space':
|
||||
height = block.get('height', 0.2)
|
||||
story.append(Spacer(1, height*inch))
|
||||
|
||||
elif block_type == 'pagebreak':
|
||||
story.append(PageBreak())
|
||||
|
||||
# Build PDF
|
||||
doc.build(story)
|
||||
return filename
|
||||
|
||||
|
||||
def create_styled_table(data, col_widths=None, style_name='default'):
|
||||
"""
|
||||
Create a styled table with common styling presets.
|
||||
|
||||
Args:
|
||||
data: List of lists containing table data
|
||||
col_widths: List of column widths (None for auto)
|
||||
style_name: 'default', 'striped', 'minimal', 'report'
|
||||
|
||||
Returns:
|
||||
Table object ready to add to story
|
||||
"""
|
||||
table = Table(data, colWidths=col_widths)
|
||||
|
||||
if style_name == 'striped':
|
||||
style = TableStyle([
|
||||
('BACKGROUND', (0, 0), (-1, 0), colors.darkblue),
|
||||
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
|
||||
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
|
||||
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
|
||||
('FONTSIZE', (0, 0), (-1, 0), 12),
|
||||
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
|
||||
('ROWBACKGROUNDS', (0, 1), (-1, -1), [colors.white, colors.lightgrey]),
|
||||
('GRID', (0, 0), (-1, -1), 0.5, colors.grey),
|
||||
])
|
||||
|
||||
elif style_name == 'minimal':
|
||||
style = TableStyle([
|
||||
('ALIGN', (0, 0), (-1, -1), 'LEFT'),
|
||||
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
|
||||
('LINEABOVE', (0, 0), (-1, 0), 2, colors.black),
|
||||
('LINEBELOW', (0, 0), (-1, 0), 1, colors.black),
|
||||
('LINEBELOW', (0, -1), (-1, -1), 2, colors.black),
|
||||
])
|
||||
|
||||
elif style_name == 'report':
|
||||
style = TableStyle([
|
||||
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
|
||||
('TEXTCOLOR', (0, 0), (-1, 0), colors.black),
|
||||
('ALIGN', (0, 0), (-1, 0), 'CENTER'),
|
||||
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
|
||||
('FONTSIZE', (0, 0), (-1, 0), 11),
|
||||
('BACKGROUND', (0, 1), (-1, -1), colors.beige),
|
||||
('GRID', (0, 0), (-1, -1), 1, colors.grey),
|
||||
('LEFTPADDING', (0, 0), (-1, -1), 12),
|
||||
('RIGHTPADDING', (0, 0), (-1, -1), 12),
|
||||
])
|
||||
|
||||
else: # default
|
||||
style = TableStyle([
|
||||
('BACKGROUND', (0, 0), (-1, 0), colors.grey),
|
||||
('TEXTCOLOR', (0, 0), (-1, 0), colors.whitesmoke),
|
||||
('ALIGN', (0, 0), (-1, -1), 'CENTER'),
|
||||
('FONTNAME', (0, 0), (-1, 0), 'Helvetica-Bold'),
|
||||
('FONTSIZE', (0, 0), (-1, 0), 12),
|
||||
('BOTTOMPADDING', (0, 0), (-1, 0), 12),
|
||||
('BACKGROUND', (0, 1), (-1, -1), colors.white),
|
||||
('GRID', (0, 0), (-1, -1), 1, colors.black),
|
||||
])
|
||||
|
||||
table.setStyle(style)
|
||||
return table
|
||||
|
||||
|
||||
def add_header_footer(canvas, doc, header_text="", footer_text=""):
|
||||
"""
|
||||
Callback function to add headers and footers to each page.
|
||||
|
||||
Usage:
|
||||
from functools import partial
|
||||
callback = partial(add_header_footer, header_text="My Document", footer_text="Confidential")
|
||||
template = PageTemplate(id='normal', frames=[frame], onPage=callback)
|
||||
"""
|
||||
canvas.saveState()
|
||||
|
||||
# Header
|
||||
if header_text:
|
||||
canvas.setFont('Helvetica', 9)
|
||||
canvas.drawString(inch, doc.pagesize[1] - 0.5*inch, header_text)
|
||||
|
||||
# Footer
|
||||
if footer_text:
|
||||
canvas.setFont('Helvetica', 9)
|
||||
canvas.drawString(inch, 0.5*inch, footer_text)
|
||||
|
||||
# Page number
|
||||
canvas.drawRightString(doc.pagesize[0] - inch, 0.5*inch, f"Page {doc.page}")
|
||||
|
||||
canvas.restoreState()
|
||||
|
||||
|
||||
# Example usage
|
||||
if __name__ == "__main__":
|
||||
# Example 1: Simple document
|
||||
content = [
|
||||
{'type': 'heading', 'content': 'Introduction'},
|
||||
{'type': 'paragraph', 'content': 'This is a sample paragraph with some text.'},
|
||||
{'type': 'space', 'height': 0.2},
|
||||
{'type': 'heading', 'content': 'Main Content'},
|
||||
{'type': 'paragraph', 'content': 'More content here with <b>bold</b> and <i>italic</i> text.'},
|
||||
{'type': 'bullet', 'content': 'First bullet point'},
|
||||
{'type': 'bullet', 'content': 'Second bullet point'},
|
||||
]
|
||||
|
||||
create_simple_document(
|
||||
"example_document.pdf",
|
||||
"Sample Document",
|
||||
author="John Doe",
|
||||
content_blocks=content
|
||||
)
|
||||
|
||||
print("Created: example_document.pdf")
|
||||
|
||||
# Example 2: Document with styled table
|
||||
doc = SimpleDocTemplate("table_example.pdf", pagesize=letter)
|
||||
story = []
|
||||
styles = getSampleStyleSheet()
|
||||
|
||||
story.append(Paragraph("Sales Report", styles['Title']))
|
||||
story.append(Spacer(1, 0.3*inch))
|
||||
|
||||
# Create table
|
||||
data = [
|
||||
['Product', 'Q1', 'Q2', 'Q3', 'Q4'],
|
||||
['Widget A', '100', '150', '130', '180'],
|
||||
['Widget B', '80', '120', '110', '160'],
|
||||
['Widget C', '90', '110', '100', '140'],
|
||||
]
|
||||
|
||||
table = create_styled_table(data, col_widths=[2*inch, 1*inch, 1*inch, 1*inch, 1*inch], style_name='striped')
|
||||
story.append(table)
|
||||
|
||||
doc.build(story)
|
||||
print("Created: table_example.pdf")
|
||||
Reference in New Issue
Block a user