Search code examples
pythonreportlab

ReportLab: align text with KeepInFrame inside Frame not working


I am trying to align a text horizontally and vertically inside a Frame using ReportLab.

The problem is that even defining explicitly the arguments hAlign='CENTER' and vAlign='BOTTOM' for the KeepInFrame function, this does not change the default left horizontal alignment and top vertical alignment top.

I am using the latest version of ReportLab (reportlab==3.6.9).

Here's a code example:

# Import packages
import re
from reportlab.lib.enums import TA_CENTER
from reportlab.lib.pagesizes import A4
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.units import cm
from reportlab.pdfgen.canvas import Canvas
from reportlab.platypus import Paragraph, Frame, KeepInFrame

# Create document
doc = Canvas(filename='test.pdf', pagesize=A4, bottomup=1, pdfVersion=(1,4))

# Text
text = ("""Here is a simple text that should be hAlign='CENTER' and vAlign='BOTTOM'""")
text = re.sub(r'\n', '<br/>', text)
text = Paragraph(text, ParagraphStyle(name='', fontName='Helvetica', fontSize=11, textColor='black', alignment=TA_CENTER), encoding='utf8')
text = KeepInFrame(
    maxWidth=0,
    maxHeight=0,
    content=[text],
    mode='shrink',
    hAlign='CENTER',
    vAlign='BOTTOM',
    fakeWidth=False,
)

# Create ReportLab Frame object
frame = Frame(
    x1=2.5*cm,
    y1=20*cm,
    width=9.0*cm,
    height=1.5*cm,
    showBoundary=1
)

frame.addFromList([text], doc)

# Save document
doc.save()

Output:
enter image description here

Does anyone know how to fix this issue? Thanks in advance.


Solution

  • Update: I was able to solve this problem by combining the Paragraph with the Table functions (instead of Frame).

    According to ReportLab's documentation (page 68):

    All flowables have an hAlign property: ('LEFT', 'RIGHT', 'CENTER' or 'CENTRE'). For paragraphs, which fill the full width of the frame, this has no effect. For tables, images or other objects which are less than the width of the frame, this determines their horizontal placement.

    Here's a working example of the desired output:

    # Import packages
    import re
    from reportlab.lib.enums import TA_CENTER
    from reportlab.lib.pagesizes import A4
    from reportlab.lib.styles import ParagraphStyle
    from reportlab.lib.units import cm
    from reportlab.pdfgen.canvas import Canvas
    from reportlab.platypus import Paragraph, KeepInFrame, Table, TableStyle
    
    # Create document
    document = Canvas(filename='test.pdf', pagesize=A4, bottomup=1, pdfVersion=(1,4))
    
    # Text
    text = ("""Here is a simple text that should be hAlign='CENTER' and vAlign='BOTTOM'""")
    text = re.sub(r'\n', '<br/>', text)
    text = Paragraph(text, ParagraphStyle(name='', fontName='Helvetica', fontSize=11, textColor='black', alignment=TA_CENTER), encoding='utf8')
    text = KeepInFrame(
        maxWidth=0,
        maxHeight=0,
        content=[text],
        mode='shrink',
        #hAlign='CENTER',
        #vAlign='BOTTOM',
        #fakeWidth=False
    )
    
    # Create ReportLab Table object
    table = Table(
            data=[[text]],
            colWidths=9.0*cm,
            rowHeights=1.5*cm,
            spaceBefore=0,
            spaceAfter=0,
            #hAlign='CENTER',
            #vAlign='BOTTOM',
        )
    
    # Set table style
    table.setStyle(TableStyle([
            ('LEFTPADDING', (0, 0), (-1, -1), 0),
            ('RIGHTPADDING', (0, 0), (-1, -1), 0),
            ('TOPPADDING', (0, 0), (-1, -1), 0),
            ('BOTTOMPADDING', (0, 0), (-1, -1), 0),
            ('VALIGN', (0, 0), (-1, -1), 'BOTTOM'),
            ('GRID', (0, 0), (-1, -1), 0.5, 'black'),
        ]))
    
    table.wrap(0, 0)
    table.drawOn(document, 2.5*cm, 20*cm)
    
    # Save document
    document.save()
    

    Output:
    enter image description here