Files
bussines_case_automation/create_excel_xlsxwriter.py
andrei 0e2e1bddba Add xlsxwriter-based Excel generation scripts with openpyxl implementation
- Created create_excel_xlsxwriter.py and update_excel_xlsxwriter.py
- Uses openpyxl exclusively to preserve Excel formatting and formulas
- Updated server.js to use new xlsxwriter scripts for form submissions
- Maintains all original functionality while ensuring proper Excel file handling

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-22 13:53:06 +00:00

152 lines
5.4 KiB
Python

#!/usr/bin/env python3
import json
import os
import shutil
import datetime
import re
from pathlib import Path
from dateutil.relativedelta import relativedelta
from update_excel_xlsxwriter import update_excel_variables
def create_excel_from_template():
"""
Create a copy of the Excel template and save it to the output folder,
then inject variables from config.json into the Variables sheet.
This version uses openpyxl exclusively for modifying existing Excel files
to preserve all formatting, formulas, and Excel features.
"""
# Define paths
script_dir = os.path.dirname(os.path.abspath(__file__))
config_path = os.path.join(script_dir, 'config.json')
# Look for any Excel template in the template directory
template_dir = os.path.join(script_dir, 'template')
template_files = [f for f in os.listdir(template_dir) if f.endswith('.xlsx')]
if not template_files:
print("Error: No Excel template found in the template directory")
return False
template_path = os.path.join(template_dir, template_files[0])
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}")
# Update the Excel file with variables from config.json
print("Updating Excel file with variables from config.json...")
update_result = update_excel_variables(output_path)
if update_result:
print("Excel file updated successfully with variables from config.json")
else:
print("Warning: Failed to update Excel file with variables from config.json")
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('.'))
elif '-' in starting_date:
# Handle ISO format (yyyy-mm-dd)
date_parts = starting_date.split('-')
if len(date_parts) == 3:
year, month, day = map(int, date_parts)
else:
# Default to current date if format is not recognized
return default_years
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
if __name__ == "__main__":
create_excel_from_template()