Search code examples
python-3.xreportlabplatypus

How to achieve text wrapping and word seperation inside python reportlab platypus frames?


I would like to create some pdf files from text and data. I set up some frames with platypus reportlab but when i try to fill them up the text is just written beyond the page margin in a single frame.

Using several options from the ParagraphStyle() class does not wrap the text at the end of the frame.

But since there appears to be some kind of wrapping operation with the given text i am confident that this would also work within the frame borders..

Another thing which troubles me is, that I can just write on one single frame. Using different "stories" allows me write on all of them.

Does anyone knows why i face these troubles?

This script below produces the following pdf file snippet:

resultpdf_snippet

Any help apprechiated. Regards

from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.platypus import Paragraph, Frame
from reportlab.lib.colors import Color, black, blue, red
from reportlab.lib.styles import getSampleStyleSheet, ParagraphStyle
from reportlab.lib.units import cm


c = canvas.Canvas('platypus_text_to_pdf.pdf', pagesize=(A4))

styles = getSampleStyleSheet() 
fiddle_style = ParagraphStyle('fiddle_style',
                           fontName="Helvetica-Bold",
                           backColor = '#FFFF00',
                           alignment = 0,
                           allowOrphans = 0,
                           allowWidows = 0,
                           borderColor = None,
                           borderPadding = 0,
                           borderRadius = None,
                           borderWidth = 100,
                           bulletAnchor = 'start',
                           bulletFontName = 'Helvetica',
                           bulletFontSize = 10,
                           bulletIndent = 0,
                           embeddedHyphenation = 0,
                           endDots = None,
                           firstLineIndent = 0,
                           fontSize = 10,
                           justifyBreaks = 0,
                           justifyLastLine = 0,
                           leading = 12,
                           leftIndent = 0,
                           linkUnderline = 0,
                           rightIndent = 20,
                           spaceAfter = 0,
                           spaceBefore = 0,
                           spaceShrinkage = 0.05,
                           splitLongWords = 1,
                           strikeGap = 1,
                           strikeOffset = 0.25,
                           strikeWidth =1,
                           textColor = Color(0,0,0,1),
                           textTransform = None,
                           underlineGap = 1,
                           underlineOffset = -0.125,
                           underlineWidth =1,
                           uriWasteReduce = 0,
                           wordWrap = None,
                           parent=styles['Heading2'],
                           )

dn_frame = Frame(A4[1]/3, A4[1]/3+(A4[1]/3)+(A4[1]/3-100),A4[1]*(2/3),100, showBoundary=1) #Dish name and serves
ingr_frame = Frame(A4[1]/3, (A4[1]*2/3)-(A4[1]/3-100),A4[1]*(2/3),2*(A4[1]/3-100), showBoundary=1) #ingredients
blw_pic_frame = Frame(0, (A4[1]*2/3)-(A4[1]/3-100),A4[1]*(1/3),(A4[1]/3-100), showBoundary=1)
facts_frame = Frame(0, 0,100,100+(A4[1]*1/3), showBoundary=1)
todo_frame = Frame(100, 0,A4[0]-100,100+(A4[1]*1/3), showBoundary=1)

text= '''
        „Lorem ipsum dolor sit amet, consectetur adipisici elit, …" ist ein Blindtext, der nichts bedeuten soll, sondern als Platzhalter im Layout verwendet wird, um einen Eindruck vom fertigen Dokument zu erhalten. Die Verteilung der Buchstaben und der Wortlängen des pseudo-lateinischen Textes entspricht in etwa der natürlichen lateinischen Sprache. Der Text ist absichtlich unverständlich, damit der Betrachter nicht durch den Inhalt abgelenkt wird.
    '''
dn_story = []
dn_story.append(Paragraph(text, fiddle_style))

dn_frame.addFromList(dn_story,c)
ingr_frame.addFromList(dn_story,c)
blw_pic_frame.addFromList(dn_story,c)
facts_frame.addFromList(dn_story,c)
todo_frame.addFromList(dn_story,c)

c.save()

Solution

  • You can feel for the remaining frame space with framename._aH you know the space requirement from floating objects with floatcontentname.wrap(todo_frame._aW,todo_frame._aH)[1]

    Example for my ingr_frame:

    #create the frame
    ingr_frame = Frame(A4[1]/3, 100+(A4[1]*1/3), A4[0]-A4[1]/3, A4[1]-100-(100+(A4[1]*1/3))-50, showBoundary=0)
    #create a text
    ingr_text = Paragraph('hello', styleN)
    #get text heigth requirement
    ingr_text.wrap(ingr_frame._aW,ingr_frame._aH)[1]
    #get available frame heigh space
    ingr_frame._aH