ReportLab Paragraph and text formatting
Asked Answered
C

3

11

My issue is that when using reportlab to generate a simple text document it loses all of the formatting. I've run it through a few times to try and debug it and the issue seems to be, when passing the msgStr to Paragraph it loses all of the formatting sent with it.

Does anyone know how to generate a simple pdf whilst maintaining the current text formatting

Code:

# PDF GENERATION LIBRARIES
# import the report lab PDF generation tools
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.units import inch
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
Parts = []

def sumFile(msgStr = None, COMPLETE = 0):

    pdfmetrics.registerFont(TTFont('Inconsolata', 'Inconsolata-Regular.ttf'))

    summaryName = SimpleDocTemplate(vehID+".pdf")

    style = ParagraphStyle(
        name='Normal',
        fontName='Inconsolata',
        fontSize=8,
    )

    msgStr.replace('\n','<br />')

    if msgStr == "PageBreak":
        parts.append(PageBreak())
    else:
        parts.append(msgStr)

    if COMPLETE == 1:
        genStr = "Generated using " + progName + " " + str(progVers)
        parts.append(genStr)
        print parts
        summaryName.build(Paragraph(parts, style))

if __name__ == "__main__":    
    sumFile("%9s %s\n" % ("Bobby", "Sue"))
    sumFile("{0:12}{1:7}{2:5}deg_C\tsmp {3}\n".format("20", "1000", "3.0", "535"))
    sumFile("{0} {1}\n\n".format("09/06/2016", "11:51:39"))
Chandra answered 9/6, 2016 at 10:58 Comment(0)
R
14

I hope this is what you are looking for :)

# PDF GENERATION LIBRARIES
# import the report lab PDF generation tools
from reportlab.lib.pagesizes import letter
from reportlab.lib.styles import ParagraphStyle
from reportlab.lib.units import inch
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont

parts = []
msg = ''
progName = "PDF"
progVers = "1.0"
vehID = "vehID"

def sumFile(msgStr = None, COMPLETE = 0):

    global parts, msg, progName, progVers, vehID

    pdfmetrics.registerFont(TTFont('Inconsolata', 'Inconsolata-Regular.ttf'))

    style = ParagraphStyle(
        name='Normal',
        fontName='Inconsolata',
        fontSize=8,
    )

    msgStr = msgStr.replace(' ','&nbsp;')
    msgStr = msgStr.replace('\n','<br />')
    msgStr = msgStr.replace('\t','&nbsp;&nbsp;&nbsp;&nbsp;')

    if msgStr == "PageBreak":
        if msg != '':
            parts.append(Paragraph(msg, style = style))
            msg = ''
        parts.append(PageBreak())
    else:
        msg += msgStr

    if COMPLETE == 1:
        if msg != '':
            parts.append(Paragraph(msg, style = style))
            msg = ''
        genStr = "Generated using " + progName + " " + str(progVers)
        parts.append(Paragraph(genStr, style = style))
        summaryName = SimpleDocTemplate(vehID+".pdf")
        summaryName.build(parts)

if __name__ == "__main__":    
    sumFile("%9s %s\n" % ("Bobby", "Sue"))
    sumFile("{0:12}{1:7}{2:5}deg_C\tsmp {3}\n".format("20", "1000", "3.0", "535"))
    sumFile("{0} {1}\n\n".format("09/06/2016", "11:51:39"))
    # sumFile("{0} {1}\n\n".format("09/06/2016", "11:51:39"), COMPLETE=1)

A few things to note:
1. The argument to summaryName.build() should be a list.
2. The first argument to Paragraph() is a string and not a list.
3. Simply writing msgStr.replace('\n','<br />') does not modify msgStr. Hence you need to assign it.
You can refer these Mouse vs Python, Docs to learn more about ReportLab.

Resonance answered 9/6, 2016 at 15:49 Comment(0)
K
3

On my windows system I had to find the real font file names and then use them as below. Now my intra-paragraph bold works correctly.

    pdfmetrics.registerFont(TTFont('Times', 'times.ttf',))
    pdfmetrics.registerFont(TTFont('Timesi', 'timesi.ttf',))
    pdfmetrics.registerFont(TTFont('Timesbd', 'timesbd.ttf',))
    pdfmetrics.registerFontFamily('Times',normal='Times',bold='Timesbd',
    italic='Timesi',)
Kilauea answered 23/9, 2017 at 15:11 Comment(1)
This solution drastically improved the quality of my life.Newborn
C
2

Necro-answer: What you are looking for is font mappings which tell ReportLab what fonts to use within a font family when boldface and italic are specified with html tags. Otherwise, when using TrueType fonts, ReportLab won't apply formatting.

from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.lib.fonts import addMapping

pdfmetrics.registerFont(TTFont(font, 'Times New Roman.ttf'))
pdfmetrics.registerFont(TTFont(font, 'Times New Roman Italic.ttf'))
pdfmetrics.registerFont(TTFont(font, 'Times New Roman Bold.ttf'))
pdfmetrics.registerFont(TTFont(font, 'Times New Roman Bold Italic.ttf'))

# 2nd positional param is bool flag for italic
# 3rd positional param is bool flag for boldface
addMapping('Times New Roman', 0, 0, 'Times New Roman')
addMapping('Times New Roman', 0, 1, 'Times New Roman Italic')
addMapping('Times New Roman', 1, 0, 'Times New Roman Bold')
addMapping('Times New Roman', 1, 1, 'Times New Roman Bold Italic')

Now you can use <strong> and <em> (or <b> and <i> if you prefer) and everything will be formatted as you expect.

Center answered 28/6, 2017 at 19:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.