このドキュメントはまだご利用の言語に翻訳されていないため、英語で表示しています。製品の画面は翻訳済みです。

← All recipes

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.

このテンプレートを取り込む

What this teaches

  • chart-line
  • chart-pie
  • chart-donut
  • expr-format-number
  • node-autoheight

Building it in the editor

  1. Add a chart and set it to line. Three values are all it needs: the array path, the label expression and the value expression.
  2. Add two more charts as pie and donut. They read the same array in a different shape, so the value expression stays the same.
  3. Pie and donut show proportions. Past about eight slices they become unreadable, so switch to bar at that point.
  4. Write the summary figures as labels: {{ format(sum(data.daily, "amount"), "number", "0,0", "en-US") }} can never disagree with the table.

Building it with the schema and API

  1. A chart picks its kind with chartKind: "bar" (the default), "line", "pie" or "donut".
  2. 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.
  3. A value expression that is not a number contributes 0. It is the same reason currency formatting shows NaN for a string — send numbers.
  4. format(value, "number", "0,0", locale) adds thousand separators. Leaving the pattern empty defaults to 0,0.

The finished document

The JSON below is exactly the document those two routes produce. Our tests validate it and check that it renders without warnings, so you can paste it and use it as is.

EXAMPLE
{
  "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"
    }
  ]
}

The request body. Put the document above into template and the data below into data.

REQUEST
{
  "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
      }
    ]
  }
}