Calculating true three-fold PDF in Python
I created a three-column PDF format using frames and reportlab in the article Multi-column PDFs. However, the document I used as an example was meant to be folded, and that was not a true three-fold layout. All of the columns were the same width and they were distributed evenly within the available printing area of the page. In order to make it truly foldable, the borders between each frame need to be distributed evenly across the entire paper width. This means that, unless there are only two columns, the outer frames need to be sized differently than the inner frames.
I divided this into four basic steps:
- Add an inner margin size.
- Set the frame width to be the first fold point, minus the inner margin size.
- Adjust the first and last frame appropriately.
- Draw guides for folding.
I modified the frame code to handle steps one through three:
[toggle code]
- #create the basic page
- pagesize =reportlab.lib.pagesizes.landscape(reportlab.lib.pagesizes.letter)
- pagewidth, pageheight = pagesize
- leftMargin = .25*inch
- rightMargin = .25*inch
- topMargin = .25*inch
- bottomMargin = .25*inch
- innerMargin = .25*inch
- document = platypus.BaseDocTemplate(destination, pagesize=pagesize, leftMargin=leftMargin, rightMargin=rightMargin, topMargin=topMargin, bottomMargin=bottomMargin)
- #create the frames
- frameCount = 3
- foldAt = pagewidth/frameCount
- frameWidth = foldAt-innerMargin
- #leave space for the header
- frameHeight = document.height-.25*inch
- frames = []
- #construct the column frames
- #Note that if the frame width is less than twice the document margin, this will fail
-
for frame in range(frameCount):
- leftMargin = foldAt*frame
- thisWidth = frameWidth
- #adjust the margins appropriately
-
if frame == 0:
- leftMargin = leftMargin + document.leftMargin
- thisWidth = thisWidth - document.leftMargin + innerMargin/2
-
else:
- leftMargin = leftMargin + innerMargin/2
-
if frame == frameCount-1:
- thisWidth = thisWidth - document.rightMargin + innerMargin/2
- column = platypus.Frame(leftMargin, document.bottomMargin, thisWidth, frameHeight)
- frames.append(column)
- document.addPageTemplates(platypus.PageTemplate(frames=frames, onPage=addHeader))
- document.build(parts)
In this version, the leftmost and rightmost column are likely to be a different size than the rest of the columns, because they are also affected by the outer margins. Also, if you’re making pages with a lot of columns, you’ll want to make sure that your columns don’t start hitting negative widths after you apply the margin adjustments.
Drawing a fold guide
We can make it easier for people to fold the sheet by adding a dashed vertical line exactly at the fold.
[toggle code]
-
def addHeader(canvas, document):
- canvas.saveState()
- …
- #draw lines where the paper should be folded
- foldguidestart = pageheight*.48
- foldguideend = pageheight*.52
- #set to 25% gray
- canvas.setStrokeColorRGB(.75, .75, .75)
- #set to a 3-point dotted line
- canvas.setDash(3, 3)
-
for fold in range(1, frameCount):
- foldpoint = foldAt*fold
- canvas.line(foldpoint, foldguidestart, foldpoint, foldguideend)
- canvas.restoreState()
There’s nothing particularly special about this. It creates a line that is about 4% the height of the page, right in the middle of the page, and it does so at each fold point.
- ReportLab Toolkit
- “The ReportLab Open Source PDF library is a proven industry-strength PDF generating solution, that you can use for meeting your requirements and deadlines in enterprise reporting systems.”
More Python
- Multiple Input Fields with multiple inheritance
- We needed to display one TextField as either a TextInput or a Textarea, depending on the value in the field. Multiple inheritance makes it easy, if a bit wonky.
- PyTown
- General rambling in code regarding Python, Mailman, and Django.
- Thinking Python: Django cache expiration time
- Django sets the expiration time when data is cached. Sometimes it makes more sense to expire data dynamically based on later changes to the database. Does this mean a change to CacheClass? Not necessarily.
- Django Twitter tag and RSS object
- I wanted to embed my twitter feed into my Django blog, and didn’t see any simple RSS readers for Python that did what I wanted.
- Excerpting partial XHTML using minidom
- You can use xml.dom.minidom to parse partial XHTML as long as you use a few tricks and don’t mind that getElementById doesn’t work.
- 18 more pages with the topic Python, and other related pages
More PDF
- Adding links to PDF in Python
- It is very easy to add links to PDF documents using reportlab or platypus in Python.
- Multiple column PDF generation in Python
- You can use ReportLab’s Platypus to generate multi-column PDFs in Snakelets, Django, or any Python app.
- Embedding Mako into Django
- You got Mako in my Django! You got Django on my Mako! Two great templates that template great together.
- Python PDF generation with Snakelets
- One of the things I need to do to move my current web site over to Django is be able to automatically generate PDF documents. Step is to learn how to generate PDF using Python.
- Combining multiple PDF files into a single file
- Automator allows you to combine multiple PDF files into a single file.
- One more page with the topic PDF, and other related pages
