Search code examples
pythonreportlab

How do I get multiple items on an address lines to print in Reportlab/tkinter/Python script?


How do I get multiple lines to print on one label in reportlab/tkinter/python? For example, the below prints "Hello" and "World" on two different labels(screenshot attached). I would like to be able to print "Hello" and "World" on the same label, along with additional items below them that would look something like this:

Hello World

Tomorrow

Wednesday

I have tried adding in the same line(sheet.add_label("Hello", "World") but get attached error. Any and all help, thoughts, comments appreciated. Sample working script below:

import labels
from reportlab.graphics import shapes

specs = labels.Specification(210, 297, 2, 8, 90, 25, corner_radius=2)

def draw_label(label, width, height, obj):
    label.add(shapes.String(2, 2, str(obj), fontName="Helvetica", fontSize=40))


sheet = labels.Sheet(specs, draw_label, border=True)

sheet.add_label("Hello")
sheet.add_label("World")


sheet.save('basic.pdf')
print("{0:d} label(s) output on {1:d} page(s).".format(sheet.label_count, sheet.page_count))

New Line example

Error Message

Original Script Output


Solution

  • It seems this problem exists as issue since 2017.

    Long strings don't wrap to new line · Issue #15 · bcbnz/pylabels

    But you can modify draw_label to get list of lines and use two label.add() with different position in String()

    def draw_label(label, width, height, lines):
        #print('lines:', lines)
        label.add(shapes.String(2, 20,  lines[0], fontName="Helvetica", fontSize=20))
        label.add(shapes.String(2, 2, lines[1], fontName="Helvetica", fontSize=20))
    
    sheet = labels.Sheet(specs, draw_label, border=True)
    
    # [ text, text ]
    sheet.add_label(["Hello","World"])
    

    enter image description here

    You could make it even more complex using list with other values (like x, y, fontName, fontSize, etc.)

    def draw_label(label, width, height, lines):
        for x, y, text in lines:
            label.add(shapes.String(x, y, text, fontName="Helvetica", fontSize=20))
    
    sheet = labels.Sheet(specs, draw_label, border=True)
    
    # [ (x, y, text), (x, y, text), ... ]
    sheet.add_label([ (2, 40, "Hello"), (2, 20, "World"), (2, 2, "Python") ])
    

    enter image description here


    Full working code

    import labels
    from reportlab.graphics import shapes
    
    specs = labels.Specification(210, 297, 2, 8, 90, 25, corner_radius=2)
    
    def draw_label(label, width, height, lines):
        for x, y, text in lines:
            label.add(shapes.String(x, y, text, fontName="Helvetica", fontSize=20))
    
    sheet = labels.Sheet(specs, draw_label, border=True)
    
    # [ (x, y, text), (x, y, text), ... ]
    sheet.add_label([ (2, 40, "Hello"), (2, 20, "World"), (2, 2, "Python") ])
    sheet.add_label([ (2, 40, "Other"), (2, 20, "Label") ])
    
    sheet.save('basic.pdf')
    
    print("{0:d} label(s) output on {1:d} page(s).".format(sheet.label_count, sheet.page_count))
    

    enter image description here


    EDIT:

    You could create more complex code to add images

    sheet.add_label([ 
        ('text', 2, 40, "Hello"), 
        ('text', 2, 20, "World"), 
        ('image', 2, 2, 50, 50, "/home/user/images/logo.png") 
    ])
    

    And it would need to use if/else to check 'text'/'image' and add different shape.

    Something like this

    import labels
    from reportlab.graphics import shapes
    
    specs = labels.Specification(210, 297, 2, 8, 90, 25, corner_radius=2)
    
    def draw_label(label, width, height, items):
        for item in items:
            if item[0] == 'text':
                print('adding string', item)
                _, x, y, text = item
                label.add(shapes.String(x, y, text, fontName="Helvetica", fontSize=20))
            elif item[0] == 'image':
                print('adding image', item)
                _, x, y, width, heigh, path = item
                label.add(shapes.Image(x, y, width, heigh, path))
    
    sheet = labels.Sheet(specs, draw_label, border=True)
    
    # [ ('text', x, y, text), ('image', x, y, width, height, path), ... ]
    sheet.add_label([ ('text', 2, 40, "Hello"), ('text', 2, 20, "World"), ('image', 100, 0, 90, 90 , "/home/furas/images/grass.jpg") ])
    sheet.add_label([ ('text', 2, 40, "Other"), ('text', 2, 20, "Label") ])
    
    sheet.save('basic.pdf')
    
    print("{0:d} label(s) output on {1:d} page(s).".format(sheet.label_count, sheet.page_count))
    

    enter image description here