Generates branded Excel spreadsheets with live formulas. Triggered when the user asks to "create a spreadsheet", "build a financial model", "generate an Excel file", "export as XLSX", "make a workbook", "Excel report", "revenue model", "budget spreadsheet", or references Excel/XLSX output for data, models, or analysis.
Generate branded Excel spreadsheets using openpyxl. Core philosophy: always use formulas, never hardcoded calculated values. Spreadsheets must remain dynamic.
Before generating output, check that {WORKING_DIR}/.reporting-resolved/brand-config.json exists. If it does not, tell the user: "The branding plugin is required but has not run. Please install the branding plugin and run /reporting-plugins:brand first." Do not produce unbranded output.
If a JSON data file was generated earlier in this session (in output/text/), read it as the canonical data source to ensure cross-format parity. If no prior JSON exists, use data from the conversation context directly. When generating both XLSX and CSV, generate the XLSX first and derive the CSV from the same data to prevent drift.
Read .reporting-resolved/brand-config.json for brand values.
pip install openpyxl pandas
output/xlsx/{slug}-{YYYY-MM-DD}-{HHmm}-{xxx}.xlsxEvery calculated value MUST use an Excel formula. Never hardcode the result of a calculation.
# WRONG — hardcoded value
ws["C2"] = 6000000 # Year 2 revenue
# RIGHT — formula
ws["C2"] = "=B2*(1+B5)" # Year 2 = Year 1 * (1 + growth rate)
This ensures the spreadsheet remains dynamic — users can change inputs and see results update.
Apply these text colors to indicate cell types:
| Cell type | Color (RGB) | Example |
|---|---|---|
| Hardcoded inputs | Blue (0, 0, 255) | Revenue assumptions, growth rates |
| Formulas | Black (0, 0, 0) | Calculated totals, derived metrics |
| Cross-sheet links | Green (0, 128, 0) | References to other worksheets |
| External links | Red (255, 0, 0) | References to other workbooks |
Background highlight:
from openpyxl.styles import Font, PatternFill
# Input cell (blue text)
ws["B2"].font = Font(color="0000FF")
# Formula cell (black text, default)
ws["C2"].font = Font(color="000000")
# Key assumption (yellow background)
ws["B5"].fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")
from openpyxl.styles import Font, PatternFill, Alignment
header_bg = brand["components"]["table_header_bg"].lstrip("#")
header_text = brand["components"]["table_header_text"].lstrip("#")
for cell in ws[1]: # First row
cell.font = Font(
name=brand["typography"]["font_family"].split(",")[0].strip(),
bold=True,
color=header_text,
)
cell.fill = PatternFill(start_color=header_bg, end_color=header_bg, fill_type="solid")
cell.alignment = Alignment(horizontal="center")
alt_row_color = brand["components"]["table_alt_row"].lstrip("#")
for row_idx in range(2, ws.max_row + 1):
if row_idx % 2 == 0:
for cell in ws[row_idx]:
cell.fill = PatternFill(start_color=alt_row_color, end_color=alt_row_color, fill_type="solid")
number_formats.* from brand config
$#,##0 or $#,##0.000.0%0 (prevents "2,026")#,##0font_family from brand config (Calibri default)colors.accent (without #)# Freeze panes
ws.freeze_panes = "A2"
# Auto-filter
ws.auto_filter.ref = ws.dimensions
# Number format
ws["B2"].number_format = '$#,##0'
ws["C2"].number_format = '0.0%'
# Tab color
ws.sheet_properties.tabColor = brand["colors"]["accent"].lstrip("#")
After building the spreadsheet, run recalc.py to verify formulas:
# Read office scripts path from resolved brand config
OFFICE_SCRIPTS=$(python3 -c "import json; print(json.load(open('.reporting-resolved/brand-config.json'))['_office_scripts_path'])")
python "$OFFICE_SCRIPTS/soffice.py" recalc output/xlsx/model.xlsx
Then check for formula errors:
import openpyxl
wb = openpyxl.load_workbook("output/xlsx/model.xlsx", data_only=True)
errors = []
for ws in wb.worksheets:
for row in ws.iter_rows():
for cell in row:
if isinstance(cell.value, str) and cell.value.startswith("#"):
errors.append({
"sheet": ws.title,
"cell": cell.coordinate,
"error": cell.value,
})
result = {"error_count": len(errors), "error_cells": errors}
If recalc.py finds errors, warn the user: "N formula errors detected in cells: ..." and continue. Produce the XLSX anyway.
If recalc.py finds errors:
{name}.validation.json sidecar with per-cell error details.recalc.py after the fix.{
"artifact": "revenue-model-2026-04-04-1430-c3a.xlsx",
"mode": "strict",
"checks": [
{ "check": "formula_recalc", "status": "fail", "detail": "2 errors: C5=#REF!, D8=#VALUE!" },
{ "check": "font_resolution", "status": "pass", "detail": "Calibri" },
{ "check": "brand_applied", "status": "pass" }
],
"overall": "fail"
}
0. Without this, 2026 displays as 2,026.