The resulting Python code shown below loads customer data from a local Excel file, also used as a record of invoicing, asks user for invoice number before creating a PDF invoice and saving to the specified local folder.
import pandas as pd
from fpdf import FPDF
import datetime
# datetime object containing current date and time
now = datetime.datetime.now()
dt_now = now.strftime("%d/%m/%Y")
dt_due_long = now + datetime.timedelta(days=14)
dt_due = dt_due_long.strftime("%d/%m/%Y")
print(dt_due)
def import_customer_data(file_path, invoice_number):
"""Imports customer data from an Excel file filtered by invoice number."""
try:
data = pd.read_excel(file_path)
# Debug: Print data and types
print("Loaded data:")
print(data.head())
print("Invoice Number column type:", data['Invoice Number'].dtype)
# Ensure invoice number comparison works correctly
if data['Invoice Number'].dtype != type(invoice_number):
invoice_number = str(invoice_number) if data['Invoice Number'].dtype == object else int(invoice_number)
filtered_data = data[data['Invoice Number'] == invoice_number]
if filtered_data.empty:
print(f"No data found for Invoice Number: {invoice_number}")
return None
return filtered_data
except Exception as e:
print(f"Error importing data: {e}")
return None
def generate_invoice(customer_data, output_path):
"""Generates a PDF invoice for the provided customer data."""
try:
pdf = FPDF()
pdf.add_page()
pdf.set_font("Arial", size=12)
# Add Logo
pdf.image(r"D:\Users\conno\OneDrive\Desktop\Coast Tutoring\Website\Coast_Tutoring_Logo.png", x=10, y=8, w=30)
# Add header
pdf.ln(5)
pdf.set_font("Arial", style='B', size=14)
pdf.cell(0, 10, txt="Coast Tutoring Invoice", ln=True, align="C")
pdf.ln(25)
# Add invoice number and date
invoice_number = customer_data['Invoice Number'].iloc[0]
pdf.set_font("Arial", style= 'B', size=11)
pdf.cell(0, 5, txt=f"Invoice Number: {invoice_number}", ln=True, align="L")
pdf.set_font("Arial", size=11)
pdf.cell(0, 10, txt=f"Issue Date: {dt_now}", ln=False, align="L")
pdf.cell(0, 10, txt=f"Due Date: {dt_due}", ln=True, align="R")
# Add customer details
customer_name = customer_data['Customer Name'].iloc[0]
#customer_address = customer_data['Customer Address'].iloc[0]
pdf.cell(0, 5, txt=f"Name: {customer_name}", ln=True, align="L")
#pdf.cell(0, 5, txt=f"Address: {customer_address}", ln=True, align="L")
# Add line break
pdf.ln(10)
# Add table header
pdf.set_font("Arial", style='B', size=11)
pdf.cell(100, 10, txt="Description", border=1, align='C')
pdf.cell(30, 10, txt="Quantity", border=1, align='C')
pdf.cell(30, 10, txt="Unit Cost", border=1, align='C')
pdf.cell(30, 10, txt="Subtotal", border=1, align='C')
pdf.ln(10)
# Add table rows for all items in the invoice
pdf.set_font("Arial", size=11)
total = 0
for _, row in customer_data.iterrows():
description = row['Description']
quantity = row['Quantity']
unit_cost = row['Unit Cost']
subtotal = row['Total']
total += subtotal
pdf.cell(100, 10, txt=f"{description}", border=1, align='L')
pdf.cell(30, 10, txt=f"{quantity}", border=1, align='C')
pdf.cell(30, 10, txt=f"${unit_cost:.2f}", border=1, align='C')
pdf.cell(30, 10, txt=f"${subtotal:.2f}", border=1, align='R')
pdf.ln(10)
# Add total
pdf.set_font("Arial", style='B', size=11)
pdf.cell(160, 10, txt="Total", border=1, align='R')
pdf.cell(30, 10, txt=f"${total:.2f}", border=1, align='R')
pdf.ln(10)
# Payment instructions
pdf.ln(10)
pdf.set_font("Arial", style='B', size=11)
pdf.cell(0, 10, txt=f"Due Date: {dt_due}", ln=True, align="L")
pdf.ln(5)
pdf.set_font("Arial", style='B', size=12)
pdf.cell(0, 10, txt="Payment Instructions", ln=True, align="L")
pdf.cell(0, 10, txt="Bank deposit via EFT", ln=True, align="L")
pdf.set_font("Arial", size=11)
pdf.cell(0, 6, txt="Bank: NAB", ln=True, align="L")
pdf.cell(0, 6, txt="Name: COAST TUTORING", ln=True, align="L")
pdf.cell(0, 6, txt="BSB: 082356", ln=True, align="L")
pdf.cell(0, 6, txt="AC#: 355918718", ln=True, align="L")
pdf.cell(0, 6, txt=f"Ref#: {invoice_number} ", ln=True, align="L")
# Customer Help
pdf.ln(20)
pdf.set_font("Arial", style='B', size=12)
pdf.cell(0, 10, txt="Need Help?", ln=True, align="L")
pdf.set_font("Arial", size=11)
pdf.cell(0, 6, txt="If you have any questions about this invoice, please contact: connor@coasttutoring.net or 0481 679 212", ln=True, align="L")
# Add footer
pdf.set_y(-40)
pdf.set_font("Arial", style='I', size=8)
pdf.cell(0, 10, txt=f"Thank you for your business {customer_name}!", align='C')
pdf.ln(5)
pdf.cell(0, 10, txt=f"Issue Date: {dt_now}", ln=False, align="L")
pdf.cell(-195, 10, txt="Coast Tutoring", align='C')
pdf.cell(0, 10, txt="ABN: 123456789", align='R')
pdf.ln(-5)
# Save the invoice as a PDF
customer_file = f"{output_path}/Coast_Tutoring_Invoice_{invoice_number}_{customer_name.replace(' ', '_')}.pdf"
pdf.output(customer_file)
print(f"Invoice generated for {customer_name} at {customer_file}")
except Exception as e:
print(f"Error generating invoice: {e}")
if __name__ == "__main__":
# Specify the Excel file path and output directory
#excel_file_path = r"C:\Users\conno\OneDrive\Desktop\Coast Tutoring\Clients\Invoices\InvoiceData\InvoiceDataFile.xlsx"
excel_file_path = r"D:\Users\conno\OneDrive\Desktop\Coast Tutoring\Clients\Invoices\InvoiceData\InvoiceDataFile.xlsx"
#output_directory = r"C:\Users\conno\OneDrive\Desktop\Coast Tutoring\Clients\Invoices\InvoiceData"
output_directory = r"D:\Users\conno\OneDrive\Desktop\Coast Tutoring\Clients\Invoices\2025"
# Prompt user for invoice number
invoice_number = input("Enter the Invoice Number: ")
# Import data
customer_data = import_customer_data(excel_file_path, invoice_number)
if customer_data is not None:
# Generate invoices
generate_invoice(customer_data, output_directory)
Below is the PDF export for an example of a single line invoice and a multi-line invoice.