Statement report
Build a report that summarises a month of activity. You use line, pie and donut charts in one document, and learn number formatting and automatic height.
このレシピで身につくこと
エディタで作る
- Add a chart and set it to line. Three values are all it needs: the array path, the label expression and the value expression.
- Add two more charts as pie and donut. They read the same array in a different shape, so the value expression stays the same.
- Pie and donut show proportions. Past about eight slices they become unreadable, so switch to bar at that point.
- Write the summary figures as labels: {{ format(sum(data.daily, "amount"), "number", "0,0", "en-US") }} can never disagree with the table.
スキーマと API で作る
- A chart picks its kind with chartKind: "bar" (the default), "line", "pie" or "donut".
- The data shape is the table one: bind is the array, columns[0].cell is the label expression and columns[1].cell is the value expression. chartKind is the only new key.
- A value expression that is not a number contributes 0. It is the same reason currency formatting shows NaN for a string — send numbers.
- format(value, "number", "0,0", locale) adds thousand separators. Leaving the pattern empty defaults to 0,0.
出来上がったドキュメント
下の JSON は、2 つの道筋が生むドキュメントそのものです。テストがこれを検証し、警告なしでレンダリングされることも確認しているので、そのまま貼り付けてお使いいただけます。
{
"v": 1,
"unit": "px",
"page": {
"size": "a4",
"orientation": "portrait",
"margin": {
"t": 48,
"r": 48,
"b": 56,
"l": 48
},
"header": "{{ data.company }} · {{ data.period }}",
"footer": "[[page]] / [[pages]]"
},
"fonts": [],
"styles": [
{
"id": "s_h1",
"fontFamily": "Liberation Sans",
"fontSize": 22,
"fontWeight": 700,
"italic": false,
"color": "#111111",
"bg": "transparent",
"align": "left",
"valign": "top",
"lineHeight": 1.5,
"border": "none",
"radius": 0,
"opacity": 1
},
{
"id": "s_l",
"fontFamily": "Liberation Sans",
"fontSize": 12,
"fontWeight": 400,
"italic": false,
"color": "#333333",
"bg": "transparent",
"align": "left",
"valign": "top",
"lineHeight": 1.5,
"border": "none",
"radius": 0,
"opacity": 1
},
{
"id": "s_big",
"fontFamily": "Liberation Sans",
"fontSize": 28,
"fontWeight": 700,
"italic": false,
"color": "#111111",
"bg": "transparent",
"align": "left",
"valign": "top",
"lineHeight": 1.5,
"border": "none",
"radius": 0,
"opacity": 1
},
{
"id": "s_cap",
"fontFamily": "Liberation Sans",
"fontSize": 11,
"fontWeight": 400,
"italic": false,
"color": "#666666",
"bg": "transparent",
"align": "left",
"valign": "top",
"lineHeight": 1.5,
"border": "none",
"radius": 0,
"opacity": 1
}
],
"nodes": [
{
"id": "n_title",
"parent": "",
"order": 0,
"type": "label",
"x": 0,
"y": 0,
"w": 697,
"h": 28,
"show": "",
"styleId": "s_h1",
"props": {
"text": "Monthly statement",
"src": "",
"fit": "",
"thickness": 0,
"stroke": "",
"fill": "",
"repeat": "",
"as": "",
"break": "",
"keep": "",
"padding": 0,
"padY": 0,
"padX": 0,
"align": "",
"valign": "",
"wrap": "",
"bind": "",
"headerHeight": 0,
"rowHeight": 0,
"max": 0,
"columns": [],
"rows": 0,
"cells": [],
"chartKind": "",
"codeKind": "",
"ecc": "",
"fieldKind": "",
"fieldName": "",
"options": [],
"required": false,
"readonly": false,
"html": ""
},
"name": "Title"
},
{
"id": "n_sum",
"parent": "",
"order": 1,
"type": "label",
"x": 0,
"y": 40,
"w": 340,
"h": 36,
"show": "",
"styleId": "s_big",
"props": {
"text": "{{ format(sum(data.daily, \"amount\"), \"number\", \"0,0\", \"en-US\") }}",
"src": "",
"fit": "",
"thickness": 0,
"stroke": "",
"fill": "",
"repeat": "",
"as": "",
"break": "",
"keep": "",
"padding": 0,
"padY": 0,
"padX": 0,
"align": "",
"valign": "",
"wrap": "",
"bind": "",
"headerHeight": 0,
"rowHeight": 0,
"max": 0,
"columns": [],
"rows": 0,
"cells": [],
"chartKind": "",
"codeKind": "",
"ecc": "",
"fieldKind": "",
"fieldName": "",
"options": [],
"required": false,
"readonly": false,
"html": ""
},
"name": "Total"
},
{
"id": "n_sum_l",
"parent": "",
"order": 2,
"type": "label",
"x": 0,
"y": 78,
"w": 340,
"h": 0,
"show": "",
"styleId": "s_cap",
"props": {
"text": "Total this month",
"src": "",
"fit": "",
"thickness": 0,
"stroke": "",
"fill": "",
"repeat": "",
"as": "",
"break": "",
"keep": "",
"padding": 0,
"padY": 0,
"padX": 0,
"align": "",
"valign": "",
"wrap": "",
"bind": "",
"headerHeight": 0,
"rowHeight": 0,
"max": 0,
"columns": [],
"rows": 0,
"cells": [],
"chartKind": "",
"codeKind": "",
"ecc": "",
"fieldKind": "",
"fieldName": "",
"options": [],
"required": false,
"readonly": false,
"html": ""
},
"name": "Total caption"
},
{
"id": "n_line_l",
"parent": "",
"order": 3,
"type": "label",
"x": 0,
"y": 116,
"w": 697,
"h": 18,
"show": "",
"styleId": "s_l",
"props": {
"text": "Daily amount",
"src": "",
"fit": "",
"thickness": 0,
"stroke": "",
"fill": "",
"repeat": "",
"as": "",
"break": "",
"keep": "",
"padding": 0,
"padY": 0,
"padX": 0,
"align": "",
"valign": "",
"wrap": "",
"bind": "",
"headerHeight": 0,
"rowHeight": 0,
"max": 0,
"columns": [],
"rows": 0,
"cells": [],
"chartKind": "",
"codeKind": "",
"ecc": "",
"fieldKind": "",
"fieldName": "",
"options": [],
"required": false,
"readonly": false,
"html": ""
},
"name": "Line heading"
},
{
"id": "n_line",
"parent": "",
"order": 4,
"type": "chart",
"x": 0,
"y": 140,
"w": 697,
"h": 200,
"show": "",
"styleId": "s_l",
"props": {
"text": "",
"src": "",
"fit": "",
"thickness": 0,
"stroke": "",
"fill": "",
"repeat": "",
"as": "",
"break": "",
"keep": "",
"padding": 0,
"padY": 0,
"padX": 0,
"align": "",
"valign": "",
"wrap": "",
"bind": "data.daily",
"headerHeight": 0,
"rowHeight": 0,
"max": 0,
"columns": [
{
"header": "Day",
"cell": "{{ item.day }}",
"width": 0,
"align": "left"
},
{
"header": "Amount",
"cell": "{{ item.amount }}",
"width": 0,
"align": "right"
}
],
"rows": 0,
"cells": [],
"chartKind": "line",
"codeKind": "",
"ecc": "",
"fieldKind": "",
"fieldName": "",
"options": [],
"required": false,
"readonly": false,
"html": ""
},
"name": "Daily trend"
},
{
"id": "n_pie_l",
"parent": "",
"order": 5,
"type": "label",
"x": 0,
"y": 364,
"w": 340,
"h": 18,
"show": "",
"styleId": "s_l",
"props": {
"text": "Share by product group",
"src": "",
"fit": "",
"thickness": 0,
"stroke": "",
"fill": "",
"repeat": "",
"as": "",
"break": "",
"keep": "",
"padding": 0,
"padY": 0,
"padX": 0,
"align": "",
"valign": "",
"wrap": "",
"bind": "",
"headerHeight": 0,
"rowHeight": 0,
"max": 0,
"columns": [],
"rows": 0,
"cells": [],
"chartKind": "",
"codeKind": "",
"ecc": "",
"fieldKind": "",
"fieldName": "",
"options": [],
"required": false,
"readonly": false,
"html": ""
},
"name": "Pie heading"
},
{
"id": "n_pie",
"parent": "",
"order": 6,
"type": "chart",
"x": 0,
"y": 388,
"w": 340,
"h": 220,
"show": "",
"styleId": "s_l",
"props": {
"text": "",
"src": "",
"fit": "",
"thickness": 0,
"stroke": "",
"fill": "",
"repeat": "",
"as": "",
"break": "",
"keep": "",
"padding": 0,
"padY": 0,
"padX": 0,
"align": "",
"valign": "",
"wrap": "",
"bind": "data.mix",
"headerHeight": 0,
"rowHeight": 0,
"max": 0,
"columns": [
{
"header": "Group",
"cell": "{{ item.name }}",
"width": 0,
"align": "left"
},
{
"header": "Amount",
"cell": "{{ item.amount }}",
"width": 0,
"align": "right"
}
],
"rows": 0,
"cells": [],
"chartKind": "pie",
"codeKind": "",
"ecc": "",
"fieldKind": "",
"fieldName": "",
"options": [],
"required": false,
"readonly": false,
"html": ""
},
"name": "Share pie"
},
{
"id": "n_donut_l",
"parent": "",
"order": 7,
"type": "label",
"x": 357,
"y": 364,
"w": 340,
"h": 18,
"show": "",
"styleId": "s_l",
"props": {
"text": "Share by channel",
"src": "",
"fit": "",
"thickness": 0,
"stroke": "",
"fill": "",
"repeat": "",
"as": "",
"break": "",
"keep": "",
"padding": 0,
"padY": 0,
"padX": 0,
"align": "",
"valign": "",
"wrap": "",
"bind": "",
"headerHeight": 0,
"rowHeight": 0,
"max": 0,
"columns": [],
"rows": 0,
"cells": [],
"chartKind": "",
"codeKind": "",
"ecc": "",
"fieldKind": "",
"fieldName": "",
"options": [],
"required": false,
"readonly": false,
"html": ""
},
"name": "Donut heading"
},
{
"id": "n_donut",
"parent": "",
"order": 8,
"type": "chart",
"x": 357,
"y": 388,
"w": 340,
"h": 220,
"show": "",
"styleId": "s_l",
"props": {
"text": "",
"src": "",
"fit": "",
"thickness": 0,
"stroke": "",
"fill": "",
"repeat": "",
"as": "",
"break": "",
"keep": "",
"padding": 0,
"padY": 0,
"padX": 0,
"align": "",
"valign": "",
"wrap": "",
"bind": "data.channel",
"headerHeight": 0,
"rowHeight": 0,
"max": 0,
"columns": [
{
"header": "Channel",
"cell": "{{ item.name }}",
"width": 0,
"align": "left"
},
{
"header": "Amount",
"cell": "{{ item.amount }}",
"width": 0,
"align": "right"
}
],
"rows": 0,
"cells": [],
"chartKind": "donut",
"codeKind": "",
"ecc": "",
"fieldKind": "",
"fieldName": "",
"options": [],
"required": false,
"readonly": false,
"html": ""
},
"name": "Share donut"
}
]
}リクエストの本文です。上のドキュメントを template に、下のデータを data に入れてください。
{
"template": "(the document above)",
"data": {
"company": "brewmypdf",
"period": "2026-08",
"daily": [
{
"day": "1",
"amount": 1200
},
{
"day": "8",
"amount": 1850
},
{
"day": "15",
"amount": 1400
},
{
"day": "22",
"amount": 2100
},
{
"day": "29",
"amount": 1650
}
],
"mix": [
{
"name": "Subscription",
"amount": 4200
},
{
"name": "One-off",
"amount": 2600
},
{
"name": "Consulting",
"amount": 1400
}
],
"channel": [
{
"name": "Direct",
"amount": 5100
},
{
"name": "Partner",
"amount": 3100
}
]
}
}