Using a loop to merge CSV data onto a PDF template in Python

Viewed 16

I am trying a small project in Python where I take a CSV with rows of customer data, then print them onto a PDF template, row by row. The problem I am hitting is that any methods to edit the PDF object mutate the original, and so each time the loop goes through, the template has all the previous data on it already.

My algorithm is as follows (the ideas and skeleton for this came from David's answer here):

from PyPDF2, reportlab, etc, etc
    
   with open("my_csv_data","r") as data_file_handle:
        data_to_write = csv.reader(data_file_handle)
       
        template_pdf = PdfFileReader(open("my_template_pdf", "rb"))
        
        for row in data_to_write:
            #put all the data into a "pdf" stream
            packet = io.BytesIO()
            can = canvas.Canvas(packet, pagesize=letter)
            can.drawString(100, 100, data_from_row)
            can.save()
            packet.seek(0)
    
            #turn it into a bonafide "pdf" object
            data_pdf = PdfFileReader(packet)
    
            #get the template page and data page and then merge them into one page
            new_template = template_pdf.getPage(0)
            new_template.mergePage(data_pdf.getPage(0))
            pdf_writer = PdfFileWriter()
            pdf_writer.addPage(new_template)
    
            #at this stage it is just bookkeeping to write that stream to a file via the .write method

As I mentioned above, the issue I get here is that the line:

new_template.mergePage(blah)

is changing the original template. So after 100 runs through the loop, I have 100 customer names on top of each other.

My attempts

  1. My first attempt was to pass the original template to a temporary one each loop via temp_clean_template = new_template but this just made two labels for the same original template so it didn't change anything.

  2. My next attempt was to pass the template into a function, merge it there, then return the merged PDF. That way it would only be changed locally. However, the function

            def merge_function(local_template,local_data):
                local_page = local_template.mergePage(local_data.getPage(0))
                return local_page
    

just returned a None type object. I am still not sure I understand why that happened, but can only assume it has something to do with the file reader object going out of scope.

  1. My last attempt did actually work, but I don't think it is "correct". I simply put the line

            template_pdf = PdfFileReader(open("my_template_pdf", "rb"))
    

inside the for loop. However, I am sure there must be a better way to do this than opening and closing the file to get the exact same information for every single iteration.

Is anyone able to offer some advice or tips here?

0 Answers
Related