I have created one program with reportlab in Python where Excel sheet is taken as input . one pdf is created for each line of that excel sheet . Addition to this I am adding two images and some other stuff to the code . Horizontal lines , vertical lines to make it look as structured . I have added Design of invoice for better clarity. . Each line is drawn manually where coordinated of lines ,text are hardcoded. I did this as I had no idea about better approach and list of products is going to be same for at least 2 years
Now this is working fine as there is single PDF is created for each row of excel but now she wants to print this and attach to the shipment . She wants 4 invoices to be clubbed to single A4 PDF to save paper . She has only A4 printer with her .
What can I do here
To be honest I am beginner and clueless . I have two approaches in mind - 1- Write another function which creates single PDF for 4 lines ( it will be very tedious the way I have written the current code . Need to change all co ordinates of points and adjust sizes of images ) 2- Is there a way any python module can take PDFs and merge it ?
import pandas as pd
import xlsxwriter
from reportlab.pdfgen import canvas
from reportlab.lib.colors import HexColor
from reportlab.lib.pagesizes import letter
from reportlab.lib.units import inch
from reportlab.lib.utils import ImageReader
import openpyxl
import datetime
import os
from mergePDF import merge_pdfs
#df = pd.read_excel('Invoice.xlsx', usecols=['Sr.No','Cust_name','Quantity','Rate','Total'],header=0)
#print(df)
def create_pdf(name, cow, crate, cm_total, buffalo, brate, bm_total,other, pending_bill, amount,file_path,image_path, qr_code_path,month):
c = canvas.Canvas(file_path)
c.setFont('Helvetica-Bold', 20)
c.drawString(50,750,'Invoice ')
c.setFont('Helvetica', 15)
c.drawString(50,730,'Contact : XYZ ')
c.drawString(50,710,'Bill for month -'+ month)
#add date time
today = datetime.datetime.today().strftime('%d-%m-%Y')
c.drawString(450, 780, "Date: " + today)
#Logo 1 big left
#image = ImageReader(image_path)
#c.drawImage(image,50,400,width=4*inch,height=4*inch)
# Logo 2 small right side
image = ImageReader(image_path)
c.drawImage(image, 450, 700, width=1 * inch, height=1 * inch)
# Adding QR Code
qrcode = ImageReader(qr_code_path)
c.drawImage(qrcode,350,130, width=3 * inch,height=3 * inch)
#add a line seperator
c.setStrokeColor(HexColor('#000000'))
c.setLineWidth(2)
c.line(45, 700, 550, 700)
#Vertical line
c.setStrokeColor(HexColor('#000000'))
c.setLineWidth(2)
c.line(45, 700, 45, 360)
c.line(550, 700, 550, 360)
c.line(150, 670, 150, 520)
c.line(250, 670, 250, 520)
c.line(350, 670, 350, 520)
c.setFont('Helvetica', 15)
c.drawString(50,680,'Customer Name:')
c.drawString(250, 680, name)
c.setStrokeColor(HexColor('#000000'))
c.setLineWidth(2)
c.line(45, 670, 550, 670)
#First line - Product , Litre , Rate , Subtotal
c.drawString(50,630,'Product')
c.drawString(200,630,'Litre')
c.drawString(300,630, 'Rate')
c.drawString(450,630, 'Sub Total')
c.setStrokeColor(HexColor('#000000'))
c.setLineWidth(2)
c.line(45, 620, 550, 620)
#Cow milk
c.drawString(50, 580, 'Cow Milk')
c.drawString(200, 580, str(cow))
c.drawString(300, 580, str(crate))
c.drawString(450, 580, str(cm_total))
c.setStrokeColor(HexColor('#000000'))
c.setLineWidth(2)
c.line(45, 570, 550, 570)
#Buffalo milk
c.drawString(50, 530, 'Buffalo Milk')
c.drawString(200, 530, str(buffalo))
c.drawString(300, 530, str(brate))
c.drawString(450, 530, str(bm_total))
c.setStrokeColor(HexColor('#000000'))
c.setLineWidth(2)
c.line(45, 520, 550, 520)
# Other Items
c.drawString(50, 470, 'Other Items')
c.drawString(450, 470, str(other))
c.setStrokeColor(HexColor('#000000'))
c.setLineWidth(2)
c.line(45, 460, 550, 460)
# Previous pending
c.drawString(50, 420, 'Pending Bill')
c.drawString(450, 420, str(pending_bill))
#c.drawString(350,650,'Total Quantity: '+ str(qty))
#c.drawString(350,600,'Rate per litre: ' + str(rate))
# add a line seperator
c.setStrokeColor(HexColor('#000000'))
c.setLineWidth(2)
c.line(45, 410, 550, 410)
c.setFont('Helvetica-Bold', 16)
c.drawString(50, 370, 'Total amount: ' )
c.drawString(450, 370, str(amount))
c.setStrokeColor(HexColor('#000000'))
c.setLineWidth(2)
c.line(45, 360, 550, 360)
# Footer
c.setFont('Helvetica', 15)
c.drawString(50, 300, " Bank Name :")
c.drawString(50, 280, " Account name : ")
c.drawString(50, 260, " Account number : ")
c.drawString(50, 240, " IFSC code : ")
c.drawString(50, 220, " GPAY No : ")
c.save()
def generate_bills(excel_path,pdf_output_path,image_path, qr_code_path):
df = pd.read_excel(excel_path)
df = df.fillna(0) # This ensures if value is null then 0 is added to avoid printing NAN/NONE
for index ,row in df.iterrows():
name = row['Cust_name']
cow = row['Cow']
crate = row['C_rate']
cm_total = row['CM_total']
buffalo = row['Buffalo']
brate = row['B_rate']
bm_total = row['BM_total']
other = row['Other']
pending_bill = row['Previous_pending']
amount = row['Total']
month = row['Month']
pdf_file_name = f"{name}.pdf"
pdf_file_path = f"{pdf_output_path}/{pdf_file_name}"
create_pdf(name, cow, crate, cm_total, buffalo, brate,bm_total,other, pending_bill, amount, pdf_file_path, image_path, qr_code_path,month )
def main():
# Get the absolute path of the current working directory
current_dir = os.path.abspath(os.getcwd())
# Specify the name of the subdirectory for output files
output_subdir = "Output"
# Combine the current directory path with the output subdirectory path
pdf_output_path = os.path.join(current_dir, output_subdir)
pdf_print_path = os.path.join(current_dir,output_print)
# Check if the output directory exists, and create it if it does not
if not os.path.exists(pdf_output_path):
os.makedirs(pdf_output_path)
# Specify the path of the input Excel file and image file
excel_path = os.path.join(current_dir, "Invoice.xlsx")
image_path = os.path.join(current_dir, "logo.jpg")
qr_code_path = os.path.join(current_dir, "QR_code.jpg")
generate_bills(excel_path, pdf_output_path, image_path, qr_code_path)
if __name__ == '__main__':
main()