0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

rex0220 kSQL Dashboard Pro デモ ④ マークダウン — 数字を、文章に埋める

0
Posted at

数字だけのダッシュボードは、読む人によって解釈が変わります。「1,247 件」が多いのか少ないのか、何を含んで何を含まないのか。それを書いておく場所がマークダウンペインです。

kSQL Dashboard Pro の 4 つの表示タイプのうち、マークダウンだけは SQL が任意です。書かなければクエリを実行せずに描画し、書けば {{列名}} が値に置き換わります。

この記事では SQL・本文・表示結果を 1 セットにして、5 つの使い方を作ります。

kSQL Dashboard Pro デモ(全 5 回)
⓪ 準備編 / ① KPI カード / ② データ表 / ③ グラフ / ④ マークダウン(この記事)

**アプリの用意は ⓪ 準備編**にまとめてあります(5 本とも同じアプリを使います)。

この連載で作るダッシュボードの全体(KPI・マークダウン・グラフ・表)


前提

項目 本記事の前提
プラグイン kSQL Dashboard Pro Ver.1
SQL エンジン kintone-sql-tools 3.66.1 系
kintone 公式対応ブラウザの最新版(PC)。モバイルは対象外
対象アプリ 売上明細(約 1,500 件)

アプリの作り方とデータの入れ方は ⓪ 準備編にまとめてあります。 この記事は売上明細 1 本だけで完結します。

ペインを追加したら、表示タイプは「マークダウン」を選びます。設定欄は 3 つです。

設定画面の欄 役割
マークダウン 本文。ここが主役
埋め込み用 SQL(任意) 空でよい。書くと {{列名}} が使える
文字サイズ 小 / 標準 / 大 / 特大

① SQL を書かない — 見出しと注記

いちばん軽い使い方です。SQL が空なら、クエリは 1 本も飛びません。

## 売上ダッシュボード

数字は「確定」のみを集計しています(保留・取消は含みません)。**SQL を書かなければクエリは実行されません** — 見出しや注記だけを置くなら、この形がいちばん軽い。

文字サイズは「」にしています。

「売上ダッシュボード」の見出し帯

ダッシュボードの一番上に置いて、集計の前提を書く用途がよく効きます。「確定のみ」「税抜」「本社を除く」— これを書いておかないと、数字を見た人が必ず一度は聞いてきます。

ペインの見出しを空にすると、本文だけが出て帯のように使えます。この例も見出しは空です。


② 数字を文章に埋め込む

SQL を書くと、本文の {{列名}}結果の 1 行目に置き換わります。

SELECT
  FORMAT(COUNT(*), '#,##0') AS 件数,
  FORMAT(ROUND(SUM(金額) / 10000), '#,##0') AS 売上万,
  FORMAT(ROUND(AVG(金額)), '#,##0') AS 平均単価,
  DATE_FORMAT(CURRENT_DATE(), '%Y年%c月') AS 対象月
FROM APP4239
WHERE 売上日 = THIS_MONTH() AND 売上ステータス = '確定'
### {{対象月}} の実績

- 確定 **{{件数}}** 件 / **{{売上万}}** 万円
- 1 件あたり **{{平均単価}}**

数字を文章に埋め込む

桁区切りは SQL 側で作ります。埋め込み値に数値書式(表示スケール・単位・桁区切り)は効きません。KPI カードや表と違い、マークダウンの値は文字列としてそのまま差し込まれるからです。FORMAT(値, '#,##0') を使ってください。

%c先頭の 0 を付けない月です。%m だと「2026年08月」になります。

結果は 1 行目だけ

2 行目以降は使われません。埋め込みは「1 行に畳んだ結果を文章に差す」ための機能なので、GROUP BY を書いた複数行の結果を渡しても、先頭 1 行しか出ません。

一覧にしたいならデータ表、1 つの数字を大きく見せたいなら KPI カードです。


③ 0 件のときの案内 — 文言を SQL で作る

COUNT(*) は対象が 0 件でも 1 行返ります。 だから CASE で文言そのものを切り替えられます。

SELECT COUNT(*) AS 件数,
  CASE WHEN COUNT(*) = 0
       THEN '今月の「取消」はありません。'
       ELSE CONCAT('今月の「取消」が ', FORMAT(COUNT(*), '#,##0'), ' 件あります。内容を確認してください。')
  END AS 案内
FROM APP4239
WHERE 売上日 = THIS_MONTH() AND 売上ステータス = '取消'
### 今月の確認事項

{{案内}}

<span style="color:#c0392b;font-weight:bold">該当 {{rowCount}} 行</span> — 行数は予約名 `rowCount` で取り出せます。

> **未定義の列と空の値は `-` になります。** 文言を SQL の `CASE` で作れば、0 件でも意味のある一文を出せます。

0 件のときの案内

{{rowCount}} は予約名で、結果の行数が入ります。SQL を書いていれば列を作らなくても使えます。

同じ名前の列があれば、列のほうが勝ちます。SELECT COUNT(*) AS rowCount と書いた人はその値を出したいはずで、行数(1 行の結果なので必ず 1)で上書きすると、黙って違う数字が出ます。

未定義と空値は -

{{存在しない列}}- になります。空欄でも、{{ }} がそのまま残るのでもありません。

これを踏まえた書き方が上の CASE です。0 件のとき 案内 列が空になる書き方をすると本文が「-」になってしまうので、0 件でも文字列を返すようにしています。


④ 運用の手順とリンク集

SQL の要らない用途をもう 1 つ。

### 月次の締め手順

1. 「保留」の伝票を確認して確定または取消にする
2. 取消の理由を伝票番号ごとに記録する
3. 月次目標アプリへ翌月の目標を登録する

**参照**: [kSQL 言語リファレンス](https://qiita.com/rex0220/items/e089fddf4229d74be699) / [プラグイン](https://qiita.com/rex0220/items/9c7a5a2aea28198c438b)

運用の手順とリンク集

手順やリンクを一覧に置いておくと、画面から離れずに済みます。マニュアルを別の場所に置くと、まず読まれません。

リンクには target="_blank"rel="noopener noreferrer" が強制的に付きます。 一覧を開いたまま別タブで開くのが常に正しい挙動なので、指定は要りません。


⑤ 書ける書式と、除去されるもの

| 書ける | 例 |
| :--- | :--- |
| 見出し・箇条書き・表 | この表そのもの |
| 強調 | **太字** / *斜体* / `コード` |
| 装飾つき HTML | <span style="color:#2e86c1"></span> / <span style="background-color:#f9e79f">背景</span> |

書式と、除去されるもの

GFM(GitHub Flavored Markdown)です。表・打ち消し線・自動リンクが使えます。単独の改行はそのまま改行になります(行末に空白 2 つは要りません)。

除去されるもの

分類
危険タグ script / iframe / object / embed / form / input / button / style
イベント属性 onclick / onerror / onload
style のレイアウト系 position / display / z-index / opacity
style の外部参照 url(...) / expression / javascript:

style装飾系だけ通ります — color background-color text-align font-size font-weight font-style text-decoration border border-radius padding margin

レイアウト系を落としているのは、偽の UI を重ねられるからです。position: fixedz-index があれば、本物のボタンの上に偽のボタンを置けます。装飾に必要な範囲だけを通しています。


置換の仕組み

これを知っていると、後で説明する制約が全部つながります。

大事なのは、置換がいちばん先だということです。マークダウンとして解釈する前の、ただの文字列の段階で差し替えます。

そのうえで、差し込む値は必ずエスケープされます。* _ # | < > などは記号のまま表示され、記法としては働きません。データに # 見出し という文字列が入っていても、見出しにはなりません。

値の中の改行は空白 1 つに潰されます。 潰さないと、続く文字が行頭に来て箇条書きや見出しが生えます。埋め込みは文中の差し込みなので、1 行に流すのが本来の姿です。


つまずきポイント

本文に {{列名}} の記法そのものを書けない

置換はマークダウンとして解釈する前に効きます。コードブロックやバッククォートの中に書いても関係ありません。説明のつもりで書くと、-(未定義)か値に置き換わります。

これはこの記事を書いていて実際に踏みました。 この記事の本文で記法を見せられているのは、Qiita 側の文章だからです。ペインの本文には書けません。

回避したいときは、{ を全角にするか、&#123;&#123;列名&#125;&#125; のように数値文字参照で書きます。

桁区切りが出ない

埋め込み値に数値書式は効きません。FORMAT(値, '#,##0') を SQL 側で使います。

- が出る

列名の綴り違い、値が空、または AS を付け忘れています。SQL の結果 1 行目にその名前の列が実在するかを確かめてください。

{{rowCount}} が 1 になる

rowCount という名前の列を SQL で作っています。列のほうが優先されます。別名にしてください。

色を付けたのに反映されない

style装飾系プロパティ以外は落ちますposition display z-index opacity は通りません。


4 つの型の使い分け

連載の最後なので、ここまでの 4 本をまとめます。

見せたいもの 設定画面の表示タイプ
数字 1 つ(前月比・目標比つき) KPI カード KPI カード
明細・ランキング・集計表 データ表
推移・構成比・内訳 グラフ 棒 / 折れ線 / 円 ほか 9 種
前提・手順・0 件の案内 マークダウン マークダウン

マークダウンは、ほかの 3 つが答えられない問いに答えます。「この数字は何を含んでいるのか」「これを見たら次に何をするのか」。数字を並べるだけでは伝わらないところです。


まとめ

  1. SQL は任意 — 見出し・注記・手順だけなら空でよい。クエリは飛ばない
  2. {{列名}} は結果の 1 行目。桁区切りは FORMAT で SQL 側に作る
  3. 未定義と空は -。0 件でも意味のある文を出したいなら CASE で文言ごと作る
  4. 置換が先、解釈が後。だから値は安全で、だから記法そのものは本文に書けない

関連記事


付録 — 配布ファイル

GitHub に一式を置いています

アプリテンプレート・データ投入スクリプト・設定 JSON をまとめてあります。

https://github.com/rex0220/ksql-dashboard-pro-demo

設定はまとめて 1 回で取り込めます。 settings/型別-全一覧-見本.json に 5 一覧・43 ペイン(連載 4 本ぶん + 4 型を組み合わせた見本)が入っています。この記事のぶんだけでよければ、下の JSON を使ってください。

**アプリの用意とデータの入れ方は ⓪ 準備編**にまとめてあります。4 本とも同じアプリを使うので、一度作れば全部動きます。

設定 JSON(この記事の 5 ペイン)

GitHub の settings/型別-マークダウン-見本.json と同じものです。コピーして使えるよう全文を貼ります。

  1. 折りたたみを開き、コードブロック右上のコピーボタンでコピー
  2. テキストエディター(メモ帳等)に貼り付け、型別-マークダウン-見本.json として保存(文字コード UTF-8)
  3. 設定画面の ツール → インポート でそのファイルを選択

SQL 中の APP4239 などは、取り込み時の確認ダイアログ「アプリ番号の変換」でご自身の環境の番号へ変換できます(JSON を手で書き換える必要はありません)。

型別-マークダウン-見本.json — 5 ペイン
{
  "date": "2026-08-15 00:00:00",
  "pluginName": "kSQL Dashboard Pro",
  "pluginVersion": "1",
  "engineVersion": "3.66.1",
  "appId": 4239,
  "appName": "売上明細",
  "sqlApps": [
    {
      "appId": 4239,
      "appName": "売上明細"
    }
  ],
  "config": {
    "schemaVersion": 2,
    "edition": "pro",
    "views": {
      "13335810": {
        "name": "マークダウンの見本",
        "viewName": "【型別】マークダウン",
        "layout": [
          {
            "i": "pane1",
            "x": 0,
            "y": 0,
            "w": 60,
            "h": 3
          },
          {
            "i": "pane2",
            "x": 0,
            "y": 3,
            "w": 30,
            "h": 4
          },
          {
            "i": "pane3",
            "x": 30,
            "y": 3,
            "w": 30,
            "h": 4
          },
          {
            "i": "pane4",
            "x": 0,
            "y": 7,
            "w": 30,
            "h": 6
          },
          {
            "i": "pane5",
            "x": 30,
            "y": 7,
            "w": 30,
            "h": 6
          }
        ],
        "panes": [
          {
            "id": "pane1",
            "type": "markdown",
            "title": "",
            "sql": "",
            "options": {
              "fontSize": "large",
              "markdown": "## 売上ダッシュボード\n\n数字は「確定」のみを集計しています(保留・取消は含みません)。**SQL を書かなければクエリは実行されません** — 見出しや注記だけを置くなら、この形がいちばん軽い。"
            }
          },
          {
            "id": "pane2",
            "type": "markdown",
            "title": "数字を文章に埋め込む",
            "sql": "/* 埋め込み値に数値書式は効かない。桁区切りは SQL 側で作る */\nSELECT\n  FORMAT(COUNT(*), '#,##0') AS 件数,\n  FORMAT(ROUND(SUM(金額) / 10000), '#,##0') AS 売上万,\n  FORMAT(ROUND(AVG(金額)), '#,##0') AS 平均単価,\n  DATE_FORMAT(CURRENT_DATE(), '%Y年%c月') AS 対象月\nFROM APP4239\nWHERE 売上日 = THIS_MONTH() AND 売上ステータス = '確定'",
            "options": {
              "markdown": "### {{対象月}} の実績\n\n- 確定 **{{件数}}** 件 / **{{売上万}}** 万円\n- 1 件あたり **{{平均単価}}** 円\n\n二重波かっこで囲んだ列名が、**結果の 1 行目**に置き換わります(2 行目以降は使われません)。\n**本文に記法そのものは書けません** — 置換の対象になるためです。"
            }
          },
          {
            "id": "pane3",
            "type": "markdown",
            "title": "0 件のときの案内",
            "sql": "/* COUNT(*) は対象が 0 件でも 1 行返る。だから CASE で文言を切り替えられる。\n   0 件だと 案内 列そのものが無くなり、埋め込みは - になる(空欄でも {{ }} でもない) */\nSELECT COUNT(*) AS 件数,\n  CASE WHEN COUNT(*) = 0\n       THEN '今月の「取消」はありません。'\n       ELSE CONCAT('今月の「取消」が ', FORMAT(COUNT(*), '#,##0'), ' 件あります。内容を確認してください。')\n  END AS 案内\nFROM APP4239\nWHERE 売上日 = THIS_MONTH() AND 売上ステータス = '取消'",
            "options": {
              "markdown": "### 今月の確認事項\n\n{{案内}}\n\n<span style=\"color:#c0392b;font-weight:bold\">該当 {{rowCount}} 行</span> — 行数は予約名 `rowCount` で取り出せます。\n\n> **未定義の列と空の値は `-` になります。** 文言を SQL の `CASE` で作れば、0 件でも意味のある一文を出せます。"
            }
          },
          {
            "id": "pane4",
            "type": "markdown",
            "title": "運用の手順とリンク集",
            "sql": "",
            "options": {
              "markdown": "### 月次の締め手順\n\n1. 「保留」の伝票を確認して確定または取消にする\n2. 取消の理由を伝票番号ごとに記録する\n3. 月次目標アプリへ翌月の目標を登録する\n\n**参照**: [kSQL 言語リファレンス](https://qiita.com/rex0220/items/e089fddf4229d74be699) / [プラグイン](https://qiita.com/rex0220/items/9c7a5a2aea28198c438b)\n\n手順やリンクを置いておくと、**一覧から離れずに済みます。**"
            }
          },
          {
            "id": "pane5",
            "type": "markdown",
            "title": "書式と、除去されるもの",
            "sql": "",
            "options": {
              "markdown": "| 書ける | 例 |\n| :--- | :--- |\n| 見出し・箇条書き・表 | この表そのもの |\n| 強調 | **太字** / *斜体* / `コード` |\n| 装飾つき HTML | <span style=\"color:#2e86c1\">色</span> / <span style=\"background-color:#f9e79f\">背景</span> |\n\n**除去されるもの**: `script` / `iframe` などの危険タグ、`onclick` のようなイベント属性。リンクには `rel=\"noopener noreferrer\"` が強制されます。`style` は装飾系だけ通ります。"
            }
          }
        ]
      }
    },
    "common": {}
  }
}
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?