#!/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()