Sijan Bhandari
Sijan Bhandari

Reputation: 3051

Apply alignments on Reportlab SimpleDocTemplate to append multiple barcodes in number of rows

I am using Reportlab SimpleDocTemplate to create a pdf file. I have to write (draw) multiple images row-wise so that I can adjust many images within the file.

class PrintBarCodes(View):

     def get(self, request, format=None):
        response = HttpResponse(content_type='application/pdf')
        response['Content-Disposition'] = 'attachment;\
        filename="barcodes.pdf"'

        # Close the PDF object cleanly, and we're done.
        ean = barcode.get('ean13', '123456789102', writer=ImageWriter())
        filename = ean.save('ean13')
        doc = SimpleDocTemplate(response, pagesize=A4)
        parts = []
        parts.append(Image(filename))
        doc.build(parts)
        return response

In the code, I have printed a single barcode to the file. And, the output is showing in the images as can be seen below.

But, I need to draw a number of barcodes. How to reduce the image size before drawing to the pdf file and adjust in row fashion?

enter image description here

Upvotes: 2

Views: 1441

Answers (1)

B8vrede
B8vrede

Reputation: 4532

As your question suggest that you need flexibility I think the most sensible approach is using Flowable's. The barcode normally isn't one but we can make it one pretty easily. By doing so we can let decide how much space there is in your layout for each barcode.

So step one the Barcode Flowable which looks like this:

from reportlab.graphics import renderPDF
from reportlab.graphics.barcode.eanbc import Ean13BarcodeWidget
from reportlab.graphics.shapes import Drawing
from reportlab.platypus import Flowable

class BarCode(Flowable):
    # Based on https://stackoverflow.com/questions/18569682/use-qrcodewidget-or-plotarea-with-platypus
    def __init__(self, value="1234567890", ratio=0.5):
        # init and store rendering value
        Flowable.__init__(self)
        self.value = value
        self.ratio = ratio

    def wrap(self, availWidth, availHeight):
        # Make the barcode fill the width while maintaining the ratio
        self.width = availWidth
        self.height = self.ratio * availWidth
        return self.width, self.height

    def draw(self):
        # Flowable canvas
        bar_code = Ean13BarcodeWidget(value=self.value)
        bounds = bar_code.getBounds()
        bar_width = bounds[2] - bounds[0]
        bar_height = bounds[3] - bounds[1]
        w = float(self.width)
        h = float(self.height)
        d = Drawing(w, h, transform=[w / bar_width, 0, 0, h / bar_height, 0, 0])
        d.add(bar_code)
        renderPDF.draw(d, self.canv, 0, 0)

Then to answer your question, the easiest way to now put multiple barcodes on one page would be using a Table like so:

from reportlab.platypus import SimpleDocTemplate, Table
from reportlab.lib.pagesizes import A4

doc = SimpleDocTemplate("test.pdf", pagesize=A4)

table_data = [[BarCode(value='123'), BarCode(value='456')],
              [BarCode(value='789'), BarCode(value='012')]]

barcode_table = Table(table_data)

parts = []
parts.append(barcode_table)
doc.build(parts)

Which outputs:

Example of barcode table

Upvotes: 2

Related Questions