テーブルの値を取得してデータを集計してみよう!

目次

はじめに

kintoneのテーブルは、1つのレコード内で複数の行を管理できるフィールドです。
たとえば、商品の注文管理アプリでは、注文に応じて異なる商品名や注文数を、必要な数だけ行を追加して入力できます。
テーブルのデータは行ごとに管理されているため、値の取得方法が他のフィールドとは少し異なります。
今回は、テーブルのデータ構造について説明しながら、値の取得方法を解説していきます。

動作イメージ

今回は、パンの売り上げ管理アプリを使用します。
アプリの動作については、次の節の「デモ環境」を参照してください。

アプリの仕様は以下のとおりです。

  • 1つのレコードで1日の売り上げをする。
  • レコード内のテーブルに売れた商品を記入していく。
  • 記入する商品の情報は、カテゴリ商品名単価(円)個数

レコードの詳細画面を開いたときに、テーブル内の商品をカテゴリごとに売上金額を集計し、結果をスペース内に表示します。

デモ環境

デモ環境で実際に動作を確認できます。
パンの売り上げ管理アプリ (External link)

ログイン情報は以下のページで確認してください。
cybozu developer network デモ環境

カスタマイズを適用するアプリ

パンの売り上げ管理アプリの作成手順です。

フォームの作成

各フィールドとフィールドコードは以下のとおりです。
フィールドコードはJavaScriptで構築する際に使用します。

フィールド名 フィールドタイプ フィールドコード
日付 日付 datetime
- テーブル order_items
- スペース sub_total_area
作成日時 作成日時 作成日時
更新日時 更新日時 更新日時

テーブル(order_items)フィールドは以下のように設定します。
テーブルの作り方については、次のページを参考にしてください。
フォームに表(テーブル)を追加する (External link)

フィールド名 フィールドタイプ フィールドコード 備考
カテゴリ ラジオボタン category 項目と順番
  • パン
  • その他
初期値:パン
商品名 文字列(1行) item_name
単価(円) 数値 unit_price
個数 数値 quantity

ここまで作成したらフォームを保存してアプリを更新します。

レコードの追加

以下のようなレコードを作成します。

実装する処理を整理

今回カスタマイズする内容と、実装する処理の流れを以下にまとめます。

カスタマイズする内容

パンの売り上げをカテゴリごとに集計し、結果をスペースに表示する。

実装する処理

実装する手順は以下のとおりです。

  1. テーブル内の売り上げをカテゴリごとに集計する。
  2. 集計結果をスペースに表示する。

サンプルコード

aggregator.js

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
/*
 * Retrieve table values sample
 * Copyright (c) 2024 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */

(function() {
  'use strict';

  kintone.events.on('app.record.detail.show', (event) => {
    if (!event.record) {
      return;
    }

    const subTotals = {};
    const tableRecords = event.record.order_items.value;

    // テーブル内の各レコードをカテゴリごとに集計する
    tableRecords.forEach(record => {
      const category = record.value.category.value;
      const quantity = parseInt(record.value.quantity.value, 10);
      const unitPrice = parseInt(record.value.unit_price.value, 10);
      const total = quantity * unitPrice;

      if (!subTotals[category]) {
        subTotals[category] = 0;
      }
      subTotals[category] += total;
    });

    // 集計結果をスペースフィールドに表示する
    const subTotalList = document.createElement('ul');

    Object.keys(subTotals).forEach(category => {
      const listItem = document.createElement('li');
      listItem.textContent = `${category}: ${subTotals[category]}円`;
      subTotalList.appendChild(listItem);
    });

    const subTotalArea = kintone.app.record.getSpaceElement('sub_total_area');
    if (subTotalArea) {
      subTotalArea.appendChild(subTotalList);
    }
  });
})();

サンプルコードの解説

テーブルのデータを取得する

テーブルのデータの取得方法は、他のフィールドタイプと同様に、eventオブジェクトのrecord要素に対して、設定したフィールドコードを指定します。
テーブルのフィールドコードがorder_itemsの場合、以下のようになります。

17
const tableRecords = event.record.order_items.value;

これで、tableRecordsにテーブルのデータが格納されます。
tableRecordsの中身は以下のようになっています。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
{
  "type": "SUBTABLE",
  "value": [
    {
      "id": "244",
      "value": {
        "category": {
          "type": "RADIO_BUTTON",
          "value": "パン"
        },
        "item_name": {
          "type": "SINGLE_LINE_TEXT",
          "value": "あんぱん"
        },
        "unit_price": {
          "type": "NUMBER",
          "value": "180"
        },
        "quantity": {
          "type": "NUMBER",
          "value": "20"
        }
      }
    },
    {
      "id": "245",
      "value": {
        "category": {
          "type": "RADIO_BUTTON",
          "value": "パン"
        },
        "item_name": {
          "type": "SINGLE_LINE_TEXT",
          "value": "食パン"
        },
        "unit_price": {
          "type": "NUMBER",
          "value": "220"
        },
        "quantity": {
          "type": "NUMBER",
          "value": "13"
        }
      }
    },
    ・・・・
    ・・・・
    ・・・・
  ]
}

ここでJavaScriptを使ってレコードの詳細画面を開いたときに、テーブルの2行目の商品名(item_name)を表示してみましょう。
配列の要素は「0」から数えます。
したがって、テーブルの2件目のデータは配列では1番目となります。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
(() => {
  'use strict';
  kintone.events.on('app.record.detail.show', (event) => {
    // フィールドコード"order_items"のレコードオブジェクトを取得
    const tableRecords = event.record.order_items.value;

    // 2個目の"商品名"フィールドの値をアラートで表示
    alert(tableRecords[1].value.item_name.value);
  });
})();

上記のjavaScriptを設定画面で登録してレコードの詳細画面を開くと以下のアラートが表示されます。

2件目の商品名「食パン」が取得できていることを確認しました。

データオブジェクトの構造はフィールドの形式により異なります。
詳細については以下のページを参照してください。

カテゴリ別の合計を算出する

テーブル内のデータをforEachを利用して行ごとのデータを取得します。
subTotalsオブジェクトを用意し、カテゴリごとの売り上げの合計を管理します。

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const subTotals = {};
const tableRecords = event.record.order_items.value;

// テーブル内の各レコードをカテゴリごとに集計する
tableRecords.forEach(record => {
  const category = record.value.category.value;
  const quantity = parseInt(record.value.quantity.value, 10);
  const unitPrice = parseInt(record.value.unit_price.value, 10);
  const total = quantity * unitPrice;

  if (!subTotals[category]) {
    subTotals[category] = 0;
  }
  subTotals[category] += total;
});

集計結果をスペースフィールドに出力する

スペースフィールドの要素はkintone.app.record.getSpaceElement()で取得できます。
フィールドコードをsub_total_areaにした場合は、以下の方法で取得可能です。
スペースフィールドの要素を取得する

42
const subTotalArea = kintone.app.record.getSpaceElement('sub_total_area');

あとは、集計結果をスペースフィールドに表示していきます。

33
34
35
36
37
38
39
40
41
42
43
44
45
// 集計結果をスペースフィールドに表示する
const subTotalList = document.createElement('ul');

Object.keys(subTotals).forEach(category => {
  const listItem = document.createElement('li');
  listItem.textContent = `${category}: ${subTotals[category]}円`;
  subTotalList.appendChild(listItem);
});

const subTotalArea = kintone.app.record.getSpaceElement('sub_total_area');
if (subTotalArea) {
  subTotalArea.appendChild(subTotalList);
}

動作確認

では、実際にレコードの詳細画面を表示してみましょう。

スペースフィールドに集計結果が表示されました。

おわりに

今回はテーブルのデータ構造について説明しながら、値を取得する方法について解説しました。
テーブルのデータの集計には、自動計算機能を利用する方法もありますが、JavaScriptを利用することで、より細かいカスタマイズにも対応できます。

テーブルについての解説記事は、他にもありますので、ぜひとも参考にしてみてください。

information

このTipsは、2024年5月版kintoneで動作を確認しています。