Search code examples
pythonpdf-generationreportlab

Generating Invoices using reportlab


I am trying to create invoices from data that is available in Excel. Currently, i've loaded the data in CSV and converted the same into a pandas dataframe and tried to put into pdf using Reportlab from the following code:

from reportlab.platypus import SimpleDocTemplate, Table, TableStyle, Paragraph
from reportlab.lib import colors

doc = SimpleDocTemplate("form_letter.pdf",pagesize=A4,
                    rightMargin=72,leftMargin=72,
                    topMargin=72,bottomMargin=18)
Story=[]
logo = "company_logo.jpg"
limitedDate = "03/05/2010"

formatted_time = time.ctime()
full_name = "Infosys"
address_parts = ["411 State St.", "Marshalltown, IA 50158"]

im = Image(logo, 2*inch, 1*inch,hAlign='LEFT')
Story.append(im)

Story.append(Spacer(1, 12))

styles=getSampleStyleSheet()
styles.add(ParagraphStyle(name='Justify', alignment=TA_JUSTIFY))
styles.add(ParagraphStyle(name='RIGHT', alignment=TA_RIGHT))


ptext = '<font size=12>%s</font>' % formatted_time

Story.append(Paragraph(ptext, styles["Normal"]))
Story.append(Spacer(1, 12))

# Create return address
ptext = '<font size=12> Customer Name:  </font>'
Story.append(Paragraph(ptext, styles["Normal"]))

ptext = '<font size=12>%s</font>' % full_name
Story.append(Paragraph(ptext, styles["Normal"]))       

Story.append(Spacer(1,12))

for part in address_parts:
  ptext = '<font size=12>%s</font>' % part.strip()
  Story.append(Paragraph(ptext, styles["RIGHT"]))   

Story.append(Spacer(1, 12))
ptext = '<font size=12>Dear %s:</font>' % full_name.split()[0].strip()
Story.append(Paragraph(ptext, styles["Normal"]))
Story.append(Spacer(1, 12))

ptext = '<font size=12>We would like to welcome you to our subscriber base 
for  Magazine! \
    You will receive issues at the excellent introductory price of . Please 
    respond by\
     to start receiving your subscription and get the following: .</font>' 


Story.append(Paragraph(ptext, styles["Justify"]))
Story.append(Spacer(1, 12))

data = [[random.random() for i in range(1,4)] for j in range (1,8)]
df = pd.DataFrame (data)

lista = [df.columns[:,].values.astype(str).tolist()] + df.values.tolist()

t_style = TableStyle([('ALIGN',(1,1),(-2,-2),'RIGHT'),
                   ('TEXTCOLOR',(1,1),(-2,-2),colors.red),
                   ('VALIGN',(0,0),(0,-1),'TOP'),
                   ('TEXTCOLOR',(0,0),(0,-1),colors.blue),
                   ('ALIGN',(0,-1),(-1,-1),'CENTER'),
                   ('VALIGN',(0,-1),(-1,-1),'MIDDLE'),
                   ('TEXTCOLOR',(0,-1),(-1,-1),colors.green),
                   ('INNERGRID', (0,0), (-1,-1), 0.25, colors.black),
                   ('BOX', (0,0), (-1,-1), 0.25, colors.black),
                   ])
s = getSampleStyleSheet()
s = s["BodyText"]
s.wordWrap = 'CJK'
t=Table(lista)
t.setStyle(t_style)

Story.append(t)
Story.append(Spacer(1, 12))


 ptext = '<font size=12>Thank you very much and we look forward to serving you.</font>'
Story.append(Paragraph(ptext, styles["Justify"]))
Story.append(Spacer(1, 12))
ptext = '<font size=12>Sincerely,</font>'
Story.append(Paragraph(ptext, styles["Normal"]))
Story.append(Spacer(1, 48))
ptext = '<font size=12>Ima Sucker</font>'
Story.append(Paragraph(ptext, styles["Normal"]))
Story.append(Spacer(1, 12))
doc.build(Story)

I was successful in creating the PDF, however, i am not able to do the following:

  1. Currently Customer Name is appearing normal. I want it to be bold. How can I make it bold?

  2. Address is coming in the line after Customer Name. However, I want address to be printed on the same line but towards right. How can I make that happen?

  3. In the table I want my Top and row and bottom rows to become bold and top row should be filled with some color.

Please let me know how can I solve these 3 issues.


Solution

  • Good afternoon Pavan

    So, for populating the invoice template I personally would use the following python code

    #FUNCTION DEFINITION
    
    def saveInvoice(templateName, saveWithName, valuesDictionary):
        import win32com.client as win32
        word = win32.gencache.EnsureDispatch('Word.Application')
        word.Visible = False
        myTemplate = word.Documents.Open(templateName)
        for key in valuesDictionary:
            find = word.Selection.Find
            find.Text = key
            find.Replacement.Text = valuesDictionary[key]
            find.Execute(Replace=2,Forward=True)
        myTemplate.SaveAs(saveWithName, FileFormat=17)
        myTemplate.Close(False)
        word.Quit()
    
    #MAIN PROGRAM
    
    templateName = 'C:\\Users\\Grossman\\workspace\\Invoicetemplate\\invoiceTemplate.docx'
    saveWithName= 'C:\\Users\\Grossman\\workspace\\Invoicetemplate\\Modified1.pdf'
    
    valuesDictionary = {'{PlaceHolder1}' : 'value1', '{PlaceHolder2}' : 'value2', '{PlaceHolder3}' : 'value3'}
    
    saveInvoice(templateName, saveWithName, valuesDictionary)
    

    You must collect all the excel row values in a dictionary with 20 keys and values where the key will be the invoice placeholder and the dictionary value will be the value to be replaced in the word template.