🎁 Get the FREE AI Skills Starter Guide β€” Subscribe β†’
BytesAgainBytesAgain
πŸ¦€ ClawHub

Spreadsheet Engineering

by @1kalin

Build reliable, well-documented spreadsheets with clear architecture, error handling, named ranges, and platform-agnostic formulas for finance, dashboards, a...

Versionv1.0.0
Downloads1,331
TERMINAL
clawhub install afrexai-spreadsheet-engineering

πŸ“– About This Skill

Spreadsheet Engineering β€” AfrexAI

> Build bulletproof spreadsheets: financial models, dashboards, data systems, and automation. Platform-agnostic methodology for Google Sheets, Excel, and LibreOffice.

Quick Health Check

Score your spreadsheet /16:

| Signal | Healthy | Sick | |---|---|---| | Named ranges for all key inputs | βœ… Uses named ranges | ❌ Raw cell references everywhere | | Inputs separated from calculations | βœ… Clear input section | ❌ Hardcoded values in formulas | | No circular references | βœ… Clean dependency chain | ❌ Iterative calculation warnings | | Documentation/comments exist | βœ… README sheet + cell notes | ❌ "What does this formula do?" | | Error handling in formulas | βœ… IFERROR/IFNA wrapping | ❌ #REF! #N/A scattered everywhere | | Consistent formatting | βœ… Style guide followed | ❌ Random fonts, colors, sizes | | Version history/backup | βœ… Named versions + changelog | ❌ "Final_v3_REAL_final.xlsx" | | Data validation on inputs | βœ… Dropdowns + range constraints | ❌ Free-text in structured fields |

Score: 0-4 πŸ”΄ rebuild | 5-8 🟑 refactor | 9-12 🟒 optimize | 13-16 πŸ”΅ production-grade


Phase 1: Architecture & Planning

Spreadsheet Strategy Brief

spreadsheet_brief:
  name: "[Descriptive Name]"
  purpose: "[What decision does this support?]"
  owner: "[Who maintains this]"
  audience: "[Who uses this β€” technical level]"
  update_frequency: "[Real-time / Daily / Weekly / Monthly / Ad-hoc]"
  data_sources:
    - source: "[Where data comes from]"
      method: "[Manual / Import / API / IMPORTRANGE / Power Query]"
      refresh: "[How often]"
  outputs:
    - "[Dashboard / Report / Export / Decision support]"
  complexity_tier: "[Simple / Standard / Complex / Enterprise]"
  platform: "[Google Sheets / Excel / Both]"
  kill_criteria:
    - "If >50 users need simultaneous editing β†’ move to database"
    - "If >100K rows β†’ move to database or BI tool"
    - "If requires audit trail β†’ move to proper system"

Complexity Tier Guide

| Tier | Rows | Sheets | Users | Formulas | Example | |---|---|---|---|---|---| | Simple | <1K | 1-3 | 1-3 | Basic | Budget tracker, checklist | | Standard | 1K-10K | 3-8 | 3-10 | Intermediate | Financial model, project tracker | | Complex | 10K-50K | 8-15 | 10-30 | Advanced | Multi-dept dashboard, CRM | | Enterprise | 50K+ | 15+ | 30+ | Expert | Data warehouse substitute (🚩 migrate) |

When NOT to Use a Spreadsheet

| Scenario | Better Tool | |---|---| | >100K rows of data | Database (PostgreSQL, SQLite) | | >10 concurrent editors | Web app or Airtable | | Complex relational data (3+ entity types) | Database + app | | Needs audit trail / compliance | Purpose-built system | | Real-time data processing | ETL pipeline + BI tool | | Version-controlled code logic | Actual code (Python, JS) |

Rule: Spreadsheets are prototyping tools that become production systems by accident. Know when to graduate.


Phase 2: Sheet Architecture

Recommended Structure

πŸ“Š Workbook
β”œβ”€β”€ πŸ“‹ README          β€” Purpose, instructions, changelog
β”œβ”€β”€ πŸ“Š Dashboard       β€” Charts, KPIs, summary (output only)
β”œβ”€β”€ βš™οΈ Config          β€” Settings, parameters, dropdowns
β”œβ”€β”€ πŸ“₯ Data_Input      β€” Raw data entry or imports
β”œβ”€β”€ πŸ”§ Calculations    β€” All formulas and transformations
β”œβ”€β”€ πŸ“ˆ Analysis        β€” Pivot tables, scenarios, what-if
β”œβ”€β”€ πŸ“€ Output          β€” Formatted reports for export/print
└── πŸ—„οΈ Reference       β€” Lookup tables, constants, mappings

7 Architecture Rules

1. One direction of flow — Data flows left→right or top→bottom. Never circular. 2. Inputs separate from calculations — NEVER hardcode numbers in formulas. Use named ranges. 3. One fact in one place — If a value is used in 3 places, define it once and reference it. 4. Color code by purpose — Blue = input, Black = formula, Green = linked from other sheet, Red = warning. 5. Freeze panes on every data sheet — Header row and label columns always visible. 6. Protect formula cells — Lock everything except input cells. Prevent accidental overwrites. 7. README sheet is mandatory — Every workbook starts with purpose, instructions, and changelog.

Naming Conventions

Sheets:    PascalCase β€” Dashboard, Raw_Data, Config
Named Ranges: SCREAMING_SNAKE β€” TAX_RATE, START_DATE, REVENUE_TARGET
Tabs:      Prefix with emoji or number for sort order β€” 01_Dashboard, 02_Config
Files:     YYYY-MM-DD_Description_vX.xlsx

Color Coding Standard

| Color | Meaning | When to Use | |---|---|---| | πŸ”΅ Light blue background | User input cell | Editable fields | | ⬛ Black text | Formula/calculated | Auto-populated cells | | 🟒 Green text | Linked from other sheet | Cross-sheet references | | πŸ”΄ Red text/background | Warning/error | Validation failures, negative values | | 🟑 Yellow background | Assumption | Key assumptions that drive the model | | ⬜ Grey background | Reference/locked | Constants, lookup tables |


Phase 3: Formula Engineering

Formula Complexity Levels

| Level | Techniques | Example | |---|---|---| | L1 Basic | SUM, AVERAGE, COUNT, IF, CONCATENATE | =SUM(B2:B100) | | L2 Intermediate | VLOOKUP/XLOOKUP, SUMIFS, INDEX/MATCH, TEXT | =XLOOKUP(A2,Ref!A:A,Ref!B:B) | | L3 Advanced | ARRAYFORMULA, QUERY, INDIRECT, nested IFs | =QUERY(Data!A:F,"SELECT A,SUM(F) GROUP BY A") | | L4 Expert | LAMBDA, MAP/REDUCE, LET, dynamic arrays, MAKEARRAY | =LET(data,A2:A100,filtered,FILTER(data,data>0),SORT(filtered)) |

Essential Formula Patterns

#### Lookup β€” Always Prefer XLOOKUP/INDEX-MATCH Over VLOOKUP

❌ VLOOKUP (fragile β€” breaks when columns inserted):
=VLOOKUP(A2, Data!A:D, 4, FALSE)

βœ… XLOOKUP (Excel 365 / Google Sheets): =XLOOKUP(A2, Data!A:A, Data!D:D, "Not Found")

βœ… INDEX/MATCH (universal β€” works everywhere): =INDEX(Data!D:D, MATCH(A2, Data!A:A, 0))

#### Multi-Criteria Lookup

=XLOOKUP(1, (Data!A:A=B2)*(Data!B:B=C2), Data!D:D, "Not Found")

Or INDEX/MATCH array (Ctrl+Shift+Enter in older Excel): =INDEX(Data!D:D, MATCH(1, (Data!A:A=B2)*(Data!B:B=C2), 0))

#### Conditional Aggregation

Single condition:
=SUMIF(Category, "Sales", Amount)

Multiple conditions: =SUMIFS(Amount, Category, "Sales", Region, "US", Date, ">="&DATE(2025,1,1))

Count with conditions: =COUNTIFS(Status, "Active", Score, ">80")

Average with conditions: =AVERAGEIFS(Score, Department, "Engineering", Status, "Active")

#### Date Calculations

Working days between dates:
=NETWORKDAYS(Start, End, Holidays)

Add working days: =WORKDAY(Start, 10, Holidays)

Month-end date: =EOMONTH(A2, 0)

Quarter from date: =ROUNDUP(MONTH(A2)/3, 0)

Fiscal year (Apr-Mar): =IF(MONTH(A2)>=4, YEAR(A2), YEAR(A2)-1)

#### Text Manipulation

Extract domain from email:
=MID(A2, FIND("@",A2)+1, LEN(A2))

Proper case with exceptions: =PROPER(SUBSTITUTE(LOWER(A2)," llc"," LLC"))

Clean messy data: =TRIM(CLEAN(SUBSTITUTE(A2, CHAR(160), " ")))

#### Dynamic Arrays (Excel 365 / Google Sheets)

FILTER:
=FILTER(Data, Data[Status]="Active", Data[Amount]>1000)

SORT: =SORT(FILTER(Data, Data[Region]="US"), 3, -1)

UNIQUE: =UNIQUE(Data[Category])

SEQUENCE: =SEQUENCE(12, 1, DATE(2025,1,1), 30) β€” 12 monthly dates

#### Google Sheets QUERY (Power Feature)

Basic aggregation:
=QUERY(Data!A:F, "SELECT A, SUM(F) WHERE B='Active' GROUP BY A ORDER BY SUM(F) DESC LABEL SUM(F) 'Total Revenue'")

Date filtering: =QUERY(Data!A:F, "SELECT A, B, F WHERE C >= date '"&TEXT(B1,"yyyy-MM-dd")&"' ORDER BY F DESC LIMIT 10")

Pivot-style: =QUERY(Data!A:F, "SELECT A, SUM(F) GROUP BY A PIVOT B")

#### LET for Readable Complex Formulas

=LET(
  revenue, SUMIFS(Sales!D:D, Sales!A:A, A2),
  costs, SUMIFS(Costs!D:D, Costs!A:A, A2),
  margin, (revenue - costs) / revenue,
  IF(revenue=0, "No Data",
    IF(margin > 0.3, "βœ… Healthy",
      IF(margin > 0.1, "⚠️ Watch", "πŸ”΄ Critical")))
)

#### LAMBDA (Custom Functions)

Named LAMBDA (define in Name Manager / named ranges):
FISCAL_QUARTER = LAMBDA(date, "FY"&IF(MONTH(date)>=4,YEAR(date),YEAR(date)-1)&" Q"&ROUNDUP(MOD(MONTH(date)+8,12)/3,0))

MAP with LAMBDA: =MAP(A2:A100, LAMBDA(x, PROPER(TRIM(x))))

10 Formula Rules

1. NEVER hardcode values β€” Use named ranges or a Config sheet 2. Wrap external lookups in IFERROR β€” =IFERROR(XLOOKUP(...), "Not Found") 3. Use LET for formulas >100 chars β€” Readable, debuggable, faster 4. Prefer XLOOKUP over VLOOKUP β€” More flexible, no column counting 5. One formula per cell β€” Don't nest 5+ functions. Break into helper columns. 6. Comment complex formulas β€” Use cell notes or a documentation column 7. Test with edge cases β€” Empty cells, zeros, dates before 1900, text in number fields 8. Avoid INDIRECT for performance β€” It's volatile (recalculates every time) 9. Use structured references in tables β€” =SUM(Table1[Amount]) not =SUM(D:D) 10. Keep formulas auditable β€” Someone else (or future you) must understand them


Phase 4: Data Validation & Quality

Input Validation Checklist

| Data Type | Validation | Implementation | |---|---|---| | Date | Date range | Data validation: between START and END | | Currency | Number β‰₯ 0 | Data validation: decimal β‰₯ 0, format $#,##0.00 | | Percentage | 0-100 or 0-1 | Data validation: decimal between 0 and 1 | | Category | Dropdown list | Data validation: list from Reference sheet | | Email | Contains @ | Custom: =ISNUMBER(FIND("@",A2)) | | Phone | Length check | Custom: =AND(LEN(A2)>=10, LEN(A2)<=15) | | Required field | Not blank | Custom: =LEN(TRIM(A2))>0 | | ID/Code | Unique + format | Custom: =AND(COUNTIF(A:A,A2)=1, LEN(A2)=8) |

Data Cleaning Pipeline

Step 1: Remove whitespace
=TRIM(CLEAN(A2))

Step 2: Standardize case =PROPER(A2) or =UPPER(A2)

Step 3: Remove duplicates Use Remove Duplicates tool or UNIQUE()

Step 4: Fix dates =DATEVALUE(TEXT(A2,"YYYY-MM-DD"))

Step 5: Validate =IF(AND(A2>0, A2<1000000, ISNUMBER(A2)), "βœ…", "❌ Check")

Conditional Formatting Rules (Priority Order)

1. πŸ”΄ Errors β€” Any cell with #REF!, #N/A, #VALUE! β†’ Red background 2. 🟑 Warnings β€” Values outside expected range β†’ Yellow background 3. 🟒 Positive β€” On-target metrics β†’ Green text 4. πŸ“Š Data bars β€” Numeric ranges β†’ Proportional bars 5. 🎯 Icons β€” Status indicators β†’ Traffic light icon sets


Phase 5: Financial Modeling

Model Architecture

πŸ“Š Financial Model
β”œβ”€β”€ πŸ“‹ Cover          β€” Model name, version, date, author
β”œβ”€β”€ βš™οΈ Assumptions    β€” ALL inputs here (blue cells), scenarios
β”œβ”€β”€ πŸ“Š Revenue        β€” Revenue build-up by product/segment
β”œβ”€β”€ πŸ“Š COGS           β€” Cost of goods/services
β”œβ”€β”€ πŸ“Š OpEx           β€” Operating expenses by category
β”œβ”€β”€ πŸ“Š P&L            β€” Income statement (auto-calculated)
β”œβ”€β”€ πŸ“Š Balance_Sheet  β€” Assets, liabilities, equity
β”œβ”€β”€ πŸ“Š Cash_Flow      β€” Operating, investing, financing
β”œβ”€β”€ πŸ“ˆ DCF            β€” Discounted cash flow valuation
β”œβ”€β”€ πŸ“ˆ Scenarios      β€” Bull/Base/Bear cases
β”œβ”€β”€ πŸ“Š KPIs           β€” Key metrics dashboard
└── πŸ“Š Charts         β€” Visualizations

Revenue Model Patterns

saas_revenue:
  mrr_start: "=PREVIOUS_MONTH_MRR"
  new_mrr: "=NEW_CUSTOMERS * ARPU"
  expansion_mrr: "=EXISTING * EXPANSION_RATE / 12"
  contraction_mrr: "=EXISTING * CONTRACTION_RATE / 12"
  churn_mrr: "=EXISTING * CHURN_RATE / 12"
  mrr_end: "=MRR_START + NEW + EXPANSION - CONTRACTION - CHURN"
  arr: "=MRR_END * 12"

unit_economics: cac: "=TOTAL_SALES_MARKETING / NEW_CUSTOMERS" ltv: "=ARPU / MONTHLY_CHURN_RATE" ltv_cac_ratio: "=LTV / CAC # Target: >3.0" cac_payback_months: "=CAC / ARPU # Target: <12"

Scenario Analysis Template

=SWITCH(SCENARIO_SELECTOR,
  "Bull", Assumptions!B2 * 1.3,
  "Base", Assumptions!B2,
  "Bear", Assumptions!B2 * 0.7,
  Assumptions!B2)

Or with CHOOSE: =CHOOSE(SCENARIO_INDEX, BEAR_VALUE, BASE_VALUE, BULL_VALUE)

Sensitivity Analysis (Data Table)

Two-variable data table:
  • Row input: Growth Rate (10%, 15%, 20%, 25%, 30%)
  • Column input: Churn Rate (2%, 3%, 5%, 7%, 10%)
  • Output cell: NPV or IRR
  • Select range β†’ Data β†’ What-If Analysis β†’ Data Table
  • Common Financial Formulas

    NPV: =NPV(DISCOUNT_RATE, CF1:CF10) + INITIAL_INVESTMENT
    IRR: =IRR(CF_RANGE, guess)
    XIRR: =XIRR(CF_VALUES, CF_DATES)  β€” irregular cash flows
    PMT: =PMT(RATE/12, NPER*12, -PV)  β€” loan payment
    Compound growth: =FV * (1 + RATE)^YEARS
    CAGR: =(END_VALUE/START_VALUE)^(1/YEARS) - 1
    Break-even units: =FIXED_COSTS / (PRICE - VARIABLE_COST)
    


    Phase 6: Dashboard Design

    Dashboard Layout

    β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚  πŸ“Š Dashboard Title              Period: [Dropdown] β”‚
    β”‚  Last Updated: [Auto]            Filter: [Dropdown] β”‚
    β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚  KPI 1   β”‚  KPI 2   β”‚  KPI 3   β”‚  KPI 4           β”‚
    β”‚  $1.2M   β”‚  45%     β”‚  128     β”‚  $47             β”‚
    β”‚  β–² 12%   β”‚  β–Ό -3%   β”‚  β–² 8%   β”‚  ● Flat          β”‚
    β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚                                                     β”‚
    β”‚  [Primary Chart β€” Revenue Trend]                   β”‚
    β”‚                                                     β”‚
    β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€
    β”‚  [Secondary Chart]  β”‚  [Table / Top Items]          β”‚
    β”‚  [Category Split]   β”‚  [Ranked List]                β”‚
    β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
    

    KPI Card Formula Pattern

    Current value:  =SUMIFS(Data!E:E, Data!A:A, ">="&PERIOD_START, Data!A:A, "<="&PERIOD_END)
    Previous value: =SUMIFS(Data!E:E, Data!A:A, ">="&PREV_START, Data!A:A, "<="&PREV_END)
    Change %:       =(CURRENT - PREVIOUS) / ABS(PREVIOUS)
    Indicator:      =IF(CHANGE>0.05, "β–²", IF(CHANGE<-0.05, "β–Ό", "●"))
    Display:        =INDICATOR & " " & TEXT(ABS(CHANGE), "0.0%")
    

    Chart Selection Guide

    | Data Pattern | Best Chart | Avoid | |---|---|---| | Trend over time | Line chart | Pie chart | | Part of whole | Stacked bar or donut | 3D pie | | Comparison | Horizontal bar | Radar chart | | Distribution | Histogram | Line chart | | Relationship | Scatter plot | Bar chart | | KPI vs target | Bullet chart or gauge | Complex chart | | Geographic | Heat map or filled map | Bar chart |

    7 Chart Rules

    1. Title = Insight, not description. "Revenue grew 23% in Q3" not "Q3 Revenue Chart" 2. Start Y-axis at zero for bar charts. Line charts can truncate with clear labeling. 3. Max 5-7 data series per chart. Use "Other" category for the rest. 4. Remove chartjunk — No 3D effects, gradient fills, excessive gridlines. 5. Use consistent colors — Same category = same color across all charts. 6. Label directly on chart where possible. Minimize legend lookups. 7. Sort meaningfully — By value (largest→smallest) or chronologically. Never alphabetically unless it's the only logical order.

    Interactive Dashboard Controls

    Filter by dropdown:
    1. Config sheet: Data validation dropdown for Region, Period, Category
    2. Dashboard formulas use dropdown value:
       =SUMIFS(Data!E:E, Data!C:C, CONFIG_REGION, Data!A:A, ">="&CONFIG_START)

    Sparklines (in-cell mini charts): =SPARKLINE(B2:M2, {"charttype","line"; "color","#2563eb"; "linewidth",2})


    Phase 7: Data Import & Integration

    Import Method Selection

    | Source | Method | Refresh | |---|---|---| | CSV/Excel file | Manual import / Power Query | Manual | | Google Sheets (other) | IMPORTRANGE | Auto (varies) | | Web page table | IMPORTHTML / Power Query | Auto / manual | | API / JSON | IMPORTDATA / Apps Script / Power Query | Scheduled | | Database | Power Query / ODBC | Scheduled | | Another sheet (same workbook) | Direct reference | Real-time |

    Google Sheets Import Functions

    From another spreadsheet:
    =IMPORTRANGE("spreadsheet_url", "Sheet1!A1:D100")

    From web page (table): =IMPORTHTML("url", "table", 1)

    From CSV: =IMPORTDATA("csv_url")

    From XML/RSS: =IMPORTXML("url", "//item/title")

    Excel Power Query Patterns

    1. Data β†’ Get Data β†’ From [Source]
    2. Transform in Power Query Editor
    3. Close & Load (to table or connection only)

    Essential transforms:

  • Remove columns β†’ Right-click header β†’ Remove
  • Filter rows β†’ Click filter arrow
  • Split column β†’ Transform β†’ Split Column
  • Unpivot β†’ Select ID columns β†’ Unpivot Other Columns
  • Merge queries β†’ Home β†’ Merge (= VLOOKUP but better)
  • Append queries β†’ Home β†’ Append (= UNION)
  • IMPORTRANGE Best Practices

    Rules:
    1. Authorize on first use (one-time popup)
    2. Use named ranges in source spreadsheet
    3. Wrap in IFERROR for graceful failures
    4. Minimize imported range β€” don't import entire sheets
    5. Cache results if auto-refresh causes slowness

    Pattern: =IFERROR( IMPORTRANGE(SOURCE_URL, "Data!A1:D"&SOURCE_ROW_COUNT), "⚠️ Connection failed β€” check source spreadsheet access" )


    Phase 8: Automation & Scripts

    Google Apps Script Essentials

    // Auto-populate timestamp on edit
    function onEdit(e) {
      const sheet = e.source.getActiveSheet();
      if (sheet.getName() === "Data" && e.range.getColumn() >= 2) {
        sheet.getRange(e.range.getRow(), 1).setValue(new Date());
      }
    }

    // Email report on schedule (set up trigger) function sendWeeklyReport() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const dashboard = ss.getSheetByName("Dashboard"); const kpi1 = dashboard.getRange("B2").getDisplayValue(); const kpi2 = dashboard.getRange("C2").getDisplayValue(); MailApp.sendEmail({ to: "team@company.com", subject: Weekly Report β€” ${Utilities.formatDate(new Date(), "GMT", "MMM dd")}, htmlBody:

    Weekly KPIs

    Revenue: ${kpi1}

    Growth: ${kpi2}

    }); }

    // Auto-archive rows older than 90 days function archiveOldRows() { const ss = SpreadsheetApp.getActiveSpreadsheet(); const data = ss.getSheetByName("Data"); const archive = ss.getSheetByName("Archive"); const cutoff = new Date(); cutoff.setDate(cutoff.getDate() - 90); const rows = data.getDataRange().getValues(); for (let i = rows.length - 1; i >= 1; i--) { if (rows[i][0] < cutoff) { archive.appendRow(rows[i]); data.deleteRow(i + 1); } } }

    Excel VBA Essentials

    ' Auto-format new entries
    Private Sub Worksheet_Change(ByVal Target As Range)
        If Not Intersect(Target, Range("A:A")) Is Nothing Then
            Application.EnableEvents = False
            Target.Offset(0, 5).Value = Now
            Application.EnableEvents = True
        End If
    End Sub

    ' Refresh all Power Query connections Sub RefreshAllData() ThisWorkbook.RefreshAll MsgBox "All data refreshed at " & Now End Sub

    Automation Decision Guide

    | Task | Google Sheets | Excel | |---|---|---| | On-edit timestamp | Apps Script onEdit | VBA Worksheet_Change | | Scheduled email | Apps Script + trigger | Power Automate | | Data refresh | Apps Script + trigger | Power Query + schedule | | PDF export | Apps Script | VBA + SaveAs | | Cross-system sync | Apps Script + API | Power Automate / VBA | | Custom functions | Apps Script CUSTOM_FUNCTION | VBA UDF or LAMBDA |


    Phase 9: Performance Optimization

    Performance Killers (Ranked)

    | Issue | Impact | Fix | |---|---|---| | INDIRECT/OFFSET (volatile) | πŸ”΄ Critical | Replace with INDEX/XLOOKUP | | Whole-column references (A:A) | πŸ”΄ Critical | Use bounded ranges (A2:A1000) | | ARRAYFORMULA on huge ranges | 🟑 High | Limit range or use QUERY | | Excessive conditional formatting | 🟑 High | Reduce rules, use bounded ranges | | Too many IMPORTRANGE | 🟑 High | Consolidate, cache locally | | Unused sheets with formulas | 🟒 Medium | Delete or clear unused sheets | | Complex nested IFs | 🟒 Medium | Replace with SWITCH/IFS/XLOOKUP | | Heavy formatting (images, shapes) | 🟒 Medium | Minimize decorative elements |

    Google Sheets Performance Rules

    1. Keep workbook under 5M cells (ideal: <500K) 2. Limit IMPORTRANGE to <10 per workbook 3. Use QUERY instead of multiple SUMIFS when possible 4. Put ARRAYFORMULA results on a dedicated calc sheet 5. Avoid NOW()/TODAY() in frequently-recalculated areas

    Excel Performance Rules

    1. Use tables (Ctrl+T) for structured data β€” better performance than raw ranges 2. Power Query > formulas for data transformation 3. XLOOKUP > VLOOKUP > INDEX/MATCH for speed 4. Turn off auto-calculation during bulk edits: Application.Calculation = xlManual 5. Use Power Pivot for >100K rows instead of formulas


    Phase 10: Collaboration & Governance

    Access Control Strategy

    | Role | Permissions | Implementation | |---|---|---| | Owner | Full control | Original creator | | Editor | Edit data, not structure | Share with edit, protect structure sheets | | Analyst | Edit inputs, view outputs | Protect all except input cells | | Viewer | View only | Share as viewer | | Commenter | View + comment | Share as commenter |

    Sheet Protection Pattern

    1. Protect entire workbook structure (prevent sheet add/delete/rename)
    2. Protect each sheet
    3. UNLOCK only input cells (blue-coded)
    4. Set password for admin overrides
    5. Document which cells are editable in README
    

    Version Control

    Naming: YYYY-MM-DD_ModelName_vX.Y
      X = major change (new section, restructure)
      Y = minor change (formula fix, data update)

    Changelog (on README sheet): | Date | Version | Author | Change | |------|---------|--------|--------| | 2025-03-15 | 2.1 | Jane | Added Q2 actuals | | 2025-03-01 | 2.0 | John | Restructured revenue model |

    Collaboration Rules

    1. Never edit someone else's model without telling them 2. Use named versions before major changes (Google Sheets: File β†’ Version history β†’ Name current version) 3. Comment on cells β€” don't explain in chat, explain in the sheet 4. One editor at a time for complex formula areas β€” use "editing" flag cell 5. Weekly review β€” Check for broken references, stale data, unused sheets


    Phase 11: Common Templates

    Budget Tracker Template

    Columns: Month | Category | Subcategory | Budgeted | Actual | Variance | % Variance
    KPIs: Total Budget | Total Spent | Remaining | Burn Rate | Projected Year-End
    Charts: Budget vs Actual (bar), Spend by Category (donut), Monthly Trend (line)
    Formulas:
      Variance: =Actual - Budgeted
      % Variance: =IF(Budgeted=0, "", (Actual-Budgeted)/ABS(Budgeted))
      Burn Rate: =SUMIFS(Actual, Month, "<="&TODAY()) / (MONTH(TODAY()) * Total_Budget / 12)
    

    Project Tracker Template

    Columns: Task | Owner | Status | Priority | Start | Due | Days Left | % Complete | Notes
    Status: πŸ”΄ Blocked | 🟑 In Progress | 🟒 Complete | βšͺ Not Started
    Formulas:
      Days Left: =IF(Status="🟒 Complete", "βœ…", MAX(0, Due-TODAY()))
      Overdue flag: =IF(AND(Status<>"🟒 Complete", Due

    Sales Pipeline Template

    Columns: Deal | Company | Stage | Amount | Probability | Weighted | Owner | Close Date | Days in Stage | Next Action
    Stages: Prospect (10%) | Qualified (25%) | Proposal (50%) | Negotiation (75%) | Closed Won (100%) | Lost (0%)
    Formulas:
      Weighted: =Amount * Probability
      Pipeline: =SUMIFS(Weighted, Stage, "<>"&"Lost", Stage, "<>"&"Closed Won")
      Velocity: =AVERAGE(Days_to_Close_for_Won_Deals)
    Dashboard: Pipeline by stage (funnel), Forecast vs quota, Win rate trend
    

    OKR Tracker Template

    Columns: Objective | Key Result | Metric | Start | Current | Target | Score | Status
    Score: =MIN(1, (Current - Start) / (Target - Start))
    Status: =IF(Score>=0.7, "🟒", IF(Score>=0.4, "🟑", "πŸ”΄"))
    Overall: =AVERAGE(Score) across all KRs per Objective
    


    Phase 12: Quality & Maintenance

    Spreadsheet Quality Rubric (0-100)

    | Dimension | Weight | Scoring | |---|---|---| | Architecture | 15% | Clear sheet structure, data flow direction, README | | Formula Quality | 20% | Named ranges, error handling, no hardcoding | | Data Validation | 15% | Input constraints, dropdowns, type checking | | Visual Design | 10% | Consistent formatting, color coding, readability | | Documentation | 15% | Cell notes, README, changelog, instructions | | Performance | 10% | No volatile functions, bounded ranges, fast recalc | | Error Handling | 10% | IFERROR wrappers, validation checks, no broken refs | | Maintainability | 5% | Protected structure, clear ownership, versioned |

    Monthly Maintenance Checklist

  • [ ] Check for #REF! and #N/A errors across all sheets
  • [ ] Verify data source connections are refreshing
  • [ ] Review and update assumptions (Config sheet)
  • [ ] Remove unused sheets and named ranges
  • [ ] Check file size β€” if growing, archive old data
  • [ ] Test all dropdowns and validation rules
  • [ ] Update README with any changes made
  • [ ] Create named version snapshot
  • 10 Spreadsheet Killers

    | Mistake | Impact | Fix | |---|---|---| | Hardcoded numbers in formulas | Can't audit or update | Named ranges + Config sheet | | No error handling | #N/A cascades break everything | IFERROR on all lookups | | Whole-column references | Slow, crashes on large data | Bounded ranges | | Circular references | Unpredictable results | Redesign calculation flow | | No documentation | "What does this formula do?" | README + cell notes | | No data validation | Garbage in = garbage out | Dropdowns + constraints | | One mega-sheet | Unmaintainable, slow | Split by function | | No backup/versions | One mistake = lost work | Named versions + exports | | Copy-paste instead of formulas | Stale data, inconsistencies | Use references/IMPORTRANGE | | Manual processes that should be automated | Error-prone, time-wasting | Scripts or scheduled refreshes |


    Edge Cases

    Migrating Excel ↔ Google Sheets

  • XLOOKUP works in both (Excel 365 + Google Sheets)
  • QUERY is Google Sheets only β€” replace with Power Query in Excel
  • ARRAYFORMULA is Google Sheets β€” Excel uses Ctrl+Shift+Enter or dynamic arrays
  • Apps Script β†’ no Excel equivalent. Use VBA or Power Automate.
  • Power Query / Power Pivot β†’ no Google Sheets equivalent. Use QUERY or BigQuery connector.
  • Test all formulas after migration. Named ranges may break.
  • Multi-Currency Spreadsheets

    =Amount * XLOOKUP(Currency, FX_Rates!A:A, FX_Rates!B:B)
    Or with GOOGLEFINANCE:
    =Amount * GOOGLEFINANCE("CURRENCY:GBPUSD")
    

    Large Dataset Workarounds (>100K rows)

    1. Split data across multiple sheets by time period 2. Use pivot tables / QUERY instead of row-level formulas 3. Import summarized data, not raw transactions 4. Consider BigQuery + Connected Sheets (Google) or Power Pivot (Excel) 5. If you need >500K rows, graduate to a database


    Natural Language Commands

    When working with spreadsheets, you can ask:

  • "Audit this spreadsheet for quality issues"
  • "Design a financial model for [business type]"
  • "Create a dashboard layout for [metrics]"
  • "Write the formulas for [calculation]"
  • "Optimize this spreadsheet for performance"
  • "Build a data validation system for [input type]"
  • "Create an Apps Script to [automate task]"
  • "Design a template for [use case]"
  • "Review this formula and suggest improvements"
  • "Help me migrate this from Excel to Google Sheets"
  • "Set up a scenario analysis for [model]"
  • "Build a KPI tracker for [department]"

  • ⚑ Level Up β€” AfrexAI Context Packs

    This skill covers spreadsheet engineering methodology. For industry-specific financial models, dashboards, and templates:

  • πŸ’° SaaS Context Pack β€” MRR/ARR models, SaaS metrics dashboards, cohort analysis templates
  • 🏦 Fintech Context Pack β€” Financial modeling, risk calculators, compliance trackers
  • 🏭 Manufacturing Context Pack β€” Production trackers, inventory models, cost analysis
  • πŸ—οΈ Construction Context Pack β€” Project budgets, bid calculators, resource planning
  • $47 per pack β€” Complete AI agent context for your industry.

    Browse all packs: AfrexAI Storefront β†’


    πŸ”— More Free Skills by AfrexAI

  • afrexai-data-storytelling β€” Data visualization & dashboard design methodology
  • afrexai-personal-finance β€” Complete personal finance operating system
  • afrexai-product-analytics β€” Product metrics & analytics engineering
  • afrexai-fpa-engine β€” Financial planning & analysis
  • afrexai-automation-strategy β€” Workflow automation methodology

  • *Built by AfrexAI β€” AI agents that compound capital and code.*