简体   繁体   中英

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.

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.

As an algorithm logic I would propose:

  1. Make a ".docx" file called "invoicetemplate.docx" . You should redesign that template however you want, and also include placeholders for each field like {ExcelColum1} and {ExcelColum2}
  2. Parse the excel worksheet with the data and for each row, open the "invoicetemplate.docx" and find and replace the placeholders corresponding to the names of those 20 columns from excel. For example find in template string {InvoiceValue1} and replace with excel value from column InvoiceValue1
  3. After you finish replacing the placeholders with the excel corresponding values, save the document as pdf with a new name.

There are many python libraries and ways you can do that, it is up to you whichever you are most comfortable with. Good luck.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM