Excel Web アドイン(Office.js)で、バックエンドから取得した配色テーマをユーザーが選ぶだけで「開いているワークブックのテーマ(ページレイアウトのテーマ色)」として反映したい――こうした“ブランド適用”の要望は非常に多い一方で、実装には落とし穴があります。本記事では、できない理由を整理したうえで、現実的に運用できる代替案(UI追従と擬似テーマ)を具体例つきで解説します。
Excelの「ブックテーマ」と、セルの「書式」は別物
まず混同しやすいポイントとして、Excelの「テーマ(Theme)」は単なる色の塗り替えではありません。ブックに紐づくテーマは、主に以下のような“既定の基準”として働きます。
- テーマカラー(アクセント1〜6、ハイパーリンクなど)
- テーマフォント(見出し/本文フォント)
- テーマ効果(図形の影や輪郭などの効果セット)
そして本来の強みは「テーマカラー参照で作られた要素が、テーマ変更に追従して自動的に見た目が変わる」ことです。例えば、テーマ準拠の表・グラフ・図形は、テーマを切り替えるだけで全体のトーンが揃います。
| 項目 | 対象 | 変えると何が起きるか | 例 |
|---|---|---|---|
| ブックテーマ | ブック全体の基準(テーマカラー/フォント/効果) | テーマ参照の要素が“自動追従”しやすい | ページレイアウトの「テーマ」 |
| セル書式 | 特定範囲の塗り/フォント/罫線など | 対象範囲の見た目だけが変わる(追従は基本しない) | 塗りつぶし、条件付き書式 |
| テーブル/グラフのスタイル | オブジェクト単位のスタイル | スタイルを変えれば統一感は出るが、テーマ切替ほど自動ではない | テーブルスタイル、系列色 |
結論:Office.jsでは「現在のワークブックの基礎テーマ」を直接変更できない
多くの開発者が最初に探すのが「workbook.theme」や「ThemeColorsをセットするAPI」ですが、現時点のOffice.js(Excel JavaScript API)には、開いているブックのテーマ(Theme/Theme Colors)を“その場で切り替える”ための公開APIがありません。
さらに、代替候補として挙がりやすい Office Scripts や Excel REST API(GraphのExcel系エンドポイント)でも、ブックテーマそのものを切り替える方法は提供されていない、という整理になります。
なぜできないのか:サンドボックス設計と「ファイル根幹の書き換え」問題
テーマ変更が難しい理由は「色を変える」程度の話ではなく、ブックの内部構造(ファイルとしての構造)に関わる操作だからです。Office.jsはセキュリティと性能を重視したサンドボックス設計で、開いているブックの内部ファイル(OOXML相当の構造)へ直接アクセスして根本から書き換える操作を公開していません。テーマの切り替えは、まさにその“根幹を書き換える”タイプの変更になるため、現状のJavaScript APIでは提供されていない、という説明になります。
ここを押さえると「テーマを変えるAPIが無いのは、単に実装漏れではなく、設計上の制約として当然起こり得る」という納得感が得られます。逆に言えば、テーマ変更の実現可能性が上がるのは、Microsoft側が明示的に対応APIを提供したときに限られます。
現実的な代替案:まずはアドインUIをOfficeのUIテーマに追従させる
「ワークブックのテーマ」ではなく「OfficeアプリのUIテーマ(ライト/ダーク、アクセント等)」にアドインのタスクパネルを合わせるだけでも、ユーザー体験は大きく改善します。
Office.jsの共通APIには、Officeのテーマ情報(背景色・前景色など)へアクセスする Office.context.officeTheme が用意されています。
重要なのは、このAPIが指しているのは“ブックテーマ”ではなく“OfficeアプリのUIテーマ”だという点です(タスクパネルの見た目を揃える用途)。
UI追従の実装イメージ(CSS変数で一括反映)
実装のコツは「Officeテーマの色をCSS変数に流し込み、コンポーネント側はCSS変数だけを見る」設計にすることです。これにより、将来テーマの取り扱いが増えても差分が小さくなります。
<style>
:root {
--office-body-bg: #ffffff;
--office-body-fg: #1a1a1a;
--office-control-bg: #f3f3f3;
--office-control-fg: #1a1a1a;
}
body {
background: var(--office-body-bg);
color: var(--office-body-fg);
}
.button {
background: var(--office-control-bg);
color: var(--office-control-fg);
border: 1px solid rgba(0,0,0,.12);
}
</style>
<script>
function applyOfficeUiTheme() {
const t = Office.context.officeTheme;
if (!t) return;
document.documentElement.style.setProperty("--office-body-bg", t.bodyBackgroundColor);
document.documentElement.style.setProperty("--office-body-fg", t.bodyForegroundColor);
document.documentElement.style.setProperty("--office-control-bg", t.controlBackgroundColor);
document.documentElement.style.setProperty("--office-control-fg", t.controlForegroundColor);
}
Office.onReady(() => {
applyOfficeUiTheme();
// ここに「テーマ変更を検知したら再適用」する処理を追加する設計にすると良い
});
</script>
テーマ変更検知については、Office側のイベント提供状況がホストや要件セットで差が出ます。少なくともイベント型の定義としては「OfficeThemeChanged」はOutlookのタスクパネル向けイベントとして説明されています。
Excelアドインでは、基本方針として「起動時に適用」「表示状態が変わるタイミングで再適用(必要ならユーザー操作で再読込)」のように割り切って設計するほうが、現場では安定します。
本命の代替案:“擬似テーマ”としてブック内の見た目を一括で揃える
「ページレイアウトのテーマを切り替える」ことはできなくても、Office.jsで書式やスタイルをまとめて当てることで、見た目として“それっぽいテーマ適用”は実現できます。Microsoft Q&Aでも、現実的な回避策として「一貫した書式を自前で適用して疑似的に統一する」方針が提示されています。
ただし、これは本物のテーマ変更ではないため、次のような違いが出ます。
| 観点 | 本物のテーマ変更 | 擬似テーマ(書式一括適用) |
|---|---|---|
| 既存要素の追従 | テーマ参照なら自動で変わりやすい | 対象を列挙して変える必要がある |
| 新規要素の追従 | 新しく作ってもテーマ基準で整う | 追加された要素は原則「再適用」しないと揃わない |
| 実装難易度 | APIがあれば簡単(だが現状ない) | 設計と運用(再適用/範囲管理)が必要 |
| ユーザー体験 | Excel標準の挙動に近い | アドインの“適用ボタン”前提にしやすい |
擬似テーマで「何を揃えるか」チェックリスト
擬似テーマの成否は、対象の選び方で決まります。よくある“統一感が崩れるポイント”を先回りして対象化するのがコツです。
| 対象 | 揃えるポイント | 実装のヒント | 注意点 |
|---|---|---|---|
| セル(通常範囲) | フォント/背景/罫線/数値書式 | UsedRangeや、命名範囲など「対象の入口」を決めて適用 | 全シート全セルは重い。範囲を絞る |
| 見出し・タイトル | 見出し色、サイズ、太字 | 「見出し行」ルールを決める(例:1行目は見出し) | ユーザーの自由度とのトレードオフ |
| テーブル | ヘッダー/帯行/集計行 | テーブルの範囲を取ってヘッダー行を強調 | 既存スタイルとの衝突に注意 |
| グラフ | 系列色、軸・タイトル色 | 系列ごとにアクセント色を割り当てる | グラフ種類で設定可能項目が変わる |
| 図形 | 塗り/線/文字色 | 図形に“ブランドカラー”を当てると一気に印象が揃う | 図形が多いと処理が重くなる |
| ピボット/スライサー等 | スタイル、強調色 | 可能な範囲で揃える(無理に全部は狙わない) | API対応が限定的な場合がある |
Q&Aでも、セルスタイル・テーブル・グラフ・図形(必要ならピボット/スライサー)を対象にして統一感を作る方向性が示されています。
擬似テーマの設計:パレットを“トークン化”してブレをなくす
バックエンドから「4〜5種類のパレット」を返す設計は良いのですが、実運用では“色をそのまま塗る”より、意味(役割)を持った色トークンにしておくほうが事故が減ります。
おすすめは、各テーマを次のような役割ベースの定義に分解することです。
| トークン(役割) | 用途例 | 備考 |
|---|---|---|
| primary | タイトル、重要な強調 | ブランドの主役色 |
| accent1〜accent6 | グラフ系列、カテゴリ色 | 系列数が多い場合の循環色 |
| bg | 表の背景、シートの基調 | 白寄り/淡色寄りが扱いやすい |
| surface | ヘッダー行、カード背景 | bgより少し濃い |
| text | 本文文字 | コントラスト確保が最優先 |
| mutedText | 注釈、補助ラベル | 薄すぎると読めないので注意 |
| border | 罫線、区切り線 | 強すぎると“うるさい”印象になる |
| positive / warning / negative | 指標の良否、アラート | 条件付き書式と相性が良い |
このトークンをバックエンドが返すようにしておけば、フロント側は「役割→適用先」のマッピングに集中でき、テーマ数が増えてもロジックは増えにくくなります。
パレット定義(JSON)例
WordPress記事として読みやすい範囲で、最低限の例を載せます(実際はバックエンドから取得)。
{
"id": "brandA",
"name": "Brand A",
"tokens": {
"primary": "#1A73E8",
"accent1": "#1A73E8",
"accent2": "#34A853",
"accent3": "#FBBC05",
"accent4": "#EA4335",
"accent5": "#7E57C2",
"accent6": "#00ACC1",
"bg": "#FFFFFF",
"surface": "#F5F7FA",
"text": "#202124",
"mutedText": "#5F6368",
"border": "#DADCE0"
}
}
Office.jsで擬似テーマを適用する実装パターン
実装は大きく分けて「状態管理」「適用対象の抽出」「一括適用」の3層にすると、後から保守しやすくなります。
状態管理:選ばれたテーマIDをブックに紐づけて保持する
ユーザーが一度選んだテーマを、次回起動時にも復元したいケースがほとんどです。そこで、テーマIDをブック側に保存しておくと運用が楽になります。たとえば次のような設計が定番です。
- 保存先:アドインの設定領域(ブックに紐づく設定)
- 保存内容:themeId、適用範囲(全シート/特定シート/選択範囲)、適用日時など
- 起動時:設定を読み、UIの選択状態を復元。必要なら「再適用」ボタンを目立つ位置に置く
「本物のテーマ変更ではない」以上、ユーザーが作業途中で追加した要素(新しい表/グラフ等)を揃えるには、どこかで再適用が必要になります。そのため“選択状態の保持”は必須級です。
適用対象の抽出:全部やらない、入口を決める
擬似テーマで失敗しがちなのが「全ワークシートの全セルに適用しようとして重くなる」パターンです。おすすめは入口を決めることです。
- 入口A:ユーザーの選択範囲(最も軽い、UXも分かりやすい)
- 入口B:特定シートだけ(レポート用シート、ダッシュボード等)
- 入口C:各シートのUsedRange(網羅できるが、ブック次第で重い)
- 入口D:命名範囲/テーブルを中心に適用(構造化されているブックに強い)
「ブランド適用」の実務では、入口D(テーブル・命名範囲中心)にしておくと、ユーザーが自由に書き散らした範囲まで勝手に塗り替える事故を減らせます。
一括適用:Excel.runでまとめて、最小syncで終える
Office.jsはExcel.runの中でキューイングし、最後にまとめてsyncするのが基本です。テーマ適用は変更数が増えやすいので、次の工夫が効きます。
- 対象を減らす(入口設計)
- 同じ書式をまとめて適用(範囲を分割しすぎない)
- ユーザー操作に対して毎回自動適用しない(「適用」ボタンで確定させる)
擬似テーマ適用(セル・テーブル中心)のサンプル
以下は「選択範囲に、背景・文字・見出し行・罫線を当てる」最小例です。実際は、テーブルやグラフ等にも拡張していきます。
<script>
async function applyPseudoThemeToSelection(tokens) {
await Excel.run(async (context) => {
const range = context.workbook.getSelectedRange();
range.load(["rowCount", "columnCount", "address"]);
await context.sync();
// 本文
range.format.fill.color = tokens.bg;
range.format.font.color = tokens.text;
range.format.font.name = "Calibri";
range.format.font.size = 11;
// 外枠・罫線(軽量化のため最小限にするのがコツ)
const b = range.format.borders;
b.getItem("EdgeTop").color = tokens.border;
b.getItem("EdgeBottom").color = tokens.border;
b.getItem("EdgeLeft").color = tokens.border;
b.getItem("EdgeRight").color = tokens.border;
// 先頭行を見出し扱いにする例
const header = range.getRow(0);
header.format.fill.color = tokens.surface;
header.format.font.color = tokens.text;
header.format.font.bold = true;
// 重要列(例:1列目)を少し強調
const firstCol = range.getColumn(0);
firstCol.format.font.bold = true;
await context.sync();
});
}
</script>
この例はあくまで“入口A(選択範囲)”なので高速です。実務で「全体」を狙う場合は、入口B〜Dに切り替え、適用対象を段階的に広げます。
テーブル・グラフ・図形まで揃えると「テーマ感」が一気に出る
セルだけ塗っても、Excelではテーブル・グラフ・図形が残っていると統一感が崩れます。ここからが“擬似テーマの本番”です。
テーブル:ヘッダーと帯行のルールを固定する
テーブルは「ヘッダー行+帯行(バンディング)」が決まるだけで見た目が締まります。実装方針としては次のどちらかです。
- テーブルスタイルを選ぶ(既定スタイルに寄せる)
- ヘッダー行/データ部/集計行に対して直接色を当てる(カスタム感が出る)
ブランドを強く出したい場合は後者が効きますが、適用対象が増えるほど処理が重くなるので「テーブル数が少ないダッシュボード」に向いています。
グラフ:系列色の割り当てを“アクセント循環”にする
グラフ系列の色は、accent1〜accent6を順番に割り当てるだけで統一できます。ポイントは「系列数が6を超えるケース」を想定して、循環させる(または淡色/濃色の2段階にする)ことです。
実務では、次のような割り当てルールが扱いやすいです。
| 系列番号 | 色 | 補足 |
|---|---|---|
| 1 | accent1 | 主役系列 |
| 2 | accent2 | 比較系列 |
| 3 | accent3 | カテゴリ拡張 |
| 4 | accent4 | カテゴリ拡張 |
| 5 | accent5 | カテゴリ拡張 |
| 6 | accent6 | カテゴリ拡張 |
| 7 | accent1(循環) | 必要なら淡色版に切替 |
図形:スライド資料化するなら必須、Excel内でも効果大
意外と効くのが図形の塗り・線です。ダッシュボードで「カード」「ボタン」「注釈枠」を図形で作っている場合、ここがバラバラだと一気にチープに見えます。図形を使う文化のある組織ほど、擬似テーマの満足度が上がります。
擬似テーマ運用でよく起きる課題と対策
新しく作った表・グラフが揃わない
これは擬似テーマの宿命です。対策は“設計で割り切る”のが最も強いです。
- アドインに「再適用」ボタンを常設する
- 「対象を選択して適用」を基本にし、全体適用は管理者向け機能にする
- ブックの使い方をテンプレート化し、ユーザーが追加する余地を減らす(ダッシュボードは特に有効)
Q&Aでも「これはテーマ変更ではないため、既存/新規要素が自動追従しない」点が明確に注意されています。
適用が重い/固まったように見える
重さの原因は、ほとんどが「対象が大きすぎる」か「sync回数が多い」です。次の順で見直すと改善しやすいです。
- 入口を絞る(選択範囲→特定シート→UsedRangeの順で慎重に)
- “塗る”より“スタイルに寄せる”を優先(スタイル変更のほうが軽い場合がある)
- 適用対象を分割して段階適用(まずセル、次にテーブル、最後にグラフ)
ユーザーの手作業の書式を壊してしまう
ブランド適用とユーザー自由度は衝突しがちです。対策としては、次の2段階が実務で効きます。
- デフォルトは「新規で作る範囲」だけに適用(選択範囲ベース)
- 全体適用には「上書きします」確認と、対象一覧プレビューを付ける
さらに“壊しやすいポイント”は見出し行や条件付き書式です。条件付き書式を多用するブックでは、むしろ条件付き書式側にトークンを反映して、セル塗りは控えめにするほうが事故が減ります。
テンプレート運用という発想:テーマ切替を「ブック差し替え」で実現する
どうしても「本物のテーマ」を使った運用(新規要素の自動追従まで含む)が必要なら、アドインで無理に現在ブックを変えようとせず、最初からテーマ適用済みテンプレートに誘導するのが現実解です。
例えば次のような運用です。
- ブランドA〜Eのテンプレート(.xltx / .xlsx)を用意しておく
- ユーザーがアドインでテーマを選んだら「このテンプレートから新規作成」へ誘導する
- 既存ブックを変えるのではなく、新しいブックで作業を開始してもらう
Office.js側で「別ブックからシートを取り込む」方向なら、ワークブックにワークシートを挿入するAPIも存在します(ただし、これでブックテーマそのものが切り替わるわけではありません)。
どうしても“本物のテーマ変更”が必要な場合
Excelデスクトップ前提であれば、VBA等の世界ではテーマ適用が可能なケースがあります。しかし、Webアドイン(Office.js)の範囲で「今開いているブックの内部テーマを直接書き換える」ことはできない、という前提は変わりません。
したがって要件が強い場合は、以下のいずれかの意思決定が必要になります。
- 要件を変更する(擬似テーマ+再適用運用で成立させる)
- 運用を変更する(テンプレート起点で作業してもらう)
- 技術選定を変更する(デスクトップアドイン/VBA/別経路を検討する)
機能要望を通しやすくするフィードバックの出し方
テーマ変更APIは“できたら便利”ではなく、ブランド統制・テンプレート運用・大量レポートの統一など、実務要件に直結します。実際にMicrosoft側も「フィードバック提出が最も確実」と案内しています。
フィードバックを書く際は、次の情報をセットにすると通りやすくなります。
| 入れるべき要素 | 例 |
|---|---|
| 目的(なぜ必要か) | ブランドカラーを複数社で切替し、同じテンプレートでレポート作成したい |
| 操作イメージ | タスクパネルでパレット選択→現在ブックのテーマが即時切替 |
| 期待するAPI形 | workbook.theme.setColors(…) / applyTheme(themeId) 等 |
| 運用上の効果 | 手作業の書式統一が不要になり、作成ミスや確認コストが減る |
| 現状の痛み | 擬似テーマは再適用が必要で、ユーザー教育と運用負担が大きい |
まとめ:狙うべきゴールは「テーマ切替」ではなく「統一感のある成果物」
Office.jsでブックテーマを直接変更できない以上、「テーマを変える」こと自体をゴールにすると詰まります。代わりに、次の2段構えで設計すると成功率が上がります。
- タスクパネルはOffice UIテーマに追従し、どの環境でも見やすくする(Office.context.officeTheme)
- ブックは擬似テーマで統一感を作る(セル/テーブル/グラフ/図形を“狙って”揃える)
この方針なら、現行APIの範囲で現実的に運用でき、将来もしテーマ変更APIが追加された場合も“擬似テーマの適用ロジック”を段階的に置き換えていけます。

コメント