0

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()


omkar
  • 1
  • try PyPDF2 https://pypi.org/project/PyPDF2/ – angwrk Apr 04 '23 at 08:29
  • 1
    Not sure what exactly you want to achieve. Using [PyMuPDF](https://pypi.org/project/PyMuPDF/) allows you to combine existing PDF pages into one easily, so-called "4-up" - among a plethora of other similar features. Please elaborate on details. – Jorj McKie Apr 04 '23 at 12:21
  • @JorjMcKie I will try to clarify my requirement . I am generating 1 Invoice per customer on 1 PDF page . with Logo of business and 1 more image . Now I got the requirement as 4 Invoices needs to be compressed on single A4 page . Basically my friend wants to save paper instead of printing 4 pages for 4 invoices she wants to print single page with 4 invoices – omkar Apr 04 '23 at 13:18

0 Answers0