mcpField
O
officecli-data-dashboard

officecli-data-dashboard

github.com/iofficeaiデータ・データベース32.7k101 回インストール今日更新
リポジトリ

officecli-data-dashboard について

officecli-data-dashboardは、officecli-xlsxを基盤に、Dashboardシートを中心とした表計算ダッシュボードの作成を案内するスキルです。数式によるKPI、セル範囲参照のチャート、視覚的な書式設定を重視します。

主な機能

  1. 01数式駆動のKPIカード作成
  2. 02セル範囲を参照するチャート
  3. 03Dashboardシートへのチャートとスパークライン配置
  4. 04データ量に応じた構成の調整
  5. 05条件付き書式による視覚的な確認
  6. 06ブックの検証とレンダリング結果の確認

活用シーン

  1. 01売上CSVから経営向けダッシュボードを作成
  2. 02KPIと推移チャートを含む運用画面の作成
  3. 03元データに応じて更新される指標とチャートの表示
  4. 04印刷向けダッシュボードブックの準備

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/iofficeai/officecli --skill officecli-data-dashboard

インストール後、Claude Code で/officecli-data-dashboardを入力して読み込まれたか確認します。

詳細

データダッシュボード(officecli-xlsx 上のシーンレイヤー)

ダッシュボードは「グラフ付きのスプレッドシート」ではありません。構成されたものです。ユーザーが最初に開く 1 つのダッシュボードシート に、数式で駆動する KPI カード、セル範囲にリンクされたグラフ、スパークライン、意味的な条件付き書式を配置します。それ以外(生データや集計)は、ユーザーが開く必要のない上流のインフラです。このスキルでは、その構成パターンを扱います。xlsx エンジンに関する内容(セル、数式、バッチ JSON、シェルのクォート、validate、HTML プレビュー)はすべて officecli-xlsx から提供されるため、ここでは再度説明しません。

セットアップ

officecli がインストールされていない場合:

  • macOS / Linux: curl -fsSL https://d.officecli.ai/install.sh | bash
  • Windows (PowerShell): irm https://d.officecli.ai/install.ps1 | iex

officecli --version で確認してください(PATH が反映されていない場合は新しいターミナルを開いてください)。インストールに失敗した場合は、https://github.com/iOfficeAI/OfficeCLI/releases からバイナリをダウンロードしてください。

⚠️ ヘルプ優先ルール

プロパティ名、列挙値、エイリアスが不確かな場合は、推測する前にヘルプを参照してください。

officecli help xlsx                          # element list
officecli help xlsx chart                    # full schema for charts
officecli help xlsx sparkline                # sparklines
officecli help xlsx conditionalformatting    # all CF rule types

ヘルプはインストール済み CLI のバージョンを反映しています。このスキルとヘルプの内容が食い違う場合は、ヘルプが優先されます。DeferredAddKeys(combosplit、holesize)は add でのみ機能します。詳細は Reference を参照してください。

メンタルモデルと継承

このスキルは officecli-xlsx のすべての xlsx のハードルールを継承します。シェルのクォート、ゼロの数式エラー、ビジュアル提供の最低基準、バッチ JSON の形式({"command":"set"|"add","path":...,"props":{...}} — キーは action ではなく command)、バッチ JSON のドット区切り名ルール、グラフのデータ供給形式、バッチとレジデントの制限、validate の運用規律などです。まず officecli-xlsx を読み、それらのルールを守ってください。ここでは再度説明しません。

逆方向の引き継ぎ — 次の場合はこのスキルを使用しないでください:

  • 依頼内容が 書式付き CSV の単一シート型トラッカー(ダッシュボードシートなし、KPI カードなし、グラフ 1 つ以下)の場合 → officecli-xlsx に戻ってください。
  • 依頼内容が、青い入力セル・黒い数式・シート間ドライバーを持つ 3 表(損益・貸借・キャッシュフロー)/ DCF / LBO の財務モデル の場合 → officecli-financial-model を使用してください。
  • 依頼内容が、1 つの SUMIF 集計と 10 行未満のデータに対する 1 つのグラフからなる 週次ステータスレポート の場合 → officecli-xlsx を使用してください。

このスキルが受け付けるのは「ユーザーが最初に開くダッシュボードシート、複数の KPI カード、複数のグラフ、いくつかの CF / スパークライン」を求める依頼のみです。

シェルと実行の規律

→ 基本ルール(クォート、! 用のヒアドキュメント、段階的な実行)については officecli-xlsx の「シェルと実行の規律」を参照してください。

ダッシュボード特有の追加ルールは 2 つです:

  • 長いグラフの add コマンドは 180 文字を超えます。 必ず末尾に \ を付けて複数行に分割し、グラフのコマンドを 1 行にまとめないでください。コマンドが長いほど、シェルのエスケープ不具合が紛れ込む可能性が高くなります。
  • 複数インスタンスの件数確認には query --json | jq length を使い、raw-get | grep -c は使わないでください。 例: 「グラフは何個ありますか?」という確認には officecli query "$FILE" chart --json | jq '.data.results | length' を使います。

コア原則

譲れない 5 つの原則です。いずれか 1 つでも破られると、その成果物はダッシュボードではなく、たまたまグラフがついたスプレッドシートになります。

  1. 数式駆動の KPI。 ダッシュボードシートのすべての KPI 値は、Data / Summary シートのセルを参照する数式です。SUM、AVERAGE、IFERROR((...-...)/...,0) など、何でも構いません。計算された数値を直接入力しないでください。明日元データが変わっても、KPI は開いたときに更新されます。

  2. グラフにはセル範囲参照を使用。 すべてのグラフ系列は、セル範囲から値を読み取ります。例: series1.values="Sheet1!B2:B13"。インラインの data="Revenue:100,200,300" は 5 分間のデモ向けであり、納品するダッシュボードには使わないでください。唯一の例外は、Excel では表現できない集計がデータに必要な場合(まれ)です。その場合は、コメントセルに例外を記録してください。

  3. ダッシュボード優先のアーキテクチャ。 KPI のラベルセル、KPI の値セル、グラフ、スパークラインはすべて Dashboard シートに配置します。これはユーザーが最初に開くシートです。元データの取り込みと SUMIFS による集計は Data / Summary シートに置き、Dashboard の上流に位置付けます。ユーザーが答えを探すためにタブを切り替える必要があってはなりません。

  4. グラフのソースには表示されているセルのみを使用。 LibreOffice は、描画時に非表示の列や非表示のシートにある数式を評価しません。series1.values が非表示列の SUMIFS を指しているグラフは、空白で描画されます。対処法は、表示された Summary シートに集計し、グラフは Summary のセルを指すようにすることです。非表示にしてよいのは、グラフのソースではない補助列だけです。

  5. データ量に応じた複雑さ。 10 行のデータセットに KPI 5 つとグラフ 4 つを用意する必要はありません。200 行のデータセットに KPI 1 つとグラフ 1 つだけを用意する必要もありません。入力に合わせて構成を拡大してください(§Design Ideas の表を参照)。過剰な作り込みも、作り込み不足と同じく誤りです。

要件

すべての officecli-xlsx の要件が適用されます(→ officecli-xlsx の §Requirements for Outputs を参照)。ダッシュボードでは、さらに以下を追加します。

  • ダッシュボードシートは、開いたときにアクティブなタブになること。 activeTab="N" を設定する前に、officecli query "$FILE" sheet で 0 始まりのシートインデックスを確認してください。インデックスを推測しないでください。
  • calc.fullCalcOnLoad=true。 officecli set "$FILE" / --prop calc.fullCalcOnLoad=true で設定します。<calcPr> を raw-set で直接設定しないでください。重複した要素が生成され、validate に失敗します。
  • 上流を編集するたびに、下流の cachedValue を更新すること。 fullCalcOnLoad=true が行うのは実行時の再計算のスケジュール設定だけで、ビルド時の cachedValue は更新しません。set B=100 → set E==B+D → fix B=150 の後、E の数式を再入力する(またはファイルを閉じて開き直す)まで E は古いままです。古いキャッシュのまま配布すると、ボードに「Net Change = 0」と表示されてしまいます。
  • すべてのグラフに説明的なタイトルを付け、すべての系列に名前を付けること。 凡例に "Series1" と表示されている状態は、作業が未完了であることを意味します。
  • すべての KPI 値セルに数式があること。 確認方法: officecli query "$FILE" 'Dashboard!:has(formula)' --json | jq '.data.results | length' の結果が、計画した KPI の数と一致するはずです。
  • すべてのデータシートにヘッダー行の塗りつぶしを設定すること。 Data シート、Summary シート、その他の補助データシートはすべて、1 行目を塗りつぶす必要があります(例: fill=1F3864 + font.color=FFFFFF + font.bold=true)。
  • Data シートが 10 行以上の場合は、数値列に少なくとも 1 つの CF ルールを設定すること。 視覚的に走査する手がかりがない 20 行の表は、品質上の欠陥です。
  • Dashboard の値列の幅は、想定される最大の cachedValue に合わせること。固定の 22 にしないこと。 24pt 太字で通貨の numFmt を使う場合の目安は width ≈ ceil((visible_chars + 2) × 1.3) です。通貨記号とカンマを含めて 14 文字の ¥1,958,414,250 を表示する KPI は width ≥ 28 が必要です。4 桁の KPI でも、最低 width ≥ 22 は必要です。10 桁以上の KPI に 22 をそのままハードコードすると、ユーザーに ### が表示されてしまいます。
  • スパークラインの行の高さは 20 以上にすること。 既定の 15pt の行にあるスパークラインは平坦な波線にしか見えません。/Dashboard/row[N] height=22(同じ行に 24pt の KPI 値セルがある場合は 24)と設定してください。
  • 印刷用の成果物では、_xlnm.Print_Area を Dashboard に限定して設定し、Dashboard 以外のシートを非表示にし、<pageSetup fitToPage/> を追加すること。3 つすべてを行わないと、印刷処理ではすべてのシートが出力され、Dashboard が 2 ページ目以降に配置されてしまいます。具体的なコマンドは §Print-ready delivery を参照してください。

クイックスタート

最小構成のダッシュボードです:12か月分の売上CSV → KPI 4つ + 折れ線グラフ1つ + activeTab + fullCalcOnLoad。数値は自分のデータに合わせて調整してください。盲目的にコピー&ペーストしないようにしてください。フェーズに分けているので、失敗したフェーズがすぐにわかります。

フェーズ1 — データシート:作成、インポート、書式設定。

FILE=my_dashboard.xlsx
officecli create "$FILE"
officecli import "$FILE" /Sheet1 --file sales.csv --header
officecli set "$FILE" '/Sheet1/col[A]' --prop width=12
officecli set "$FILE" '/Sheet1/col[B]' --prop width=15
officecli set "$FILE" '/Sheet1/B2:B13' --prop numFmt='$#,##0'
officecli set "$FILE" '/Sheet1/A1:B1' --prop fill=1F3864 --prop font.color=FFFFFF --prop font.bold=true

フェーズ2 — ダッシュボードシート + KPIカード1つ。

officecli add "$FILE" / --type sheet --prop name=Dashboard
officecli set "$FILE" '/Dashboard/col[A]' --prop width=22
officecli set "$FILE" '/Dashboard/col[B]' --prop width=12
officecli set "$FILE" /Dashboard/A1 --prop value="Total Revenue" --prop font.size=9 --prop font.color=666666 --prop bold=true
officecli set "$FILE" /Dashboard/A2 --prop 'formula==SUM(Sheet1!B2:B13)' --prop numFmt='$#,##0' --prop font.size=24 --prop bold=true --prop font.color=2E7D32

フェーズ3 — スパークラインとグラフ。

officecli add "$FILE" /Dashboard --type sparkline --prop cell=B2 --prop range='Sheet1!B2:B13' --prop type=line --prop color=4472C4 --prop highPoint=true --prop highMarkerColor=FF0000
officecli add "$FILE" /Dashboard --type chart \
  --prop chartType=line \
  --prop title="Revenue Trend" \
  --prop series1.name="Revenue" \
  --prop series1.values='Sheet1!B2:B13' \
  --prop series1.categories='Sheet1!A2:A13' \
  --prop preset=dashboard --prop axisNumFmt='$#,##0' \
  --prop x=0 --prop y=5 --prop width=10 --prop height=15

フェーズ4 — fullCalcOnLoad → activeTab(最後)→ 閉じる → 検証。

officecli set "$FILE" / --prop calc.fullCalcOnLoad=true

# Resolve Dashboard's 0-based index from the actual sheet list — never hardcode.
DASH_IDX=$(officecli query "$FILE" sheet --json \
  | jq '[.data.results[].path] | index("/Dashboard")')
officecli raw-set "$FILE" /workbook --xpath "//x:sheets" --action insertbefore \
  --xml "<bookViews xmlns=\"http://schemas.openxmlformats.org/spreadsheetml/2006/main\"><workbookView activeTab=\"$DASH_IDX\" /></bookViews>"
officecli close "$FILE"
officecli validate "$FILE"

12行の売上CSVでエンドツーエンドの検証を行いました。validate はエラーを報告せず、ダッシュボードが最初に開き、Dashboard/A2.cachedValue が解決され(テストデータでは 2,075,000)、グラフは値がリンクされた状態で描画されました。

デザインのアイデア

これらは選択肢であり、テンプレートではありません。ユーザーのデータと対象読者によって選び方が決まります。

レイアウトパターン(1つ選び、一貫して使用)

パターン1 — エグゼクティブサマリー(役員向け資料):KPIストリップ A1:H4、6行目からグラフを縦に積み重ねます。

┌ KPI1 │ KPI2 │ KPI3 │ KPI4 ┐  rows 1-4
├──────┴──────┴──────┴──────┤
│     Chart 1 (wide)        │  rows 6-18
├───────────────┬───────────┤
│   Chart 2     │  Chart 3  │  rows 20-32

パターン2 — オペレーションコンソール(リアルタイム運用):KPIをA:Bに縦に並べ、グラフでC:Lを埋めます。

│ KPI1 │                   │
│ KPI2 │    Chart 1        │  rows 1-12
│ KPI3 │                   │
│ KPI4 ├───────────────────┤
│ KPI5 │    Chart 2        │  rows 14-26

パターン3 — スコアカード(KPIが6つ以上で、支配的なグラフがない場合):2×3のカードグリッド(ラベル / 値 / スパークライン)。

│ KPI1 │ KPI2 │ KPI3 │  rows 1-4
│ KPI4 │ KPI5 │ KPI6 │  rows 5-8
データ量に応じた複雑さの調整
行数KPIグラフスパークラインCFルールプリセット
10未満1–21省略0–1minimal
10–502–32連続した時系列の場合のみ1–2dashboard
50–2003–52–3連続した時系列の場合のみ2–3dashboard
200以上3–53連続した時系列の場合のみ3–4dashboard
グラフの種類の選択
データのパターングラフの種類補足
1系列の時間推移lineノイズの多い系列で傾向を示すには trendline=linear を追加
複数の構成要素の時間推移line(複数系列)または columnStacked構成要素の合計に意味がある場合は積み上げ
時系列順のカテゴリ間比較columnbar は不可。横棒グラフは左から右への時間の読み取りを崩します
全体に対する内訳doughnutpie より推奨。chartType=pie には既知のLibreOffice空白描画の不具合があります
予算と実績combosplit=1 付きの combo最初の系列を棒、残りを折れ線に
相関scatterX軸は categories / series1.categories で指定。series1.xValues はサポート外です
プリセットオプション

すべてのグラフに --prop preset=<name> を指定します。選択肢は minimal、dashboard、corporate、magazine、colorful、monochrome、dark です。1つ選び、同じダッシュボード上のすべてのグラフで一貫して使用してください。プリセットを混在させると、意図しない見た目に見えてしまいます。

条件付き書式 — 意味に応じた色

CFのルールタイプは4種類あり、add 時に --type <shorthand> で指定します:

目的--type代表的なプロパティ
大きさを示す棒(売上、支出)databarsqref=B2:B13 color=4472C4。予測可能なスケーリングのために明示的な min=0 max=<妥当な値> を推奨しますが、省略も有効です(データの最小値・最大値がデフォルト)
ヒートマップ(率、成長率)colorscalesqref=D2:D13 mincolor=FFCDD2 midcolor=FFFFFF maxcolor=C8E6C9
ステータス表示iconsetsqref=E2:E13 iconset=3Arrows。完全な列挙値はヘルプを参照してください
カスタムの業務ルールformulacfsqref=B2:B13 'formula=$B2>=100000' fill=C8E6C9 font.color=2E7D32。font.bold はCFでも有効です

ダッシュボード内で一貫して使用する意味的な色:

  • 良い / 正の値:塗りつぶし C8E6C9、フォント 2E7D32
  • 悪い / 負の値:塗りつぶし FFCDD2、フォント C62828
  • 中立:塗りつぶし F5F5F5、フォント 666666
KPIカードの構造

カードは、ラベルセルと値セルで構成されます。ラベルは小さめのグレー(font.size=9、font.color=666666、太字)、値は大きな太字(font.size=24、bold=true、numFmt、font.color でトーンを示す)です。カード領域全体に薄い塗りつぶし(例:F0F4FF)を1行入れると、結合セルを使わなくてもカードに見えます。値列の幅は、最も大きな cachedValue に合わせて設定してください。8桁以上の通貨の場合、22より狭くしてはならず、多くは26〜32が必要です(要件を参照)。

タイトル長に基づくチャート幅の目安

dashboard プリセットの既定のタイトルフォントでは、チャートのプロットボックス幅(列単位)がタイトル文字列より大きくなければ、タイトルが単語の途中で切れます。目安は chart.width ≥ ceil(title.length × 0.18) です。35 文字のタイトル("Department: Year-End Headcount vs Attrition Rate")の場合は width ≥ 7 が必要ですが、安全を見て 10〜12 を使用してください。アンカーを広げられない場合は、タイトルを 25 文字以内に短縮してください。報告用の成果物でタイトルが切れているのは許容できません。

officecli get chart[N] は、.data.results[0].format で数値の width(例: width=480pt)と anchor(例: "A6:K21")を返します。どちらも Gate 2 で利用できます。列単位の幅の目安が必要な場合は、アンカーの列文字から列数を求めてください(A→K = 10 列)。

印刷用の納品(board-pack / investor-send / one-pager)

トリガー: 依頼文に "print" / "一页" / "董事会" / "投资人" が含まれる場合。Dashboard シートに 4 つの成果物を配置し、Dashboard 以外のシートは非表示にして、印刷パイプラインが 1 ページだけを出力するようにします。

# 1. Print_Area scoped to Dashboard (xlnm convention).
officecli add "$FILE" / --type namedrange --prop name=_xlnm.Print_Area --prop scope=Dashboard --prop 'refersTo=Dashboard!$A$1:$H$36'
# 2. fit-to-page on Dashboard.
officecli raw-set "$FILE" /Dashboard --xpath "//x:worksheet" --action prepend --xml '<sheetPr xmlns="http://schemas.openxmlformats.org/spreadsheetml/2006/main"><pageSetUpPr fitToPage="1"/></sheetPr>'
# 3. Landscape page setup.
officecli raw-set "$FILE" /Dashboard --xpath "//x:sheetData" --action insertafter --xml '<pageSetup orientation="landscape" paperSize="9" fitToWidth="1" fitToHeight="1"/>'
# 4. Hide non-Dashboard sheets — Print_Area scope alone does NOT stop the print pipeline from emitting every visible sheet.
for S in Sheet1 Summary; do
  officecli raw-set "$FILE" /workbook --xpath "//x:sheet[@name='$S']" --action setattr --xml "state=hidden" || true
done

Data / Summary シートに設定された Print_Area は削除してください。スコープが競合すると複数ページの出力になります。

QA(必須・納品ゲート)

問題があると想定してください。あなたの仕事はそれを見つけることです。 チャートがレンダリングされたことは、そのチャートが意味を持つことを意味しません。「validate pass」は納品ではありません。「Dashboard シートが、業務を理解している人が作ったように読める」状態が納品です。

「完了」前の最小サイクル

xlsx のベースライン(view issues、数式エラーのクエリ、validate、HTML プレビューのスキャン)を継承します:→ officecli-xlsx §QA 最小サイクル を参照。

次に、ダッシュボード固有のデリバリーゲートを実行します。各ゲートは .data.* ラッパーを使った COUNT-then-if パターンを使用します。&& echo OK || echo FAIL のように連結することは決してしないでください。

ゲート 1 — KPI 数式カバレッジ。 計画されたすべての KPI セルに数式が設定されている必要があります。-lt 2 は計画に合わせて調整してください(KPI が 4 つ → -lt 4)。

KPI_FORMULAS=$(officecli query "$FILE" 'Dashboard!:has(formula)' --json | jq '.data.results | length')
[ "$KPI_FORMULAS" -lt 2 ] && { echo "REJECT Gate 1: $KPI_FORMULAS formula cells on Dashboard"; exit 1; }

ゲート 2 — グラフ数が計画と一致し、すべてのグラフにデータがあり、タイトル幅が妥当であること。

CHART_COUNT=$(officecli query "$FILE" chart --json | jq '.data.results | length')
[ "$CHART_COUNT" -lt 1 ] && { echo "REJECT Gate 2: zero charts"; exit 1; }
col_num () { local c=$1 n=0; for ((k=0;k<${#c};k++)); do n=$((n*26+$(printf '%d' "'${c:$k:1}")-64)); done; echo "$n"; }
for i in $(seq 1 "$CHART_COUNT"); do
  JSON=$(officecli get "$FILE" "/Dashboard/chart[$i]" --json)
  SC=$(echo "$JSON" | jq -r '.data.results[0].format.seriesCount // 0')
  TITLE=$(echo "$JSON" | jq -r '.data.results[0].format.title // ""')
  ANCHOR=$(echo "$JSON" | jq -r '.data.results[0].format.anchor // ""')
  [ "$SC" = "0" ] || [ -z "$TITLE" ] && { echo "REJECT Gate 2: chart[$i] seriesCount=$SC title='$TITLE'"; exit 1; }
  [ -z "$ANCHOR" ] && continue
  LCOL=$(echo "${ANCHOR%%:*}" | sed 's/[0-9]*$//'); RCOL=$(echo "${ANCHOR##*:}" | sed 's/[0-9]*$//')
  SPAN=$(( $(col_num "$RCOL") - $(col_num "$LCOL") + 1 ))
  MIN=$(( (${#TITLE} * 18 + 99) / 100 ))
  [ "$SPAN" -lt "$MIN" ] && { echo "REJECT Gate 2: chart[$i] title=${#TITLE} chars needs width ≥ $MIN, anchor spans $SPAN"; exit 1; }
done

プリセット minimal / magazine では、タイトルが幅の狭い状態で 0.18 係数より早く切れる可能性があります。抜き取りで確認してください。

ゲート 3 — グラフの系列名が設定されていること(凡例に「Series1」が出ないこと)。

for i in $(seq 1 "$CHART_COUNT"); do
  BAD=$(officecli get "$FILE" "/Dashboard/chart[$i]" --json | jq '[.data.results[0].children[]? | select(.type == "series") | select((.format.name // "") | test("^Series[0-9]+$"; "i"))] | length')
  [ "$BAD" -gt 0 ] && { echo "REJECT Gate 3: chart[$i] has $BAD auto-named series"; exit 1; }
done

ゲート 4 — Data シートの CF ルール(10 行以上)。

CF_COUNT=$(officecli query "$FILE" conditionalformatting --json | jq '.data.results | length')
[ "$CF_COUNT" -lt 1 ] && { echo "REJECT Gate 4: zero CF rules on 10+ row data sheet"; exit 1; }

注:query conditionalformatting が正式な要素名です。query cf は 0 を返します(エイリアスではありません)。

ゲート 5 — activeTab と fullCalcOnLoad が設定されていること。 実際の Dashboard のインデックスと比較してください(Dashboard がインデックス 0 にある場合は正しく合格です)。

DASH_IDX=$(officecli query "$FILE" sheet --json | jq '[.data.results[].path] | index("/Dashboard")')
ACTIVE=$(officecli get "$FILE" /workbook --json | jq '.data.results[0].format.activeTab // -1')
FULLCALC=$(officecli get "$FILE" /workbook --json | jq -r '.data.results[0].format["calc.fullCalcOnLoad"] // false')
[ "$ACTIVE" != "$DASH_IDX" ] && { echo "REJECT Gate 5: activeTab=$ACTIVE Dashboard=$DASH_IDX"; exit 1; }
[ "$FULLCALC" != "true" ] && { echo "REJECT Gate 5: calc.fullCalcOnLoad=$FULLCALC — stale caches will ship"; exit 1; }

ゲート 6 — プレースホルダーの確認。 レンダリング結果にビルド時のトークンが残っていないこと。

LEAKS=$(officecli view "$FILE" text 2>/dev/null | grep -niE '\{\{|\$fy\$|<TODO>|xxxx|TBD' | wc -l | tr -d ' ')
[ "$LEAKS" -gt 0 ] && { echo "REJECT Gate 6: $LEAKS placeholder tokens"; exit 1; }

ゲート 7 — ビジュアル納品基準(xlsx から移植)。 officecli view "$FILE" html を実行し、返された HTML パスを読み込んでください。以下を確認します:

  • Dashboard・Data のどのセルにも ### が表示されていないこと(列が狭すぎる)。
  • KPI ラベル、シートタブ名、グラフタイトルが切れていないこと。
  • プレースホルダーのトークン($fy$24、{var}、<TODO>、xxxx)がテキストとして表示されていないこと。
  • 円グラフ・ドーナツグラフのスライスが異なる塗りつぶし色で描画されていること(LibreOffice で潰れて見える場合は、壊れていると判断する前にユーザーの対象ビューアーで確認してください → officecli-xlsx §Known Issues/Renderer caveats を参照)。
  • 空のグラフアンカーがないこと。すべてのグラフに表示された妥当なプロットがあること。
  • Dashboard シートが最初に開くこと(タブがハイライトされ、アクティブ領域が先頭にスクロールされていること)。

view html がブロックされている場合(レンダラーの競合、ヘッドレス環境、ポート使用中など)でも、ゲート 7 は必須です。すべてのフォールバックチェックを実行してください:

# a) Token / ### sweep.
officecli view "$FILE" text 2>/dev/null | grep -nE '###|\{\{|<TODO>|\$fy\$|xxxx' && { echo "REJECT Gate 7: tokens or ### present"; exit 1; }
# b) Per-KPI: cachedValue length × coef must fit col width. coef=0.55 fit-to-page, 0.85 otherwise.
for CELL in A2 C2 E2 G2; do
  CV=$(officecli get "$FILE" "/Dashboard/$CELL" --json | jq -r '.data.results[0].format.cachedValue // .data.results[0].text // ""')
  W=$(officecli get "$FILE" "/Dashboard/col[${CELL%%[0-9]*}]" --json | jq -r '.data.results[0].format.width // 0')
  CAP=$(echo "$W * 0.55" | bc -l | awk '{print int($1)}')
  [ "${#CV}" -gt "$CAP" ] && { echo "REJECT Gate 7: $CELL '$CV' (${#CV} chars) > cap $CAP"; exit 1; }
done
# c) Rerun Gate 2 title × 0.18 ≤ anchor span.  d) Log which fallback was used and why.

ゲート 7 は決して省略してはなりません。省略すると、### がユーザーに届いてしまいます。

シーンのキーワードに print / 1ページ / board / 投資家 / 取締役会 が含まれる場合は、ゲート 7 に構造的な印刷範囲チェックを追加してください:

if echo "$USER_REQ" | grep -qiE 'print|一页|投资人|董事会|board'; then
  # Every non-Dashboard sheet must be hidden or veryHidden.
  # query sheet --json carries the name in .preview (no .name/.state); visibility lives in
  # each sheet's own get .format.hidden (absent => visible), so iterate + probe per sheet.
  LEAKING=""
  while IFS=$'\t' read -r SPATH SNAME; do
    [ "$SNAME" = "Dashboard" ] && continue
    HIDDEN=$(officecli get "$FILE" "$SPATH" --json | jq -r '.data.results[0].format.hidden // false')
    [ "$HIDDEN" != "true" ] && LEAKING="$LEAKING $SNAME"
  done < <(officecli query "$FILE" 'sheet' --json | jq -r '.data.results[] | [.path, .preview] | @tsv')
  [ -n "$LEAKING" ] && { echo "REJECT Gate 7 print-scope: visible non-Dashboard sheet(s):$LEAKING — hide before delivery"; exit 1; }
  # Dashboard must carry an explicit Print_Area named range.
  PA=$(officecli query "$FILE" 'namedrange[name="_xlnm.Print_Area"]' --json | jq '.data.results | length')
  [ "$PA" -ge 1 ] || { echo "REJECT Gate 7 print-scope: no _xlnm.Print_Area set"; exit 1; }
fi

最終的な印刷プレビューは、ユーザーが対象ビューアー(Office / WPS / Numbers)でファイルを開いて確認します。このスキルはエクスポート成果物をレンダリングしません。

ゲート 8 — 数式の妥当性(cachedValue が古い値やエラーではなく実際の値であること)。 fullCalcOnLoad=true が更新するのは実行時であり、ビルド時のキャッシュではありません。そのため、すべての数式セルは今この時点で、空でなく、ゼロでなく、エラーでもない cachedValue を持っている必要があります。

for CELL in A2 C2 E2 G2; do
  JSON=$(officecli get "$FILE" "/Dashboard/$CELL" --json)
  [ -z "$(echo "$JSON" | jq -r '.data.results[0].format.formula // ""')" ] && continue
  CV=$(echo "$JSON" | jq -r '.data.results[0].format.cachedValue // ""')
  case "$CV" in
    "" | "0" | "#DIV/0!" | "#REF!" | "#N/A" | "#VALUE!" | "#NAME?" | "null")
      echo "REJECT Gate 8: $CELL cachedValue='$CV' — re-issue formula or close+reopen"; exit 1 ;;
  esac
done

KPI が本当にゼロである場合(例:「今四半期の解約数」= 0)は、ループ内でホワイトリストに登録し、文書化してください。デフォルトの前提は「ゼロは壊れている」です。

いずれかが失敗した場合は、ソースで修正し、サイクル全体を再実行してください。

既知の制約

散布図は series1.xValues を受け付けません(非対応)。X 軸は categories / series1.categories で指定してください。LibreOffice でのグラフ色のずれ、円グラフのスライスの潰れ、チェックボックスの二重枠はビューアーによるアーティファクトです。まず Office / WPS / Numbers で抜き取り確認してください。

リファレンス

  • add 時の --type の省略形: chart、sparkline、databar、colorscale、iconset、formulacf。CF ルールは help xlsx conditionalformatting に対応し、パスのサフィックスは /Sheet/cf[N] です。
  • 完全なスキーマはヘルプにあります: officecli help xlsx chart / sparkline / conditionalformatting。このスキルではスキーマを複製していません。
  • DeferredAddKeys(add のみ): combosplit、holesize。D-1 を参照。(preset、trendline、referenceline、axisNumFmt は現在 set でも使用できます。ヘルプには [add/set] と表示されます。)
  • ビルド順序: まずグラフ・スパークライン・CF・tabColors → 高レベルの set で calc.fullCalcOnLoad=true → raw-set activeTab を最後に実行(すべてのシートが存在した後)。

既知の問題と落とし穴

Dashboard 固有
#IssueMitigation
D-1combosplit は DeferredAddKey であり、add 時のみ機能します。(preset、referenceline、trendline、axisNumFmt は現在 set でも適用されます。ヘルプには [add/set] と表示されます。)add 時に combosplit を設定してください。作成後に適用することはできません。削除して再追加してください。他の 4 つは作成後に set で適用または変更できます。
D-2referenceline の形式は value:color:label:dash です(color が label の前に来ます)。"0:Break-Even:FF0000:dash" は Invalid color value で失敗します。順序は value、color、label、dash です。
D-3散布図は series1.xValues を受け付けません(UNSUPPORTED)。x 軸は categories / series1.categories を通して指定してください。--prop series1.categories="Sheet1!A2:A13"(または --prop categories="Sheet1!A2:A13")
D-4formulacf は font.bold / font.italic を扱います(dxf フォントに書き込まれ、読み戻し時にも反映されます)。fill および font.color も同様です。CF ルールを指定するには fill / font.color / font.bold / font.italic のいずれかを使用してください。
D-5ダッシュボードの列幅はデフォルトで 8.43 です。24pt 太字の KPI 値は ### と表示されます。cachedValue の桁数で決めてください。4〜6 桁 → 22〜24、7〜9 桁(百万)→ 26〜30、10 桁以上(亿 / billion)→ 32〜36、百亿 / 10 桁 + 通貨記号 + 用紙に合わせた横向き印刷 → 40〜44。式 ceil((visible_chars+2)*1.3) は出発点として使えます。必ず Gate 7 のフォールバック b) で検証してください。スパークラインの列は 12 にしてください。
D-6raw-set activeTab は最後に行う変更でなければなりません。すべてのシートが存在する前に挿入するとインデックスがずれます。すべてのシート / チャート / CF / スパークライン / tabColors を完成させてから raw-set を実行してください。
D-7raw-set で calc.fullCalcOnLoad を設定すると重複した <calcPr> が作成され、validate が失敗します。officecli set "$FILE" / --prop calc.fullCalcOnLoad=true を使用してください。
D-8LibreOffice は描画時に非表示列の数式を評価しないため、非表示セルを参照するチャートは空白で描画されます。表示用の Summary シートに集計し、チャートは Summary から読み取るようにしてください。チャートのソースではない列だけを非表示にしてください。
D-9chartType=pie は LibreOffice で空白に描画されます。全体に対する内訳を示す場合は、安全な代替として doughnut を使用してください。
D-10日付条件を含む SUMIFS / AVERAGEIFS は、条件が文字列の場合にエラーなく失敗します。DATE() または DATEVALUE() で囲んでください:=SUMIFS(B2:B13,A2:A13,DATE(2025,1,5))。
D-11numFmt を指定しないと、Summary シートのパーセント数式が生の小数(0.098)として表示されます。数式を設定するのと同じ set 呼び出しで numFmt="0.0%" を設定してください。
D-12import --header は freeze と AutoFilter を設定しますが、列幅は設定しません。col[] で列幅を設定してください。col[] パスに対する numFmt は、現在は列レベルのスタイル(<col s=...>、スキーマに適合し、numberformat として読み戻されます)を適用します。その列の空白セルに書式が適用されます。個別のスタイルを持つセルには、セル範囲ごとの numFmt が引き続き必要です。
D-13スパークラインの highpoint は色ではなく bool 値(ハイライトの有効 / 無効)です。--prop highpoint=FF0000 は Invalid boolean value エラーになります。--prop highPoint=true --prop highMarkerColor=FF0000 を使用してください。lowPoint / firstPoint / lastPoint およびそれぞれの *MarkerColor も同じパターンです。
D-14横断的なデータ(地域や部署など)には順序がないため、スパークラインは意味を持ちません。行が連続した時系列(日付、月、四半期)である場合にのみスパークラインを使用してください。そうでなければ省略してください。
D-15空のチャートの add は CLI 層で拒否されます(Chart requires a 'data' property)。エラーを出さずに受け付けていた旧来のスキルはここで失敗します。チャートの add 時には必ず series1.values= / dataRange= / インライン data= のいずれかを指定してください。Gate 2 の seriesCount チェックは、二重の検証として扱ってください。
D-16fullCalcOnLoad=true は、エンドユーザーがファイルを開いたときに実行時の再計算を保証しますが、XML 内のビルド時の cachedValue は更新しません。set B=100 → set E==B+D → fix B=150 というビルド手順では、E.cachedValue が古いままになります(ボードには「Net Change = 0」と表示されます)。上流の編集がすべて確定したら、後続のすべての数式を再設定するか(officecli set "$FILE" /Sheet/E2 --prop formula==B2+D2)、close してからファイルを開き直してください。Gate 8 で検証されます。
D-17組み込みの計算エンジンは、配列条件の形式 SUMPRODUCT((A2:A97=X)*C2:C97*D2:D97) の SUMPRODUCT を評価しません。cachedValue は 0 / null のままとなり、Gate 8 で拒否されます。実行時の Excel / WPS では正しく計算されますが、古いキャッシュを持つ XLSX をボードに納品すると 0 が表示されたままになります。ヘルパー列と SUMIF に書き換えてください。ソースシートで F2==C2*D2 とし、=SUMIF(B:B, "Region X", F:F) を使用します。または Summary シートで事前に集計し、そこからチャートを作成してください。
継承(ポインターのみ)

シート間の ! 参照の落とし穴、およびチャートの anchor / 作成後のシリーズの変更不可という制約については、officecli-xlsx の §Known Issues を参照してください。

コメント