kintoneにおけるテーブル操作の基本(行の追加・更新・削除)

目次

kintone で便利なテーブルですが、JavaScript カスタマイズで取得して操作する場合は入れ子構造が深くて少々複雑ですので、構造や操作方法について解説します。

テーブルの操作の方法

テーブルの構造

テーブルの構造は少々複雑ですが、どのような構造になっているかを図に示しました。
特に、テーブルのオブジェクトの中には 3 階層にわたって value がありますので注意してください。

実際のオブジェクトを示すとこのようになります。(テーブル以外のフィールドは省略)

 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
{
  "テーブル": {
    "type": "SUBTABLE",
    "value": [
      {
        "id": "1923",
        "value": {
          "行番号": {
            "type": "NUMBER",
            "value": "1"
          },
          "テキスト": {
            "type": "SINGLE_LINE_TEXT",
            "value": "サンプルテキスト1"
          },
          "チェックボックス": {
            "type": "CHECK_BOX",
            "value": [
              "チェック1"
            ]
          }
        }
      },
      {
        "id": "1925",
        "value": {
          "行番号": {
            "type": "NUMBER",
            "value": "2"
          },
          "テキスト": {
            "type": "SINGLE_LINE_TEXT",
            "value": "サンプルテキスト2"
          },
          "チェックボックス": {
            "type": "CHECK_BOX",
            "value": [
              "チェック2"
            ]
          }
        }
      }
    ]
  }
}

サンプルアプリ:テーブル操作

テーブルを JavaScript カスタマイズで操作するための、デモ環境にサンプルアプリを用意してみました。

デモ環境

デモ環境で実際に動作を確認できます。
https://dev-demo.cybozu.com/k/313/ (External link)

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

このアプリでは、「追加」「更新」「削除」ができます。

  • 追加ボタンを押したとき:「追加_テキスト」「追加_チェックボックス」フィールドの値をテーブルに追加する。
  • 更新ボタンを押したとき:「更新_行番号」で指定したテーブルの対象の「テキスト」フィールドを「更新_テキスト」「更新_チェックボックス」で更新する。
  • 削除ボタンを押したとき:「削除_行番号」で指定したテーブルの対象の行を削除する。

サンプルプログラムの解説は、こちらの 第 16 回 kintone JavaScript カスタマイズのプログラム実例を学ぼう④(テーブル操作) にあります。
「コードの意味は理解できていない」「変更を加えたいけど、どの部分を修正すればいいかわからない」と感じている方は、ぜひチュートリアル記事を確認してみてください。

プログラム

 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
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/*
 * テーブル操作のサンプルコード
 * Copyright (c) 2020 Cybozu
 *
 * Licensed under the MIT License
 * https://opensource.org/license/mit/
 */
(() => {
  'use strict';
  kintone.events.on(['app.record.create.show', 'app.record.edit.show'], (e) => {

    // 追加ボタンを設置
    const addSpace = kintone.app.record.getSpaceElement('addSpace');
    const addButton = document.createElement('button');
    addButton.innerHTML = '追加';
    addButton.onclick = addRow;
    addSpace.appendChild(addButton);

    // 更新ボタンを設置
    const updateSpace = kintone.app.record.getSpaceElement('updateSpace');
    const updateButton = document.createElement('button');
    updateButton.innerHTML = '更新';
    updateButton.onclick = updateRow;
    updateSpace.appendChild(updateButton);

    // 削除ボタンを設置
    const deleteSpace = kintone.app.record.getSpaceElement('deleteSpace');
    const deleteButton = document.createElement('button');
    deleteButton.innerHTML = '削除';
    deleteButton.onclick = deleteRow;
    deleteSpace.appendChild(deleteButton);
    return e;
  });

  // 行追加関数
  const addRow = () => {
    const record = kintone.app.record.get().record;
    const addText = record.追加_テキスト.value;
    const addCheckBox = record.追加_チェックボックス.value;
    record.テーブル.value.push({
      value: {
        行番号: {
          value: '',
          type: 'NUMBER',
        },
        テキスト: {
          value: addText,
          type: 'SINGLE_LINE_TEXT',
        },
        チェックボックス: {
          value: addCheckBox,
          type: 'CHECK_BOX',
        }
      }
    });
    resetRowNo(record);
    kintone.app.record.set({record: record});
  };

  // 行更新関数
  const updateRow = () => {
    const record = kintone.app.record.get().record;
    const updateText = record.更新_テキスト.value;
    const updateCheckBox = record.更新_チェックボックス.value;
    const targetRowNo = record.更新_行番号.value;
    record.テーブル.value.forEach((row) => {
      if (row.value.行番号.value === targetRowNo) {
        row.value.テキスト.value = updateText;
        row.value.チェックボックス.value = updateCheckBox;
      }
    });
    resetRowNo(record);
    kintone.app.record.set({record: record});
  };

  // 行削除関数
  const deleteRow = () => {
    const record = kintone.app.record.get().record;
    const targetRowNo = record.削除_行番号.value;
    record.テーブル.value.forEach((row, i) => {
      if (row.value.行番号.value === targetRowNo) {
        record.テーブル.value.splice(i, 1);
      }
    });
    resetRowNo(record);
    kintone.app.record.set({record: record});
  };

  // 行番号更新関数
  const resetRowNo = (record) => {
    record.テーブル.value.forEach((row, i) => {
      row.value.行番号.value = i + 1;
    });
  };
})();

JavaScriptカスタマイズ全体の構成

この JavaScript カスタマイズは、「スペースフィールドにボタンを設置する」部分と「テーブルの行追加・更新・削除」部分に分かれます。
今回はテーブルを中心に解説しますので、スペースフィールドの扱い方は次の記事を参考にしてください。

第3回 レコード詳細にもボタンを設置しよう!

スペースフィールドにボタンを設置する処理
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
    // 追加ボタンを設置
    const addSpace = kintone.app.record.getSpaceElement('addSpace');
    const addButton = document.createElement('button');
    addButton.innerHTML = '追加';
    addButton.onclick = addRow;
    addSpace.appendChild(addButton);

    // 更新ボタンを設置
    const updateSpace = kintone.app.record.getSpaceElement('updateSpace');
    const updateButton = document.createElement('button');
    updateButton.innerHTML = '更新';
    updateButton.onclick = updateRow;
    updateSpace.appendChild(updateButton);

    // 削除ボタンを設置
    const deleteSpace = kintone.app.record.getSpaceElement('deleteSpace');
    const deleteButton = document.createElement('button');
    deleteButton.innerHTML = '削除';
    deleteButton.onclick = deleteRow;
    deleteSpace.appendChild(deleteButton);
テーブルの行を追加する処理
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  // 行追加関数
  const addRow = () => {
    const record = kintone.app.record.get().record;
    const addText = record.追加_テキスト.value;
    const addCheckBox = record.追加_チェックボックス.value;
    record.テーブル.value.push({
      value: {
        '行番号': {
          value: '',
          type: 'NUMBER',
        },
        'テキスト': {
          value: addText,
          type: 'SINGLE_LINE_TEXT',
        },
        'チェックボックス': {
          value: addCheckBox,
          type: 'CHECK_BOX',
        }
      }
    });
    resetRowNo(record);
    kintone.app.record.set({record: record});
  };
テーブルの行を更新する処理
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
  // 行更新関数
  const updateRow = () => {
    const record = kintone.app.record.get().record;
    const updateText = record.更新_テキスト.value;
    const updateCheckBox = record.更新_チェックボックス.value;
    const targetRowNo = record.更新_行番号.value;
    record.テーブル.value.forEach((row) => {
      if (row.value.行番号.value === targetRowNo) {
        row.value.テキスト.value = updateText;
        row.value.チェックボックス.value = updateCheckBox;
      }
    });
    resetRowNo(record);
    kintone.app.record.set({record: record});
  };
テーブルの行を削除する処理
76
77
78
79
80
81
82
83
84
85
86
87
  // 行削除関数
  const deleteRow = () => {
    const record = kintone.app.record.get().record;
    const targetRowNo = record.削除_行番号.value;
    record.テーブル.value.forEach((row, i) => {
      if (row.value.行番号.value === targetRowNo) {
        record.テーブル.value.splice(i, 1);
      }
    });
    resetRowNo(record);
    kintone.app.record.set({record: record});
  };
テーブルの行番号を更新する処理
89
90
91
92
93
94
  // 行番号更新関数
  const resetRowNo = (record) => {
    record.テーブル.value.forEach((row, i) => {
      row.value.行番号.value = i + 1;
    });
  };

以下に、それぞれの部分ごとに解説をします。

ボタン設置部分

ここでは、スペースフィールドへのボタン設置と、ボタン押下時の設定をそれぞれいれています。
たとえば下記は「追加ボタン」の後続に宣言している「行追加」の関数を指定しています。

1
addButton.onclick = addRow();

行追加処理

テーブルは配列で表現されていますので、JavaScript でいうと配列の最後に値を追加する処理を書きます。
配列に行を追加するには .push() を使います。
push() の中にはテーブルの行に相当する value を指定します。
このとき、テーブル内のすべてのフィールドのフィールドコードや type, value も指定する必要があります。

テーブルへ1行追加するためのコード(例)
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
record.テーブル.value.push({
  value: {
    '行番号': {
      value: 1,
      type: 'NUMBER',
    },
    'テキスト': {
      value: 'テキスト本文',
      type: 'SINGLE_LINE_TEXT',
    },
    'チェックボックス': {
      value: ['チェック1'],
      type: 'CHECK_BOX',
    }
  }
});
行追加のイメージ

サンプルアプリのコードの行追加部分の解説

前述の例のとおり push() をつかって行を追加します。
このサンプルでは、追加/更新/削除すべてのタイミングで resetRowNo() という関数を呼んで行番号をリセットしています。(詳しくは後述)

record 取得と追加する行にセットするための値を代入する
32
33
34
    const record = kintone.app.record.get().record;
    const addText = record.追加_テキスト.value;
    const addCheckBox = record.追加_チェックボックス.value;
push() で行を追加する

このとき、すべてのフィールドの value/type を指定する必要があります。

40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
    record.テーブル.value.push({
      value: {
        '行番号': {
          value: '',
          type: 'NUMBER',
        },
        'テキスト': {
          value: addText,
          type: 'SINGLE_LINE_TEXT',
        },
        'チェックボックス': {
          value: addCheckBox,
          type: 'CHECK_BOX',
        }
      }
    });
行番号には空文字を指定する

行追加の直後に行番号を更新するため、行番号には空文字を指定します。

1
2
3
4
        '行番号': {
          value: '',
          type: 'NUMBER',
        },
行番号を更新する関数(後述)
56
    resetRowNo(record);
ここまでの変更内容を record に反映させる
57
    kintone.app.record.set({record: record});

行更新処理

行を更新する場合は、大まかに分けて「更新したい行を探す」「行の値を書き換える」の 2 つの処理が必要です。
「更新したい行を探す」方法はいくつかありますが、今回はループして該当の行の場合は書き換えるという処理にしています。

record 取得と追加する行にセットするための値を代入する
62
63
64
65
    const record = kintone.app.record.get().record;
    const updateText = record.更新_テキスト.value;
    const updateCheckBox = record.更新_チェックボックス.value;
    const targetRowNo = record.更新_行番号.value;
forEach() を使ってループし、「更新_行番号」と同じ行を更新する
66
67
68
69
70
71
    record.テーブル.value.forEach((row) => {
      if (row.value.行番号.value === targetRowNo) {
        row.value.テキスト.value = updateText;
        row.value.チェックボックス.value = updateCheckBox;
      }
    });
行番号を更新する関数(後述)
72
    resetRowNo(record);
ここまでの変更内容を record に反映させる
73
    kintone.app.record.set({record: record});

行削除処理

追加と同じく、JavaScript の配列操作によって配列を一部削除する必要があります。
配列の一部要素を削除するには、 .splice() を使うことでできます。

テーブルの行を削除するためのコード(例)

.splice() は 2 つの引数が必要です。

  • 1 つ目の引数: 何番目の配列か。
  • 2 つ目の引数: 何個消すか。

2 つ目の行を 1 行削除するには次のとおりになります。

1
record.receipts.splice(1, 1);
行削除のイメージ

サンプルアプリのコードの行削除部分の解説

更新のときのように forEach() でループさせて判定処理を行い、対象の行を splice() を削除する流れになっています。

record 取得と削除する行番号取得
78
79
    const record = kintone.app.record.get().record;
    const targetRowNo = record.削除_行番号.value;
forEach() を使ってループし、「削除_行番号」と同じ行を splice() で削除する
80
81
82
83
84
    record.テーブル.value.forEach((row, i) => {
      if (row.value.行番号.value === targetRowNo) {
        record.テーブル.value.splice(i, 1);
      }
    });
行番号を更新する関数(後述)
85
    resetRowNo(record);
ここまでの変更内容を record に反映させる
86
    kintone.app.record.set({record: record});

行番号リセット処理

今回のサンプルアプリでは追加/更新/削除どの関数を使っても毎回最後に行番号をリセットしています。
行番号更新と削除と同じように forEach() で繰り返し処理をして、番号を書き換えています。
リセット処理は各追加/更新/削除関数で呼ばれるため、record データは引数に渡しています。

89
90
91
92
93
94
  // 行番号更新関数
  const resetRowNo = (record) => {
    record.テーブル.value.forEach((row, i) => {
      row.value.行番号.value = i + 1;
    });
  };

補足

保存時に処理を実行させたい場合

今回のサンプルアプリでは、編集画面でボタンを押したときに動作するものなので、
レコードの値を取得する / レコードに値をセットする をつかっています。
保存時に処理を実行させる場合は、 レコード編集画面で保存するときのイベント を使って引数 event に渡される record を編集すれば OK です。

.forEach() などの繰り返し処理について

通常の for 文よりも、forEach()map()reduce() などの繰り返し処理が便利ですので、下記リンクを参考にしてください。
forEach, map, filterなどをつかってkintoneのrecords配列をもっと上手に扱う (External link)

テーブルを一括削除したい場合

テーブルは配列でできていますので、配列の中身を空にすれば一括で削除できます。

1
record.テーブル.value = [];
information

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