import xlsxwriter
workbook = xlsxwriter.Workbook('image.xlsx')
worksheet = workbook.add_worksheet()
logo = '/home/vikrant/Pictures/alicante-logo.png.png'
# Original image.
worksheet.insert_image('B2', logo)
# Same size as original, despite row/col changes.
worksheet.insert_image('E8', logo)
# Make column F narrower.
worksheet.set_column('F:F', 2)
# Hide row 10 (zero indexed).
worksheet.set_row(9, None, None, {'hidden': True})
workbook.close()Module III - Day 2
Python Made Easy: Science and Math Edition
Sep-Dec 2025 batch, Vikrant Patil
Date: 20 Dec 2025
Live note are here https://vikrant.dev/python-made-easy-science-math/module3-day2.html
Please login to https://traininghub.vikrant.dev and create a notebook with name module3-day2.ipynb
© Vikrant Patil
%%file invoice-generator.py
import typer
import csv
import datetime
import os
import re
import xlsxwriter
alicante_data = {
"address" : "Address: C402,Purvi Lotus Apartments;HSR 2nd sector Extn,Near SS Palya Lake,;Hosapaly,Bangalore 560068",
"GSTIN" :"27ASBLL55591Z0",
"CIN" : "U74900KA2015PTC078397",
"vendor_number":"97330282"
}
def generate_invoice_count(folder=None):
year = datetime.datetime.now().year
pattern = r"^AAPL-[A-Z0-9\-]+-(?P<count>\d\d\d)-" + f"{year}.xlsx$"
p = re.compile(pattern)
def get_count(text):
m = p.match(text)
return int(m.groupdict()['count'])
if not folder:
folder = os.getcwd()
files = [f for f in os.listdir(folder) if p.match(f)]
if files:
last = max(files, key=get_count)
return f"{get_count(last)+1}".zfill(3)
else:
return "001"
def invoice_number(customer_id):
year = datetime.datetime.now().year
count= generate_invoice_count()
return f"AAPL-{customer_id}-{count}-{year}"
def read_po(pofile):
with open(pofile) as f:
d_po = csv.DictReader(f)
return [line for line in d_po]
def read_customer_details(customerfile):
with open(customerfile) as f:
d_po = csv.DictReader(f)
return next(d_po)
def create_invoice_excel(excelname):
def alicante_details(worksheet):
address_lines = alicante_data['address'].split(";")
for i,line in enumerate(address_lines, start=10):
worksheet.write(f"A{i}", line)
n = 10 + len(address_lines)
worksheet.write(f"A{n}", "GSTIN", bold)
worksheet.write(f"B{n}", ": " + alicante_data['GSTIN'], bold)
n = n + 1
worksheet.write(f"A{n}", "Vendor No")
worksheet.write(f"B{n}", ": " + alicante_data['vendor_number'])
workbook = xlsxwriter.Workbook(excelname)
worksheet = workbook.add_worksheet()
bold = workbook.add_format({'bold': True})
boldbig = workbook.add_format({'bold': True})
boldbig.set_font_size(18)
logo = '/home/vikrant/Pictures/alicante-logo.png'
worksheet.insert_image('A1',
logo,
{"x_scale": 0.58, "y_scale": 0.58}
)
worksheet.write("D8", "INVOICE", boldbig)
worksheet.set_column('A:A', 10)
alicante_details(worksheet)
workbook.close()
def generate_invoice(document_num:str, pofile:str, customer:str):
po_info = (read_po(pofile))
customer_info = read_customer_details(customer)
invoice = invoice_number(customer_info['customer_id'])
filename = f"{invoice}.xlsx"
print("generating invoice", filename)
create_invoice_excel(filename)
if __name__ == "__main__":
typer.run(generate_invoice)Overwriting invoice-generator.py
!python invoice-generator.py --helpUsage: invoice-generator.py [OPTIONS] DOCUMENT_NUM POFILE CUSTOMER ╭─ Arguments ──────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ * document_num TEXT [required] │ │ * pofile TEXT [required] │ │ * customer TEXT [required] │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ╭─ Options ────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ --help Show this message and exit. │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
!python invoice-generator.py 4500050005 po1.csv bosch.csvgenerating invoice AAPL-BMG-6-016-2025.xlsx
import datetimedatetime.datetime.now().year2025
import re # regular expressionyear = datetime.datetime.now().year
pattern = r"^AAPL-[A-Z0-9\-]+-\d\d\d-" + f"{year}.xlsx$"pattern'^AAPL-[A-Z0-9\\-]+-\\d\\d\\d-2025.xlsx$'
p = re.compile(pattern)invoice_num = "AAPL-BMG-6-006-2025.xlsx"p.match(invoice_num)<re.Match object; span=(0, 24), match='AAPL-BMG-6-006-2025.xlsx'>
p.match("AAPL-BMG-6-006-2025dhsjkd")p.match("AAPL-BMG-6-006-2025.pdf")year = datetime.datetime.now().year
pattern = r"^AAPL-[A-Z0-9\-]+-(?P<count>\d\d\d)-" + f"{year}.xlsx$"pattern'^AAPL-[A-Z0-9\\-]+-(?P<count>\\d\\d\\d)-2025.xlsx$'
p = re.compile(pattern)
m = p.match(invoice_num)m<re.Match object; span=(0, 24), match='AAPL-BMG-6-006-2025.xlsx'>
m.groupdict()['count']'006'
m.count--------------------------------------------------------------------------- AttributeError Traceback (most recent call last) Cell In[47], line 1 ----> 1 m.count AttributeError: 're.Match' object has no attribute 'count'
def get_count(text):
year = datetime.datetime.now().year
pattern = r"^AAPL-[A-Z0-9\-]+-(?P<count>\d\d\d)-" + f"{year}.xlsx$"
p = re.compile(pattern)
m = p.match(text)
return int(m.groupdict()['count'])get_count(invoice_num)6
"5".zfill(3)'005'
import typer
import csv
import datetime
import os
import re
def generate_invoice_count(folder=None):
year = datetime.datetime.now().year
pattern = r"^AAPL-[A-Z0-9\-]+-(?P<count>\d\d\d)-" + f"{year}.xlsx$"
p = re.compile(pattern)
def get_count(text):
m = p.match(text)
return int(m.groupdict()['count'])
if not folder:
folder = os.getcwd()
files = [f for f in os.listdir(folder) if p.match(f)]
if files:
last = max(files, key=get_count)
return f"{get_count(last)+1}".zfill(3)
else:
return "001"
generate_invoice_count()'001'
!touch "AAPL-BMG-6-006-2025.xlsx"generate_invoice_count()'007'
def invoice_number(customer_id):
year = datetime.datetime.now().year
count= generate_invoice_count()
return f"AAPL-{customer_id}-{count}-{year}"invoice_number("BMG-6")'AAPL-BMG-6-007-2025'
%%file bosch.csv
customer_id,GSTIN,address
BMG-6,29AAACM9840P1ZP,"Bosch Limited;Naganathapura plant;PB No 6887,Electronic City PO;Bangalore-560100, Karnataka" Overwriting bosch.csv