サブテーブルに1行追加を全レコードに行いたい

お世話になります。

サブテーブルに新しいレコードを持たせる作業を全レコードに対して一括で行いたいのですが、良い方法はありますでしょうか。

レコードを追加させる際に初期値として別フォームの値を持たせたいです。

具体的には年に1回マスタを更新したいのですが、年度ごとにサブテーブルで持っているため、手動で追加するのが手間です。

下記のようにjsで追加しようとしたのですが、テーブル自体が行追加ではなく、リメイク動作をしてしまいます(元あったデータが削除されて新たに作り直される)

 

(function() {
   "use strict";
   kintone.events.on("app.record.index.show", function(event) {
       if (document.getElementById('my_4_button') !== null) {
           return;
       }
       var myIndexButton = document.createElement('button');
       myIndexButton.id = 'my_4_button';
       myIndexButton.innerHTML = 'table';

      //ボタンクリック後の処理
       myIndexButton.onclick = function() {
           var appId = kintone.app.getId();
           var param = {
               app: appId,
               query: '',
               fields: ['$id', '有給用', '有給年度'],
               totalCount: true,
               isGuest: false
           };
    kintoneUtility.rest.getAllRecordsByQuery(param).then(function(resp) {


        /////////空更新オブジェクトの生成
        var param = {
            "app": appId,
            "records": [],
            isGuest: false
        };
        //レコード更新
        resp.records.forEach(function(record) {
            var newRow1 = {};
            newRow1 = {
              value: {
                '有給年度': { value: 2022 },
              }
            }
 
            param.records.push({
                "id": record.$id.value,
                "record": {
                    '有給用': {
                        value: [
                            newRow1
                        ]
                    }
                }
            });
 
        });
        kintoneUtility.rest.putAllRecords(param).then(function(resp) {
            //success
            console.log(resp);
        }, function(error) {
            //error
            console.log(param);
            console.log(error);
        });
    });
       }
       kintone.app.getHeaderMenuSpaceElement().appendChild(myIndexButton);
       return event;
   });
})();

テーブルのデータを作り直さずに更新する方法をお答えします。

サブレコード行の値を更新する時は、行ごとに付与されているIDを使用します。

下図のサブテーブルの場合、

データ構造は以下のようになっています。

 

レコード作成前 (kintone の仕様として必ず1行存在する)

[
  {
  "id": null,
    "value": {
      "有給年度": {
      "type": "NUMBER"
    }
    }
  }
]

レコード作成後

[
  {
    "id": "34077",
    "value": {
      "有給年度": {
        "type": "NUMBER",
        "value": "2022"
      }
    }
  }
]

 

このような構造のため、ADMさんのコードはIDを指定していないことから、データを破棄して新たな行を作成するという挙動になっています。

既存の行を更新する場合は、下記のようにIDを指定すれば解決します。

            newRow1 = {
            id: targetRowId, // 更新対象の行のIDを設定する
             value: {
                '有給年度': { value: 2022 },
              }
          }

また、サブテーブルに行を追加する場合は、既存の行を含める必要があります。

            param.records.push({
                "id": record.$id.value,
                "record": {
                    '有給用': {
                        value: [
                          { id: firstRowId }, // 値に変更がなければ、IDのみを指定すればOK
                            newRow1
                        ]
                    }
                }
          });

以上になります。

川村様

ご教示いただきありがとうございます。

頂いた内容を反映させてみました。

既存のテーブル2行が1行となり全て空白、その下に今回の追加分が挿入されていました。想定では既存のレコード2行は残ったまま今回の追加分が挿入されて3行になる想定でした。

何か指定を間違えていますでしょうか

 

(function() {
   "use strict";
   kintone.events.on("app.record.index.show", function(event) {
       if (document.getElementById('my_4_button') !== null) {
           return;
       }
       var myIndexButton = document.createElement('button');
       myIndexButton.id = 'my_4_button';
       myIndexButton.innerHTML = '年次処理';

      //ボタンクリック後の処理
       myIndexButton.onclick = function() {
           var appId = kintone.app.getId();
           var param = {
               app: appId,
               query: '',
               fields: ['$id', '有給用', '有給年度','前残'],
               totalCount: true,
               isGuest: false
           };
    kintoneUtility.rest.getAllRecordsByQuery(param).then(function(resp) {
        /////////空更新オブジェクトの生成
        var param = {
            "app": appId,
            "records": [],
            isGuest: false
        };
        //レコード更新
        resp.records.forEach(function(record) {
            var newRow1 = {};
            var targetRowId = {};
            var firstRowId = {};
            newRow1 = {
            $id: targetRowId, // 更新対象の行のIDを設定する
              value: {
                '有給年度': { value: 2022 },
              }
            }
 
            param.records.push({
                "id": record.$id.value,
                "record": {
                   '有給用': {
                        value: [
                         { $id: firstRowId }, // 値に変更がなければ、IDのみを指定すればOK
                            newRow1
                        ]
                    }
                }
            });
 
        });
        kintoneUtility.rest.putAllRecords(param).then(function(resp) {
            //success
            console.log(resp);
        }, function(error) {
            //error
            console.log(param);
            console.log(error);
        });
    });
       }
       kintone.app.getHeaderMenuSpaceElement().appendChild(myIndexButton);
       return event;
   });
})();

ADMさん

私が書いたコード内の変数(targetRowId, firstRowId)は一例ですので、ADMさんのコードの場合は、下記のようにIDを指定すれば再作成にはならず、デフォルトの行(1行目)を更新できます。

  var newRow1 = {
    id: record.有給用.value[0].id, 
    value: {
      '有給年度': { value: 2022 },
    }
  }

  param.records.push({
    "id": record.$id.value,
    "record": {
       '有給用': {
            value: [
                newRow1
            ]
        }
    }
  });

2行以上ある場合はこの記述だとサブテーブルの値を上書きしてしまうので、更新するデータ(param.records)に既存の行を含めてみてください。

実装上で不明な点がありましたら、お気軽にご質問ください。

 

川村

度々ありがとうございます。

更新の必要がなく、追加のみが前提だとすると記述は変わってきますでしょうか。

最低1行は既に入っており、最終行に1行を追加する想定です。

最初にお伝えすればよかったですが、前後して申し訳ございません。

1つ問題なのは、テーブル内の行数はレコードによってバラバラで1行のときもあれば5行の時もあったりします。

そのため2行目に追加するのか、6行目に追加するのかが固定できません。

ADMさん

それでは質問内容を下記と理解した上で、コードの一例で回答します。

  1. デフォルトの1行(値は未設定)が存在する場合は、その行に値を設定する

  2. 値が設定されている行が存在する場合は、新たに行を追加する

     resp.records.forEach(function (record) {
       var oldRows = record.有給用.value;
       var newRow = { value: { 有給年度: { value: '2022' } } };
       var newRows = [];
    
       if (oldRows.length === 1 && !oldRows[0].value.有給年度.value) {
       // デフォルトの行が未入力の場合、値を設定して更新(行内の他のフィールドも判定が必要な場合は条件に追加)
         newRow.id = oldRows[0].id;
       } else {
         // 既存の行は更新しないためIDのみ取り出す、通信量・パフォーマンスを気にしなければ newRows = oldRows でも可
         newRows = oldRows.map(function (row) {
           return { id: row.id };
         });
      }
    
       newRows.push(newRow);
    
       param.records.push({
         id: record.$id.value,
         record: {
           有給用: {
             value: newRows,
           },
         },
       });
     });
    

以上になります。既に設定したい値が存在する場合の処理は考慮していませんが、参考になれば幸いです。

>>川村様

ありがとうございます。

想定通りの動きになりました。今回の件、とても勉強になりました。感謝いたします。

今後のために知りたいのですが、今回は有給年度を「2022」固定としましたが、別フィールドから持ってくる場合は、

     varnewRow = { value: { 有給年度: { value:'2022'} } };

この部分のvalue:以降をレコードフィールド指定で問題ありませんでしょうか。

今後は年度の他にも前年度残数等を持ってきたいと考えています。

自己解決しました。

ありがとうございます!

このトピックはベストアンサーに選ばれた返信から 3 日が経過したので自動的にクローズされました。新たに返信することはできません。