Invoice Generator with Python
Upgrade Your Skills, Upgrade Your Career - Learn more
Containing all the information about a buyer, seller, product, payments done for the product, and Invoice is a document that forms a contract between the dealers. We will be building a project for invoice generator using python and save it in the device given the required inputs in this project. So, let’s get started with it.
What is an Invoice Generator?
An invoice generator is a project that takes the inputs like company name, address, city, date, etc. via an interface. And then generates an invoice with the provided information and saves it in the form of a PDF.
Invoice Generator with Python
In this project, we will be using the Tkinter module to build the GUI (Graphical User Interface) where the inputs are taken, reportlab library to create a PDF and save it.
Download the Invoice Generator Python Project
You can download the Invoice generator with the Python project using the link: Invoice Generator Project
Project Prerequisites
It is expected that the developer has prior knowledge of Python and the Tkinter module. The above mentioned modules can be installed using the below commands.
pip install tk pip install reportlab
Project Structure
We will be following the below steps to build the project:
- Import the required modules
- Build a GUI to take inputs
- Write a function to choose the date and upload the signature
- Write a function to generate an invoice and save it
Import the required modules
import os import tkinter as tk from tkinter import * from reportlab.pdfgen import canvas from tkinter import filedialog from tkcalendar import Calendar
Code explanation:
In this part of the code, we import the above specified modules, tkinter, and reportlab. We also use the Calender object from tkcalender and os module to access files on device.
Build a GUI to take inputs
wn = Tk()
wn.title("Python Invoice Generator By PythonGeeks")
wn.geometry("750x800")
wn.configure(bg='azure2')
# creating wn in window
Label( wn,text="Enter your company details ",font=("calibre",30,"bold"),bg="azure2",fg="green").place(x=100,y=10)
Label( wn, text="Company Name", font=("calibre", 15), bg="azure2", fg="gray").place(x=50, y=80)
company_name=Entry( wn,font=("calibre",15))
company_name.place(x=270,y=80,width=300,height=35)
Label( wn, text="Address", font=("calibre", 15), bg="azure2", fg="gray").place(x=50, y=140)
address= Entry( wn, font=("calibre", 15))
address.place(x=270, y=140, width=300,height=35)
Label( wn, text="City", font=("calibre", 15), bg="azure2", fg="gray").place(x=50, y=200)
city = Entry( wn, font=("calibre", 15))
city.place(x=270, y=200, width=300, height=35)
Label( wn, text="GST Number", font=("calibre", 15), bg="azure2", fg="gray").place(x=50, y=260)
gstNo = Entry( wn, font=("calibre", 15))
gstNo.place(x=270, y=260, width=300, height=35)
Label( wn, text="Date", font=("calibre", 15), bg="azure2", fg="gray").place(x=50, y=320)
date = Label(wn, text = "",font=("calibre", 15))
date.place(x=270, y=320, width=300, height=35)
Button( wn, text="Select Date", font=("calibre", 14), command= selectDate).place(x=620, y=320)
Label( wn, text="Phone No", font=("calibre", 15), bg="azure2", fg="gray").place(x=50, y=380)
phNo = Entry( wn, font=("calibre", 15))
phNo.place(x=270, y=380, width=300, height=35)
Label( wn, text="Customer Name", font=("calibre", 15), bg="azure2", fg="gray").place(x=50, y=440)
c_name = Entry( wn, font=("calibre", 15))
c_name.place(x=270, y=440, width=300, height=35)
Label( wn, text="Authorized Signatory", font=("calibre", 15), bg="azure2", fg="gray").place(x=50, y=500)
auSign = Entry( wn, font=("calibre", 15))
auSign.place(x=270, y=500, width=300, height=35)
Label( wn, text="Company Image", font=("calibre", 15), bg="azure2", fg="gray").place(x=50, y=560)
# ==== Browse File
Button( wn, text="Browse Files", font=("calibre", 14), command= browseFiles).place(x=270, y=560)
# ====submit details
Button( wn, text = "Submit Details",command = generateInvoice, font = ("calibre", 14),cursor = "hand2").place(x = 50, y = 640, width = 180, height = 40)
wn.mainloop()
Code explanation:
In this code we create a GUI for taking the required inputs
- title(): It displays the title on the top of the GUI.
- config(): It sets the background color of the GUI.
- geometry(): It sets the length and width of the GUI.
- place(): This is used to locate the widgets in a particular position based on coordinates mentioned.
- Label(): This creates a label to show text on GUI.
- Button(): This creates a button with mentioned properties and the command parameter represents the function that executed on pressing the button.
- mainloop(): This makes sure the screen runs till the user manually closes the window.
Write a function to choose the date and upload the signature
def browseFiles():
global wn,file_name
file_name = filedialog.askopenfilename(title="Select your File")
Label(wn, text=os.path.basename(file_name), font=("calibre", 15)).place(x=270, y=600)
def selectDate():
global date
root = Tk()
root.geometry("400x400")
# Adding Calendar
cal = Calendar(root, selectmode = 'day',
year = 2020, month = 5,
day = 22)
cal.pack(pady = 20)
def grad_date():
date.config(text = str(cal.get_date()))
root.quit()
Button(root, text = "Get Date",
command = grad_date).pack(pady = 20)
root.mainloop()
Code explanation:
Here, browseFiles() is used to select a file for setting the logo
- askopenfilename() function opens a separate window to choose a file from device
- .path.basename() is used to get the location of the file selected
selectDate() is used to choose a date
- Here we firstcreate a window called root
- Then we create a Calendar() object
- Then give a button to return the date selected
Write a function to generate an invoice and save it
def generateInvoice():
global file_name, company_name, address, city, gstNo, date, c_name, phNo, auSign
inv_canvas = canvas.Canvas("Invoice Generated by PythonGeeks.pdf", pagesize=(200, 250), bottomup=0)
inv_canvas.line(5, 45, 195, 45)
inv_canvas.line(15, 120, 185, 120)
inv_canvas.line(35, 108, 35, 220)
inv_canvas.line(115, 108, 115, 220)
inv_canvas.line(135, 108, 135, 220)
inv_canvas.line(160, 108, 160, 220)
inv_canvas.line(15, 220, 185, 220)
inv_canvas.translate(10, 40)
inv_canvas.scale(1, -1)
inv_canvas.drawImage(file_name, 0, 0, width=50, height=30)
inv_canvas.scale(1, -1)
inv_canvas.translate(-10, -40)
inv_canvas.setFont("Times-Bold", 10)
inv_canvas.drawCentredString(125, 20, company_name.get())
inv_canvas.setFont("Times-Bold", 5)
inv_canvas.drawCentredString(125, 30, address.get())
inv_canvas.drawCentredString(125, 35, city.get() + ", India")
inv_canvas.setFont("Times-Bold", 6)
inv_canvas.drawCentredString(125, 42, "GST No:"+gstNo.get())
inv_canvas.setFont("Times-Bold", 8)
inv_canvas.drawCentredString(100, 55, "INVOICE")
inv_canvas.setFont("Times-Bold", 5)
inv_canvas.drawRightString(70, 70, "Invoice No. :")
inv_canvas.drawRightString(100, 70, "XXXXXXX")
inv_canvas.drawRightString(70, 80, "Customer Name :")
inv_canvas.drawRightString(100, 80, c_name.get() )
inv_canvas.drawRightString(70, 90, "Date :")
inv_canvas.drawRightString(100, 90, date.cget("text"))
inv_canvas.drawRightString(70, 100, "Phone No. :")
inv_canvas.drawRightString(100, 100, phNo.get())
inv_canvas.roundRect(15, 108, 170, 130, 10, fill=0)
inv_canvas.drawCentredString(25, 118, "S.No.")
inv_canvas.drawCentredString(75, 118, "Orders")
inv_canvas.drawCentredString(125, 118, "Price")
inv_canvas.drawCentredString(148, 118, "Qty.")
inv_canvas.drawCentredString(173, 118, "Total")
inv_canvas.drawRightString(180, 228, auSign.get())
inv_canvas.drawRightString(180, 235, "Signature")
inv_canvas.showPage()
inv_canvas.save()
Code explanation:
- This function creates an invoice and saves it as a PDF
- In this, we first created a Canvas and stared adding components to it
- line() draws a line starting and ending at specified coordinated
- translate() moves the position of the reference point from which coordinates are set
- drawImage() places an image on the canvas
- drawCentredString() writes specified text at specified position, center aligned
- setfont() sets the font style and size of the text
- drawRightString() writes text eight aligned
- roundRect() draws a rectangle with rounded corners
- save() saves the invoice as a PDF
Output of the Python Invoice Generator
Image of the GUI
Image of the Invoice PDF
Conclusion
Hurray! We have completed building the Invoice generator using Python. We got to use different modules including Tkinter, and reportlab. Hope you enjoyed building with us!



how to run it
import os
from tkinter import Tk, Label, Button, Entry, filedialog
from tkinter import Toplevel
from reportlab.pdfgen import canvas
from tkcalendar import Calendar
def browseFiles():
global file_name
file_name = filedialog.askopenfilename(title=”Select your File”)
Label(wn, text=os.path.basename(file_name), font=(“calibre”, 15)).place(x=270, y=600)
from reportlab.lib.pagesizes import letter # for letter size (8.5 x 11 inches)
from reportlab.lib.pagesizes import A4 # for A4 size
def generateInvoice():
global file_name, company_name, address, city, gstNo, date, c_name, phNo, auSign
# Change canvas size to A4 or letter size
inv_canvas = canvas.Canvas(“Invoice Generated by faheem.pdf”, pagesize=A4, bottomup=0)
# Adjusting margins and positioning
margin_left = 0
margin_top = 0
width, height = A4 # Get A4 paper size dimensions
inv_canvas.setFont(“Times-Bold”, 10)
inv_canvas.drawCentredString(width / 2, margin_top, company_name.get())
inv_canvas.setFont(“Times-Bold”, 6)
inv_canvas.drawCentredString(width / 2, margin_top + 15, address.get())
inv_canvas.drawCentredString(width / 2, margin_top + 20, city.get() + “, India”)
inv_canvas.drawCentredString(width / 2, margin_top + 25, “GST No: ” + gstNo.get())
inv_canvas.setFont(“Times-Bold”, 8)
inv_canvas.drawCentredString(width / 2, margin_top + 40, “INVOICE”)
# Adjusting text and element positions
inv_canvas.setFont(“Times-Bold”, 5)
inv_canvas.drawRightString(width – margin_left, margin_top + 60, “Invoice No. :”)
inv_canvas.drawRightString(width – margin_left, margin_top + 70, “XXXXXXX”)
inv_canvas.drawRightString(width – margin_left, margin_top + 80, “Customer Name :”)
inv_canvas.drawRightString(width – margin_left, margin_top + 90, c_name.get())
inv_canvas.drawRightString(width – margin_left, margin_top + 100, “Date :”)
inv_canvas.drawRightString(width – margin_left, margin_top + 110, date.cget(“text”))
inv_canvas.drawRightString(width – margin_left, margin_top + 120, “Phone No. :”)
inv_canvas.drawRightString(width – margin_left, margin_top + 130, phNo.get())
inv_canvas.roundRect(margin_left, margin_top + 130, width – 2 * margin_left, height – margin_top – 150, 10, fill=0)
# Adjust the table layout
inv_canvas.drawCentredString(margin_left + 10, margin_top + 150, “S.No.”)
inv_canvas.drawCentredString(margin_left + 60, margin_top + 150, “Orders”)
inv_canvas.drawCentredString(margin_left + 110, margin_top + 150, “Price”)
inv_canvas.drawCentredString(margin_left + 140, margin_top + 150, “Qty.”)
inv_canvas.drawCentredString(margin_left + 170, margin_top + 150, “Total”)
inv_canvas.drawRightString(width – margin_left, margin_top + height – 80, auSign.get())
inv_canvas.drawRightString(width – margin_left, margin_top + height – 70, “Signature”)
inv_canvas.showPage()
inv_canvas.save()
def selectDate():
top = Toplevel(wn)
cal = Calendar(top, selectmode=’day’, year=2023, month=10, day=5)
cal.pack(pady=20)
def grab_date():
date.config(text=cal.get_date())
top.destroy()
Button(top, text=”Select”, command=grab_date).pack(pady=20)
# Setting up the main window
wn = Tk()
wn.title(” “)
wn.geometry(“750×800″)
wn.configure(bg=’azure2′)
Label(wn, text=”Enter your company details”, font=(“calibre”, 30, “bold”), bg=”azure2″, fg=”green”).place(x=100, y=10)
Label(wn, text=”Company Name”, font=(“calibre”, 15), bg=”azure2″, fg=”gray”).place(x=50, y=80)
company_name = Entry(wn, font=(“calibre”, 15))
company_name.place(x=270, y=80, width=300, height=35)
Label(wn, text=”Address”, font=(“calibre”, 15), bg=”azure2″, fg=”gray”).place(x=50, y=140)
address = Entry(wn, font=(“calibre”, 15))
address.place(x=270, y=140, width=300, height=35)
Label(wn, text=”City”, font=(“calibre”, 15), bg=”azure2″, fg=”gray”).place(x=50, y=200)
city = Entry(wn, font=(“calibre”, 15))
city.place(x=270, y=200, width=300, height=35)
Label(wn, text=”GST Number”, font=(“calibre”, 15), bg=”azure2″, fg=”gray”).place(x=50, y=260)
gstNo = Entry(wn, font=(“calibre”, 15))
gstNo.place(x=270, y=260, width=300, height=35)
Label(wn, text=”Date”, font=(“calibre”, 15), bg=”azure2″, fg=”gray”).place(x=50, y=320)
date = Label(wn, text=””, font=(“calibre”, 15))
date.place(x=270, y=320, width=300, height=35)
Button(wn, text=”Select Date”, font=(“calibre”, 14), command=selectDate).place(x=620, y=320)
Label(wn, text=”Phone No”, font=(“calibre”, 15), bg=”azure2″, fg=”gray”).place(x=50, y=380)
phNo = Entry(wn, font=(“calibre”, 15))
phNo.place(x=270, y=380, width=300, height=35)
Label(wn, text=”Customer Name”, font=(“calibre”, 15), bg=”azure2″, fg=”gray”).place(x=50, y=440)
c_name = Entry(wn, font=(“calibre”, 15))
c_name.place(x=270, y=440, width=300, height=35)
Label(wn, text=”Authorized Signatory”, font=(“calibre”, 15), bg=”azure2″, fg=”gray”).place(x=50, y=500)
auSign = Entry(wn, font=(“calibre”, 15))
auSign.place(x=270, y=500, width=300, height=35)
Label(wn, text=”Company Image”, font=(“calibre”, 15), bg=”azure2″, fg=”gray”).place(x=50, y=560)
# Browse button to select the company image
Button(wn, text=”Browse”, font=(“calibre”, 14), command=browseFiles).place(x=270, y=560)
# Submit button to generate invoice
Button(wn, text=”Submit Details”, command=generateInvoice, font=(“calibre”, 14), cursor=”hand2″).place(x=50, y=640, width=180, height=40)
wn.mainloop()