OKR sheet architecture: a 3-tab design
Split the workbook into three tabs.
| Tab | Role | Data flow |
|---|---|---|
| OKR_Data | KR inputs and score calculation | Outputs to Assumptions only |
| Assumptions | Scenario switches and financial assumptions (DSO, Capex included) | Outputs to P&L, BS, CF |
| P&L / BS / CF | Three-statement model | Receives from Assumptions only |
One-way flow keeps the model auditable. If the P&L references OKR_Data directly, cross-tab dependencies snowball and you can't trace where a number came from. Centralizing every financial assumption in one tab means a scenario change propagates consistently across all three statements.
Required FP&A fields per OKR row
In Measure What Matters (Portfolio/Penguin, 2018, ch. 4), John Doerr defines a Key Result as something whose attainment must be judgable independently of other KRs. Translated into spreadsheet terms, you need at least seven columns per row.
| Col | Field | Type | Example |
|---|---|---|---|
| A | KR_ID | Text | 2026Q3-SALES-01 |
| B | Objective description | Text | Hit ARR ¥500M |
| C | Target value | Number | 500,000 |
| D | Weight (0–1) | Number | 0.35 |
| E | Current value | Number | 338,000 |
| F | Progress | Formula | =E2/C2 |
| G | Confidence score | Number (manual) | 0.72 |
| H | Last updated | Date | 2026/05/01 |
The confidence score (column G) is not the same as progress (column F). ARR can be at 67% of target while confidence sits below 50% because pipeline quality has degraded. That subjective estimate is the input that drives the scenario switch.
The weighted-average score lives at Assumptions!B3.
// Assumptions!B3: weighted-average KR confidence
=SUMPRODUCT(OKR_Data!G2:G20, OKR_Data!D2:D20)
/ SUMPRODUCT(OKR_Data!D2:D20)
Per Google Sheets' SUMPRODUCT documentation, the function multiplies arrays element-wise and sums the result, treating blanks as zero. Even an ARRAYFORMULA over 5M rows recalculates in under 50ms.
Cascading into EBITDA
Branch scenarios off the score in Assumptions!B3.
// Assumptions!B4: scenario flag
=IF(B3>=0.75,"OnTrack",IF(B3>=0.55,"Caution","Downside"))
// Assumptions!B5: monthly revenue assumption (¥k)
=IFS(B4="OnTrack", 42000, B4="Caution", 36000, B4="Downside", 29000)
In Q2 2026, the weighted-average KR score was 75.7% — OnTrack. Going into Q3, the product roadmap KR and customer success KR slipped, and the score fell to 67.8%. The scenario auto-switches to Caution.
| Scenario | Monthly revenue | Quarterly EBITDA (22%) | NOPAT (30% tax) |
|---|---|---|---|
| OnTrack (≥75%) | ¥42,000k | ¥27,720k | ¥19,404k |
| Caution (55–75%) | ¥36,000k | ¥23,760k | ¥16,632k |
| Downside (<55%) | ¥29,000k | ¥19,140k | ¥13,398k |
// P&L!C5: quarterly EBITDA
='P&L'!C3 * Assumptions!$B$8 // C3 = quarterly revenue, B8 = EBITDA margin (0.22)
// P&L!C7: NOPAT
='P&L'!C5 * (1 - Assumptions!$B$9) // B9 = effective tax rate (0.30)
From KR confidence to FCFF waterfall
This is where the model becomes investor-ready. A scenario toggle on the P&L alone doesn't finish FCFF. KR confidence shifts working capital (DSO) and Capex timing, and those flow straight into cash.
DSO assumption and balance-sheet linkage
When product KRs slip, customer acceptance drags and the collection cycle stretches. In Caution, lift average DSO from 45 days to 52.
// Assumptions!B6: DSO (days)
=IFS(B4="OnTrack", 45, B4="Caution", 52, B4="Downside", 60)
// BS!C15: AR balance
='P&L'!C3 / 90 * Assumptions!$B$6
// P&L!C3 = quarterly revenue (Caution: ¥108,000k)
// → AR balance: ¥108,000 / 90 × 52 = ¥62,400k
// BS!C16: ΔAR (vs prior period)
=C15 - B15
// B15 = end-of-Q2 AR (OnTrack: ¥126,000/90×45 = ¥63,000k)
// → ΔAR = ¥62,400 - ¥63,000 = -¥600k (small AR release = small WC improvement)
Capex timing linkage
It's irrational to keep deploying full growth Capex while a product roadmap KR is slipping. In Caution, defer 50% of growth Capex on engineering equipment. In Downside, freeze it entirely.
// Assumptions!B7: quarterly Capex (¥k)
=IFS(B4="OnTrack", 45000, B4="Caution", 22500, B4="Downside", 0)
FCFF waterfall (CF tab)
// CF!C3: NOPAT (from P&L)
='P&L'!C7
// CF!C5: D&A (fixed, ¥9,000k/Q)
=Assumptions!$B$10
// CF!C7: ΔWC (sign-flipped ΔAR)
=-'BS'!C16
// CF!C9: Capex
=-Assumptions!$B$7
// CF!C11: FCFF
=C3 + C5 + C7 + C9
Lay the three scenarios side by side and a structural pattern jumps out.
| FCFF waterfall (Q3 2026, ¥k) | OnTrack | Caution | Downside |
|---|---|---|---|
| NOPAT | ¥19,404 | ¥16,632 | ¥13,398 |
| D&A | ¥9,000 | ¥9,000 | ¥9,000 |
| ΔWC (sign-flipped ΔAR) | ¥0 | +¥600 | +¥4,400 |
| Capex | -¥45,000 | -¥22,500 | ¥0 |
| FCFF | -¥16,596 | +¥3,732 | +¥26,798 |
The Downside FCFF is higher than OnTrack — because Capex went to zero. When you walk an investor through this paradox in a QBR, "we're cash-rich even in Downside" doesn't fly. What does work: "this is the result of halting growth investment, and we're trading future runway to get there." That framing is the value of binding the OKR sheet to FCFF.
The OnTrack-to-Caution shift produces a +¥20,328k FCFF delta. Here's the bridge.
| FCFF bridge (OnTrack → Caution, ¥k) | Amount |
|---|---|
| ① NOPAT contraction (revenue -¥18,000k × 22% × 70%) | -¥2,772 |
| ② ΔWC improvement (AR -¥600k, WC release) | +¥600 |
| ③ Capex deferral (¥45,000 → ¥22,500) | +¥22,500 |
| FCFF delta | +¥20,328 |
Drop this bridge into the monthly board deck as a single page and the explanation lands on its own: "OKRs are tracking behind, so we deferred Capex; the FCFF impact was +¥20,328k." You start the conversation on KR attainment and end up with numbers that reconcile to the balance sheet and cash flow. That's the point of the design.
Staleness alerts to keep inputs fresh
If a KR confidence score hasn't been touched in 14 days, the Assumptions tab is running on a dead input. As of May 2026, plenty of teams ship quarterly forecasts without realizing the underlying scores haven't moved.
// Assumptions!D3: days since last update
=TODAY() - MAX(OKR_Data!H2:H20) // column H = each KR's last-updated date
// Assumptions!E3: alert message
=IF(D3>14,
"⚠ KR scores " & D3 & " days stale — model needs review",
"✓ Fresh")
Park that cell at the top of the Assumptions tab, paint it red with conditional formatting, and it's the first thing you see when the model opens. SUMPRODUCT can extend it to per-owner alerts.
// Per-owner staleness check
=SUMPRODUCT((TODAY()-OKR_Data!H2:H20>14)*(OKR_Data!I2:I20="Tanaka"))
// Column I = owner name; any value ≥1 means follow-up needed
Closing the update loop with ModelMonkey
The sheet design itself is complete with the SUMPRODUCT and 3-tab structure above, but the operational cost of updating eight or more KRs every week isn't trivial. Connect ModelMonkey to Google Sheets and confidence-score inputs from Slack or Google Forms write straight into the OKR_Data tab — every entry triggers a recompute through Assumptions, P&L, BS, and CF. The 14-day alert fires less often, and the "are these numbers right?" check before QBR shrinks.
Try ModelMonkey free for 14 days — works in both Google Sheets and Excel.