问题
I built a pdf using reportlab, to have more controle one the page (colors- padding- return to line...) I created a frame.
the issue is that, my text is coming from a database and it need more than one page.
I want to know how to tell that its the end of the page/frame and I should create a new one for the rest of text.
import MySQLdb
import pprint
import sys
import csv
from datetime import *
from reportlab.pdfgen import canvas
from reportlab.lib.styles import getSampleStyleSheet
from reportlab.lib.pagesizes import landscape, letter, A4
from reportlab.lib.units import cm, inch
from reportlab.platypus import Image, Paragraph, Frame, KeepInFrame
styles = getSampleStyleSheet()
styleN = styles['Normal']
styleH = styles['Heading1']
story = []
pdf_file_name = 'report_.pdf'
c = canvas.Canvas(pdf_file_name)
f = Frame(0.5*inch, inch, 7*inch, 10.5*inch, showBoundary=1)
story.append(Paragraph("<font size='12' face='times' color='blue'>>SOME TEXT!</font>",styleN))
story.append(Paragraph("<font size='10' face='times'>SOME TEXT</font>", styleN) )
story.append( Paragraph('MORE TEXT HERE', styleN ) )
f.addFromList(story,c)
del story [:]
c.save()
回答1:
According to the reportlab API, you should not be using a Frame
directly, rather you should be using a Flowable
such as Paragraph
instead and that will create and manipulate the Frames for you. For example, instead of f.addFromList(story,c)
you ought to use
for p in story:
while f.add(p, c) == 0:
f.split(p, c)
f = Frame(0.5*inch, inch, 7*inch, 10.5*inch, showBoundary=1)
This way, f.add
will return 1 on success and 0 when it can't fit p
into it, when that happens we use f.split
to extract as much as possible from p
to fill up f
than replace f
with a new Frame.
回答2:
I guess you could do it like this, though I'm not sure if it's the best way to do it.
If we start by declaring a string variable with the entire text from the database
the_text = "Here you would have your sql call, but this is just for demonstration purposes :)"
Our next move would be to create a list of all the words in
text_list = the_text.split(' ')
You might have to configure this just a bit, depending on how many words fit on one page. For this, I'm just going to say we want 3 words on each page.
words_on_page = 3
Now for the "magic". We make a for loop where x is going to itterate in steps trough the text_list And in this case it starts on the first word at 0 and jumps up 3 each loop
Then inside the loop we have a one liner that goes from x to (x + 3) And then for each 3 words we join them together with a whitespace.
And then you can put that into your frame
for x in range(0, len(text_list), words_on_page):
page_text = " ".join(text_list[x:x + words_on_page])
do_something_with_the(page_text)
And now we have lists of words fitting on to each page. Where each page has an eaqual amount of words on it. Which might not be ideal, but you can take this and make a better split.
The Code:
the_text = "Here you would have your sql call, but this is just for demonstration purposes :)"
text_list = the_text.split(' ')
words_on_page = 3
for x in range(0, len(text_list), words_on_page):
page_text = " ".join(text_list[x:x + words_on_page])
do_something_with_the(page_text)
来源:https://stackoverflow.com/questions/28778261/how-to-know-the-end-of-a-frame-to-create-a-new-one-reportlab