17

I am new to reportlab lib, I am learning it simultaneously working on a college project. I have created a desktop application in wxpython, which result in saving data in PDF.

I want to add 2 lines in my pdf. Where line starts with a user input called name, then some words, again at 2nd line some words, user name and then again some words...

I tried use some of Paragraph and canvas methods and classes but I wasn't able to get the desired output.

Desired output:

Alex is working on college project.

reportlab is very good lib, Alex liked it.

My code:

import os
import reportlab
from reportlab.pdfgen import canvas
from reportlab.lib.pagesizes import A4
from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.pdfmetrics import registerFontFamily
from reportlab.pdfbase.ttfonts import TTFont

# Registered font family
pdfmetrics.registerFont(TTFont('Vera', 'Vera.ttf'))
pdfmetrics.registerFont(TTFont('VeraBd', 'VeraBd.ttf'))
pdfmetrics.registerFont(TTFont('VeraIt', 'VeraIt.ttf'))
pdfmetrics.registerFont(TTFont('VeraBI', 'VeraBI.ttf'))
# Registered fontfamily
registerFontFamily('Vera',normal='Vera',bold='VeraBd',italic='VeraIt',boldItalic='VeraBI')

# Output pdf file name.
can = canvas.Canvas("Bold_Trail.pdf", pagesize=A4)

# Setfont for whole pdf.
can.setFont('Vera', 12)

# student name variable.
student_name ="Alex"

# Content.
line1 = " is working on college project."
line2 = "Reportlab is very good lib, "
line3 = " liked it.<br>"

# Joining whole content together.
content = "<strong>" + student_name + "</strong>" + line1
content2 = line2 + "<strong>"+student_name + "</strong>" + line3

# drawString location calculation.
x = 0; y = 8.5 * 72

# First string.
can.drawString(x,y, content)

y = y - 72

# Second String.
can.drawString(x,y, content2)

# Create PDF.
can.save()

Is there any other way except using XML method <strong> or <b> that do not work in the above program?

The words should remain on one line.

Jongware
  • 22,200
  • 8
  • 54
  • 100
Omkar
  • 1,493
  • 3
  • 17
  • 36

2 Answers2

21

You could use the setFont method of the canvas object, to set the font to Bold when needed, and Normal otherwise.

* UPDATE *

In order to calculate the right value for x, you can use the stringWidth method, that calculates the length of the string given its content, the font name and the font size. You will have to import it from reportlab.pdfbase.pdfmetrics:

[...]
from reportlab.pdfbase.pdfmetrics import stringWidth
[...]

# student name variable.
student_name = 'Alex'

# Content.
line1 = " is working on college project."
line2 = "Reportlab is very good lib, "
line3 = " liked it"

# drawString location calculation.
x = 0
y = 8.5 * 72

# First string.
can.setFont('Helvetica-Bold', 8)
can.drawString(x, y, student_name)
can.setFont('Helvetica', 8)
textWidth = stringWidth(student_name, 'Helvetica-Bold', 8) 
x += textWidth + 1
can.drawString(x, y, line1)

y = y - 72

# Second String.
x = 0
can.setFont('Helvetica', 8)
can.drawString(x, y, line2)
textWidth = stringWidth(line2, 'Helvetica', 8) 
x += textWidth + 1
can.setFont('Helvetica-Bold', 8)
can.drawString(x, y, student_name)
textWidth = stringWidth(student_name, 'Helvetica-Bold', 8) 
x += textWidth + 1
can.setFont('Helvetica', 8)
can.drawString(x, y, line3)

# Create PDF.
can.save()

Or you could have a look at ParagraphStyle and Paragraph (from reportlab.lib.styles import ParagraphStyle, from reportlab.platypus import Paragraph) but I am not sure if you can concatenate two different styles in the same string.

jbihan
  • 3,053
  • 2
  • 24
  • 34
  • **Thank you,** it worked ! I will also looking for suggested class (Paragraph). – Omkar Jan 01 '15 at 18:21
  • You're welcome! Yeah I'm pretty sure there is a way to achieve that using `ParagraphStyle`, it would probably be more elegant... – jbihan Jan 01 '15 at 18:29
  • One question. Why you multiplied student name with 5 ? and later with 4.5 ? I didn't understood what that value is for. – Omkar Jan 02 '15 at 04:20
  • That's what I meant with "calculation of `x` can definitely be improved": I put these values to fit with the name "Alex". Please see my updated answer for a more dynamic solution. – jbihan Jan 02 '15 at 13:29
  • 1
    Thank you again. Now I am clear with this concept :) – Omkar Jan 05 '15 at 09:19
5

I found a way to format the Paragraph text with XML tags. Firstly you need to register the font family then it should work. Below I downloaded a group of .ttf files as an example and registered them, after that, the XML tags worked properly.

from reportlab.pdfbase import pdfmetrics
from reportlab.pdfbase.ttfonts import TTFont
from reportlab.pdfbase.pdfmetrics import registerFontFamily

pdfmetrics.registerFont(TTFont('OpenSansR', 'OpenSans-Regular.ttf'))
pdfmetrics.registerFont(TTFont('OpenSansL', 'OpenSans-Light.ttf'))
pdfmetrics.registerFont(TTFont('OpenSansB', 'OpenSans-Bold.ttf'))
registerFontFamily('OpenSans', normal='OpenSansR', bold='OpenSansB', italic='OpenSansL', boldItalic='OpenSansB')