Validates Customer Feedback Analyzer Excel exports with 7 view sheets, 36 columns, and professional formatting...
Every Excel export MUST be delivered with:
This is customer-facing output - quality is non-negotiable.
Required Sheets (in order):
Management Dashboard View (RED tab)
Churn Risk Analysis View (ORANGE tab)
Pain Point Analysis View (YELLOW tab)
Sentiment Analysis View (BLUE tab)
Quality Control View (PURPLE tab)
Duplicate Analysis View (GRAY tab)
Validation Command:
# Check sheet count and names
expected_sheets = [
"Management Dashboard View",
"Churn Risk Analysis View",
"Pain Point Analysis View",
"Sentiment Analysis View",
"Quality Control View",
"Duplicate Analysis View",
"Calculated Data"
]
wb = load_workbook('export.xlsx')
actual_sheets = wb.sheetnames
assert len(actual_sheets) >= 7, f"Expected >= 7 sheets, got {len(actual_sheets)}"
for sheet in expected_sheets:
assert sheet in actual_sheets, f"Missing sheet: {sheet}"
GROUP 1: Primary Review Columns (10 columns)
GROUP 2: Secondary Analysis Columns (7 columns) 11. Pain Point Category (Secondary) 12. Pain Point Keywords (matched Spanish keywords) 13. Sentiment Score Alignment (0-1 match score) 14. Actionability Score (0-10 specificity) 15. Word Count (comment length) 16. Has Deep Insights (boolean flag) 17. Deep Insights JSON (structured analysis)
GROUP 3: Duplicate Detection (5 columns) 18. Is Duplicate (boolean) 19. Duplicate Count (times appeared) 20. Duplicate Group ID (group identifier) 21. First Occurrence ID (original row reference) 22. Is First Occurrence (boolean flag)
GROUP 4: Quality Control (3 columns) 23. Quality Flags (VERY_SHORT, GENERIC, etc.) 24. Analysis Tier (FULL_AI/BASIC_AI/FREE) 25. Problemas Detectados (Spanish translation)
GROUP 5: AI Correction Details (4 columns) 26. Original User Score (pre-adjustment) 27. Sentiment Score (Before Discrepancy Check) 28. Discrepancy Flag (large difference indicator) 29. Discrepancy Explanation (why correction made)
GROUP 6: Technical Scores (7 columns) 30. Sentiment Score (GPT-4o-mini) (-1 to 1 scale) 31. Confidence Score (analysis confidence) 32-36. [Additional technical metrics]
Validation Command:
# Verify column count in Calculated Data
ws = wb["Calculated Data"]
column_count = ws.max_column
assert column_count == 36, f"Expected 36 columns, got {column_count}"
Required Tab Colors (openpyxl RGB format):
from openpyxl.worksheet.properties import TabColor
# View sheets (priority-based colors)
wb["Management Dashboard View"].sheet_properties.tabColor = TabColor("FF0000") # RED
wb["Churn Risk Analysis View"].sheet_properties.tabColor = TabColor("FFA500") # ORANGE
wb["Pain Point Analysis View"].sheet_properties.tabColor = TabColor("FFFF00") # YELLOW
wb["Sentiment Analysis View"].sheet_properties.tabColor = TabColor("0000FF") # BLUE
wb["Quality Control View"].sheet_properties.tabColor = TabColor("800080") # PURPLE
wb["Duplicate Analysis View"].sheet_properties.tabColor = TabColor("808080") # GRAY
# Calculated Data: No color (default white/none)
# Do NOT set tab color for Calculated Data
Color Meanings:
Validation Command:
# Check tab colors
expected_colors = {
"Management Dashboard View": "FF0000",
"Churn Risk Analysis View": "FFA500",
"Pain Point Analysis View": "FFFF00",
"Sentiment Analysis View": "0000FF",
"Quality Control View": "800080",
"Duplicate Analysis View": "808080"
}
for sheet_name, expected_color in expected_colors.items():
sheet = wb[sheet_name]
actual_color = sheet.sheet_properties.tabColor
if actual_color:
assert actual_color.rgb == expected_color, \
f"{sheet_name}: Expected {expected_color}, got {actual_color.rgb}"
Review Priority Score Conditional Formatting:
from openpyxl.formatting.rule import ColorScaleRule
# Apply to Review Priority Score column (column I in most views)
priority_col = 'I' # Adjust based on actual column
# Red (80-100) -> Yellow (60-80) -> Green (40-60)
color_scale = ColorScaleRule(
start_type='num', start_value=40, start_color='63BE7B', # Green
mid_type='num', mid_value=60, mid_color='FFEB84', # Yellow
end_type='num', end_value=80, end_color='F8696B' # Red
)
ws.conditional_formatting.add(f'{priority_col}2:{priority_col}1000', color_scale)
Churn Risk Conditional Formatting:
# Similar color coding for Churn Risk column
# High risk (red), medium (yellow), low (green)
Sentiment Discrepancy Highlighting:
# Highlight large gaps between User Score and AI Sentiment
# Gap >= 5.0 points should be visually flagged
Validation Command:
# Verify conditional formatting applied
ws = wb["Management Dashboard View"]
rules = ws.conditional_formatting._cf_rules
assert len(rules) > 0, "No conditional formatting found in Management Dashboard"
No Missing Required Columns:
# All 36 columns present in Calculated Data
# All view sheets have required subset of columns
No #REF!, #VALUE!, #NAME! Errors:
# Even though v3.9.0 uses static values, check for any errors
for sheet in wb.sheetnames:
ws = wb[sheet]
for row in ws.iter_rows():
for cell in row:
if cell.value and isinstance(cell.value, str):
assert not cell.value.startswith('#'), \
f"Error in {sheet}!{cell.coordinate}: {cell.value}"
Data Type Validation:
# User Score: numeric (0-10)
# AI Sentiment: numeric (0-10)
# Review Priority Score: numeric (0-100)
# Churn Risk: numeric (0-100)
# Is Duplicate: boolean
# Customer Comment: string
# Full test suite
cd api
PYTHONPATH=".:$PYTHONPATH" ./venv/Scripts/python -m pytest api/tests/domain/export/excel/ -v
# Specific test for column generation
PYTHONPATH=".:$PYTHONPATH" ./venv/Scripts/python -m pytest api/tests/integration/test_column_generation.py -v
# File: api/tests/integration/test_excel_export_integration.py
# Generates complete Excel file and validates all requirements
cd api/tests/integration
python test_excel_export_integration.py
Open Excel file manually and verify:
[ ] All 7 view sheets present (in correct order)
[ ] Tab colors correct (RED/ORANGE/YELLOW/BLUE/PURPLE/GRAY)
[ ] Calculated Data has 36 columns
[ ] Conditional formatting applied (see color gradients)
[ ] No #REF!, #VALUE!, #NAME! errors
[ ] No blank rows in view sheets
[ ] No missing data in key columns
[ ] Column headers match schema
[ ] Data types correct (numbers, text, booleans)
[ ] Sheet positions correct (views first, Calculated Data at end)
# Verify AI analysis columns present
cd api
python scripts/validation/validate_data_flow.py
# Should confirm:
# - Sentiment Score (GPT-4o-mini) present
# - Churn Risk calculated
# - Emotion detected
# - Pain Point Category assigned
# - Deep Insights JSON generated
Symptom: Only Calculated Data sheet present
Root Cause: View sheet generation skipped in code
Fix: Verify create_view_sheets() called in export service
File: api/app/domain/export/excel/service/export_service.py
Symptom: Calculated Data has != 36 columns
Root Cause: Column schema mismatch or missing columns
Fix: Check CALCULATED_DATA_COLUMNS constant
File: api/app/domain/export/excel/constants/column_schemas.py
Symptom: All tabs white/default color
Root Cause: TabColor not applied after sheet creation
Fix: Apply tab colors after creating sheets
File: api/app/domain/export/excel/service/export_service.py
Code:
from openpyxl.worksheet.properties import TabColor
ws.sheet_properties.tabColor = TabColor("FF0000") # RED
Symptom: No color gradients in Review Priority Score
Root Cause: Conditional formatting rules not added
Fix: Add ColorScaleRule after data populated
File: api/app/domain/export/excel/sheets/view_sheets.py
Symptom: Sentiment, Churn Risk, Emotion columns empty
Root Cause: AI analysis commented out or not running
Fix: Verify AI analysis in calculated_data_sheet.py:163-248 uncommented
File: api/app/domain/export/excel/sheets/core/calculated_data_sheet.py
Always use when:
Especially important when:
Skip for:
# Add to .git/hooks/pre-commit
if git diff --cached --name-only | grep -q "api/app/domain/export/excel/"; then
echo "Excel export modified. Running validation..."
cd api
PYTHONPATH=".:$PYTHONPATH" ./venv/Scripts/python -m pytest api/tests/domain/export/excel/ -v
if [ $? -ne 0 ]; then
echo "Excel validation failed. Fix tests before committing."
exit 1
fi
fi
# .github/workflows/test.yml
- name: Excel Export Validation
run: |
cd api
PYTHONPATH=".:$PYTHONPATH" ./venv/Scripts/python -m pytest api/tests/domain/export/excel/ -v
PYTHONPATH=".:$PYTHONPATH" ./venv/Scripts/python -m pytest api/tests/integration/test_column_generation.py -v
Excel Generation Speed:
If slower than expected:
Memory Usage:
If memory issues occur:
v3.9.0 (November 2025):
v3.8.0:
v3.7.0:
# Sheet generation
pytest api/tests/domain/export/excel/test_guide_sheet.py -v
pytest api/tests/domain/export/excel/test_calculated_data_sheet.py -v
# View sheets
pytest api/tests/domain/export/excel/test_view_sheets.py -v
# Formatters
pytest api/tests/domain/export/excel/test_formatters.py -v
# Complete export
pytest api/tests/integration/test_excel_export_integration.py -v
# Column generation (verifies AI analysis)
pytest api/tests/integration/test_column_generation.py -v
# Generate real export
cd api
python scripts/export/generate_ftth_export.py \
--input datasets/ftth/ftth_846_reviews.csv \
--output results/ftth_export_$(date +%Y%m%d).xlsx
# Open in Excel and verify visually
# Use checklist above
An Excel export is considered validated and ready when:
File Locations:
api/app/domain/export/excel/service/export_service.pyapi/app/domain/export/excel/sheets/api/app/domain/export/excel/sheets/view_sheets.pyapi/app/domain/export/excel/sheets/core/calculated_data_sheet.pyapi/tests/domain/export/excel/api/tests/integration/Key Constants:
api/app/domain/export/excel/constants/column_schemas.pyapi/app/domain/export/excel/constants/colors.pyapi/app/config/analysis_thresholds.pyCritical Checks:
Remember: This is customer-facing output. Quality is non-negotiable. Zero errors, professional formatting, complete validation.