OKRシートとは、目標(Objective)と主要成果(Key Result)の進捗を一元管理するGoogle Sheetsのテンプレートです。適切に設計すれば、シナリオ切替・ベースライン調整済み進捗率・外部データのクレンジングまでをフォーミュラだけで自動化できます。
適切に設計されたOKRシートは、「Bear(悲観)・Base(標準)・Bull(楽観)」を切り替える1つのセルと、CHOOSEフォーミュラの組み合わせで動きます。このセルを変えるだけで、下流のすべての計算が自動的に対応するシナリオの前提値に切り替わります。予測が変わるたびにセルを手動で差し替える必要もなく、前提値タブを更新したときに参照が壊れることもありません。アーキテクチャ自体はシンプルです。問題は、実際に届くデータがどんな形をしているかです。
OKR関連のチュートリアルの多くは、整然と手入力された4行のデータを前提にしています。でも、月曜の朝に開くシートはそうなっていないはずです。この記事では実務で必要なパターンを一通り解説します。シナリオルーティング、ベースライン調整済みの進捗率の計算、そしてCurrentカラムがノーブレークスペース付きのテキスト文字列としてインポートされてきたときの対処法まで。
OKRシートを機能させるタブ構成
最小構成のOKRシートは3つのタブで成り立ちます。日常管理用、前提値用、シナリオ切替用の3つです。
OKR_Tracker — 毎日確認するメインタブ:
| 列 | ヘッダー | 入力例 |
|---|---|---|
| A | Objective | 中小企業向け売上拡大 |
| B | Key Result | 新規ARR |
| C | Owner | 営業部 |
| D | Baseline | 6,500万円 |
| E | Target | 1億4,000万円 |
| F | Current | 1億870万円 |
| G | Confidence | Base |
| H | Progress% | =フォーミュラ |
Revenue_Assumptions — ドライバーごとに1行、シナリオを3列で管理:
| ドライバー | Bear | Base | Bull |
|---|---|---|---|
| 新規受注率 | 18% | 24% | 31% |
| 平均契約単価 | 280万円 | 340万円 | 410万円 |
| 営業サイクル(日) | 72 | 58 | 44 |
| 解約率 | 6.2% | 4.1% | 2.8% |
Scenario — B1の1セルに「Bear,Base,Bull」でドロップダウンを設定。
計算セルに入れるCHOOSEフォーミュラは、このドロップダウンを読んで該当する列に振り分けます:
=CHOOSE(MATCH(Scenario!$B$1,{"Bear","Base","Bull"},0),
Revenue_Assumptions!B2,
Revenue_Assumptions!C2,
Revenue_Assumptions!D2)
CFOや経営企画部長が「今回は保守的なケースで試算してほしい」と言えば、1セルを切り替えるだけです。以降の全試算が自動で更新されます。前提値タブの構造さえ整っていれば、この仕組みを組み上げるのに必要な時間は20分程度です。
なお、名前付き範囲を使う実装もよく見かけますが、タブ名を変えるたびに参照が壊れるという問題があります。CHOOSE+MATCHパターンはその依存を持たないため、2026年4月時点でGoogle Sheetsにおけるシナリオルーティングの最もクリーンな実装方法です。
OKRシートに本当に必要なベースライン調整済み進捗率
単純な進捗率フォーミュラは =F2/E2、つまりCurrentをTargetで割るだけです。数字は出ますが、実態を反映していません。
ベースラインが6,500万円、ターゲットが1億4,000万円で、現在が1億870万円の場合、このフォーミュラは「ターゲットの77.6%達成」と返します。しかし出発点は0円ではなく6,500万円です。実際に縮めなければならないギャップのうち、どれだけ埋めたかを正しく示すには次の式が必要です:
=(F2-D2)/(E2-D2) → (1億870万円 - 6,500万円) ÷ (1億4,000万円 - 6,500万円) = 58.3%
これは見た目だけの違いではありません。ARRベースラインが4億3,500万円で、ターゲットが5億円の事業に単純な進捗率を使うと、ヘッドラインは77%でも実際の進捗は52%になります。四半期レビューで「達成率77%」と報告したあと、期末に大幅未達が発覚する——このパターンの多くは、分母の設定ミスが原因です。正しい分母を使うだけで防げます。追加で書くのは4文字です。
OKR_Tracker の H2 に次のフォーミュラを入れてください:
=IFERROR((F2-D2)/(E2-D2), "—")
IFERRORは必須です。ターゲットとベースラインが同じ値になっているケース——目標未確定のまま立ち上げたOKRではよく起きます——では、ゼロ除算エラーが発生します。ラッパーなしだと進捗列全体がエラー表示になり、四半期レビュー直前にシートが使い物にならなくなります。ラッパーを入れておけばダッシュが表示されるだけで済みます。
データが汚いときに起きること
Currentカラム(F列)が、OKRシートが実際に壊れる場所です。手入力であれば問題ありません。CRM・ERPやCSVエクスポートからインポートしている場合、これは必ず起きます:
セルには 108700000 と表示されているのに、=F2-D2 が #VALUE! を返す。
セルの中身はテキスト文字列です。見た目は数値ですが、Sheetsは数値として認識していません。確認方法:=ISNUMBER(F2) がFALSEを返します。列全体を一括修正するなら:
=VALUE(TRIM(SUBSTITUTE(F2, CHAR(160), " ")))
SUBSTITUTEの部分は、多くのクレンジング解説が省略しているポイントです。CHAR(160) はノーブレークスペースで、セル上では通常のスペースと見分けがつきません。TRIMだけでは除去できません。Google SheetsのTRIM関数が削除するのはASCIIの通常スペース(コード32)のみで、ノーブレークスペース(コード160)はそのまま通過します。基幹システム、CRM、Unicodeを出力するシステムからのインポートであれば、すでにこの問題が起きている可能性があります。
混在フォーマット・空白行・"108 %"(パーセント記号の前にスペースが入っているケース)まで含む完全版:
=IFERROR(
VALUE(
TRIM(
SUBSTITUTE(
SUBSTITUTE(F2, CHAR(160), ""),
"%", ""
)
)
) / IF(SEARCH("%", F2&""), 100, 1),
""
)
このフォーミュラで対応できるケース:スペース付きのパーセンテージ文字列、ノーブレークスペース、空白セル、通常の数値。ヘルパー列(Current_Clean と名付けることを推奨)に入れて、進捗フォーミュラはインポート列ではなくこのヘルパー列を参照するようにしてください。
Confidenceが未設定の行——目標は立てたがG2が空のOKR——では、CHOOSEルーティングがエラーになります。次のようにラップしておきます:
=IFERROR(
CHOOSE(
MATCH(G2, {"Bear","Base","Bull"}, 0),
Revenue_Assumptions!B2,
Revenue_Assumptions!C2,
Revenue_Assumptions!D2
),
Revenue_Assumptions!C2
)
Confidenceが未設定の場合はBaseにフォールバックします。これは合理的なデフォルトで、入力途中のトラッカーでも空白行より下の行が壊れずに済みます。
エラーに強いOKRシートのフォーミュラ構成
まとめると、OKR_Trackerの本番用の1行はこうなります:
H2 — ベースライン調整済み進捗率:
=IFERROR((Current_Clean-D2)/(E2-D2), "—")
シナリオ別ターゲット(シナリオごとに目標値が変わる場合):
=IFERROR(
CHOOSE(MATCH(G2,{"Bear","Base","Bull"},0),
Targets!B2, Targets!C2, Targets!D2),
Targets!C2
)
ターゲットまでのギャップ(金額):
=IFERROR(E2 - Current_Clean, "—")
IFERRORラッパーは「念のための保険」ではありません。ダッシュで静かに失敗するシートと、40行にわたってエラーを伝播させて取締役会直前にシート全体を使い物にならなくするシートを分ける、実質的な違いです。
よくある質問
Q. CHOOSEとIFSはどちらが保守しやすいですか?
シナリオが3つ固定であればCHOOSE+MATCHの方がすっきりしています。シナリオ名を配列で一元管理できるため、後から修正する際に複数箇所を直す必要がありません。IFSは条件ごとに独立した式になるため、シナリオが増えたときにメンテナンスコストが上がります。
Q. Revenue_Assumptionsの列数が変わった場合、フォーミュラはどうなりますか?
CHOOSE+MATCHパターンは列のインデックスではなく値の一致で動作するため、列の追加・削除の影響を受けません。ただし前提値タブの列ヘッダー(Bear/Base/Bull)の文字列は変えないようにしてください。
Q. 複数のOKRでシナリオを独立して切り替えることはできますか?
Scenario!$B$1を1セルで管理する設計では全OKRが同じシナリオに連動します。OKRごとに独立したConfidence列(G列)を設ける場合は、行レベルのMATCHを使ってください。本記事のCONFIDENCEフォールバック例がその実装パターンに当たります。
Q. Google SheetsとExcelでフォーミュラの挙動は同じですか?
CHOOSE・MATCH・IFERROR・SUBSTITUTEはいずれも両環境で動作します。CHAR(160)のノーブレークスペース問題はExcelでも同様に発生します。Apps Script依存の実装でなければ、ほぼそのまま移植できます。
Q. OKRの行数が増えてもパフォーマンスは落ちませんか?
Current_Cleanのような複合IFERRORフォーミュラを数百行に展開すると再計算が遅くなることがあります。その場合はCurrent_Cleanをヘルパー列に固定値として貼り付け(値のみ貼り付け)、週次バッチで更新する運用が現実的です。
Google SheetsでのOKR運用を効率化する
ここまで紹介したフォーミュラを一から組み上げるには1時間ほどかかります。それ以上に時間を取られるのは、その後の運用です。実績値の更新、CSVのフォーマットが変わったときにCurrent_Cleanの式が正しく動いているかの確認、四半期途中でOKRが変わった際の行追加——これらの積み重ねで、四半期ごとに5時間以上が消えていきます。
OKRトラッカーをGoogle Sheetsで管理しているなら、ModelMonkeyのプランを選ぶ。OKR_TrackerとRevenue_Assumptionsタブを読み込んで、実績値の更新・新規OKRの追加・インポートフォーマット変更後のCurrent_Cleanフォーミュラの修正を行えます。「Q2の実績をこのテーブルから更新して」と入力してエクスポートデータを貼り付けるだけで、毎回シートの構造を一から説明しなくても、フォーミュラを検査して処理します。Google SheetsとExcelの両方に対応しています。