Initial commit: Business Case Automation with Excel generation
This commit is contained in:
249
create_excel.py
Executable file
249
create_excel.py
Executable file
@@ -0,0 +1,249 @@
|
||||
#!/usr/bin/env python3
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
import datetime
|
||||
import re
|
||||
from pathlib import Path
|
||||
from dateutil.relativedelta import relativedelta
|
||||
import openpyxl
|
||||
|
||||
def create_excel_from_template():
|
||||
"""
|
||||
Create a copy of the Excel template, replacing {store_name} with the value from config.json
|
||||
and save it to the output folder.
|
||||
"""
|
||||
# Define paths
|
||||
script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
config_path = os.path.join(script_dir, 'config.json')
|
||||
template_path = os.path.join(script_dir, 'template', 'Footprints AI for {store_name} - Retail Media Business Case Calculations.xlsx')
|
||||
output_dir = os.path.join(script_dir, 'output')
|
||||
|
||||
# Ensure output directory exists
|
||||
os.makedirs(output_dir, exist_ok=True)
|
||||
|
||||
# Read config.json to get store_name, starting_date, and duration
|
||||
try:
|
||||
with open(config_path, 'r') as f:
|
||||
config = json.load(f)
|
||||
user_data = config.get('user_data', {})
|
||||
store_name = user_data.get('store_name', '')
|
||||
starting_date = user_data.get('starting_date', '')
|
||||
duration = user_data.get('duration', 36)
|
||||
|
||||
# If store_name is empty, use a default value
|
||||
if not store_name:
|
||||
store_name = "Your Store"
|
||||
|
||||
# Calculate years array based on starting_date and duration
|
||||
years = calculate_years(starting_date, duration)
|
||||
print(f"Years in the period: {years}")
|
||||
except Exception as e:
|
||||
print(f"Error reading config file: {e}")
|
||||
return False
|
||||
|
||||
# Use first and last years from the array in the filename
|
||||
year_range = ""
|
||||
if years and len(years) > 0:
|
||||
if len(years) == 1:
|
||||
year_range = f"{years[0]}"
|
||||
else:
|
||||
year_range = f"{years[0]}-{years[-1]}"
|
||||
else:
|
||||
# Fallback to current year if years array is empty
|
||||
current_year = datetime.datetime.now().year
|
||||
year_range = f"{current_year}"
|
||||
|
||||
# Create output filename with store_name and year range
|
||||
output_filename = f"Footprints AI for {store_name} - Retail Media Business Case Calculations {year_range}.xlsx"
|
||||
output_path = os.path.join(output_dir, output_filename)
|
||||
|
||||
# Copy the template to the output directory with the new name
|
||||
try:
|
||||
shutil.copy2(template_path, output_path)
|
||||
print(f"Excel file created successfully: {output_path}")
|
||||
|
||||
# Now inject variables from config.json into the Variables sheet
|
||||
inject_variables(output_path, config)
|
||||
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error creating Excel file: {e}")
|
||||
return False
|
||||
|
||||
def calculate_years(starting_date, duration):
|
||||
"""
|
||||
Calculate an array of years that appear in the period from starting_date for duration months.
|
||||
|
||||
Args:
|
||||
starting_date (str): Date in format dd/mm/yyyy or dd.mm.yyyy
|
||||
duration (int): Number of months, including the starting month
|
||||
|
||||
Returns:
|
||||
list: Array of years in the period [year1, year2, ...]
|
||||
"""
|
||||
# Default result if we can't parse the date
|
||||
default_years = [datetime.datetime.now().year]
|
||||
|
||||
# If starting_date is empty, return current year
|
||||
if not starting_date:
|
||||
return default_years
|
||||
|
||||
try:
|
||||
# Try to parse the date, supporting both dd/mm/yyyy and dd.mm.yyyy formats
|
||||
if '/' in starting_date:
|
||||
day, month, year = map(int, starting_date.split('/'))
|
||||
elif '.' in starting_date:
|
||||
day, month, year = map(int, starting_date.split('.'))
|
||||
else:
|
||||
# If format is not recognized, return default
|
||||
return default_years
|
||||
|
||||
# Create datetime object for starting date
|
||||
start_date = datetime.datetime(year, month, day)
|
||||
|
||||
# Calculate end date (starting date + duration months - 1 day)
|
||||
end_date = start_date + relativedelta(months=duration-1)
|
||||
|
||||
# Create a set of years (to avoid duplicates)
|
||||
years_set = set()
|
||||
|
||||
# Add starting year
|
||||
years_set.add(start_date.year)
|
||||
|
||||
# Add ending year
|
||||
years_set.add(end_date.year)
|
||||
|
||||
# If there are years in between, add those too
|
||||
for y in range(start_date.year + 1, end_date.year):
|
||||
years_set.add(y)
|
||||
|
||||
# Convert set to sorted list
|
||||
return sorted(list(years_set))
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error calculating years: {e}")
|
||||
return default_years
|
||||
|
||||
def inject_variables(excel_path, config):
|
||||
"""
|
||||
Inject variables from config.json into the Variables sheet of the Excel file.
|
||||
|
||||
Args:
|
||||
excel_path (str): Path to the Excel file
|
||||
config (dict): Configuration data from config.json
|
||||
"""
|
||||
try:
|
||||
# Load the workbook
|
||||
workbook = openpyxl.load_workbook(excel_path)
|
||||
|
||||
# Try to find the Variables sheet
|
||||
sheet_names = workbook.sheetnames
|
||||
variables_sheet = None
|
||||
|
||||
# Print all sheet names for debugging
|
||||
print("Available sheets:", sheet_names)
|
||||
|
||||
# Look for the Variables sheet by name (case-insensitive)
|
||||
for sheet_name in sheet_names:
|
||||
if "variable" in sheet_name.lower():
|
||||
variables_sheet = workbook[sheet_name]
|
||||
print(f"Found Variables sheet: '{sheet_name}'")
|
||||
break
|
||||
|
||||
# If Variables sheet not found by name, try the last sheet
|
||||
if variables_sheet is None and sheet_names:
|
||||
last_sheet_name = sheet_names[-1]
|
||||
variables_sheet = workbook[last_sheet_name]
|
||||
print(f"Using last sheet '{last_sheet_name}' as Variables sheet")
|
||||
|
||||
# If still not found, try all sheets and look for specific cell patterns
|
||||
if variables_sheet is None:
|
||||
for sheet_name in sheet_names:
|
||||
sheet = workbook[sheet_name]
|
||||
# Check if this sheet has a cell B2 with a value
|
||||
if sheet["B2"].value is not None:
|
||||
variables_sheet = sheet
|
||||
print(f"Using sheet '{sheet_name}' as it has data in cell B2")
|
||||
break
|
||||
|
||||
if variables_sheet is None:
|
||||
print("Warning: Variables sheet not found. No variables were injected.")
|
||||
return
|
||||
|
||||
# Get user data from config
|
||||
user_data = config.get("user_data", {})
|
||||
|
||||
# Map cell references to config values based on the image
|
||||
cell_mappings = {
|
||||
"B2": user_data.get("store_name", ""),
|
||||
"B31": user_data.get("starting_date", ""),
|
||||
"B32": user_data.get("duration", 36),
|
||||
"B37": user_data.get("open_days_per_month", 0),
|
||||
|
||||
# Convenience store type
|
||||
"H37": user_data.get("convenience_store_type", {}).get("stores_number", 0),
|
||||
"C37": user_data.get("convenience_store_type", {}).get("monthly_transactions", 0),
|
||||
# Convert boolean to 1/0 for has_digital_screens
|
||||
"I37": 1 if user_data.get("convenience_store_type", {}).get("has_digital_screens", False) else 0,
|
||||
"J37": user_data.get("convenience_store_type", {}).get("screen_count", 0),
|
||||
"K37": user_data.get("convenience_store_type", {}).get("screen_percentage", 0),
|
||||
# Convert boolean to 1/0 for has_in_store_radio
|
||||
"M37": 1 if user_data.get("convenience_store_type", {}).get("has_in_store_radio", False) else 0,
|
||||
"N37": user_data.get("convenience_store_type", {}).get("radio_percentage", 0),
|
||||
|
||||
# Supermarket store type
|
||||
"H38": user_data.get("supermarket_store_type", {}).get("stores_number", 0),
|
||||
"C38": user_data.get("supermarket_store_type", {}).get("monthly_transactions", 0),
|
||||
# Convert boolean to 1/0 for has_digital_screens
|
||||
"I38": 1 if user_data.get("supermarket_store_type", {}).get("has_digital_screens", False) else 0,
|
||||
"J38": user_data.get("supermarket_store_type", {}).get("screen_count", 0),
|
||||
"K38": user_data.get("supermarket_store_type", {}).get("screen_percentage", 0),
|
||||
# Convert boolean to 1/0 for has_in_store_radio
|
||||
"M38": 1 if user_data.get("supermarket_store_type", {}).get("has_in_store_radio", False) else 0,
|
||||
"N38": user_data.get("supermarket_store_type", {}).get("radio_percentage", 0),
|
||||
|
||||
# Hypermarket store type
|
||||
"H39": user_data.get("hypermarket_store_type", {}).get("stores_number", 0),
|
||||
"C39": user_data.get("hypermarket_store_type", {}).get("monthly_transactions", 0),
|
||||
# Convert boolean to 1/0 for has_digital_screens
|
||||
"I39": 1 if user_data.get("hypermarket_store_type", {}).get("has_digital_screens", False) else 0,
|
||||
"J39": user_data.get("hypermarket_store_type", {}).get("screen_count", 0),
|
||||
"K39": user_data.get("hypermarket_store_type", {}).get("screen_percentage", 0),
|
||||
# Convert boolean to 1/0 for has_in_store_radio
|
||||
"M39": 1 if user_data.get("hypermarket_store_type", {}).get("has_in_store_radio", False) else 0,
|
||||
"N39": user_data.get("hypermarket_store_type", {}).get("radio_percentage", 0),
|
||||
|
||||
# Website, App, Loyalty
|
||||
"B43": user_data.get("website_visitors", 0),
|
||||
"B44": user_data.get("app_users", 0),
|
||||
"B45": user_data.get("loyalty_users", 0),
|
||||
|
||||
# Social Media
|
||||
"B49": user_data.get("facebook_followers", 0),
|
||||
"B50": user_data.get("instagram_followers", 0),
|
||||
"B51": user_data.get("google_views", 0)
|
||||
}
|
||||
|
||||
# Inject values into the Variables sheet
|
||||
print(f"Injecting variables into sheet: {variables_sheet.title}")
|
||||
for cell_ref, value in cell_mappings.items():
|
||||
try:
|
||||
# Check if cell exists
|
||||
if cell_ref in variables_sheet:
|
||||
variables_sheet[cell_ref] = value
|
||||
print(f"Set {cell_ref} = {value}")
|
||||
else:
|
||||
print(f"Warning: Cell {cell_ref} not found in sheet")
|
||||
except Exception as e:
|
||||
print(f"Warning: Could not set value for cell {cell_ref}: {e}")
|
||||
|
||||
# Save the workbook
|
||||
workbook.save(excel_path)
|
||||
print(f"Variables successfully injected into {excel_path}")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error injecting variables: {e}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
create_excel_from_template()
|
||||
Reference in New Issue
Block a user