cybozu developer network

カテゴリー内の他の記事

後で追加した計算フィールドに一括で値を反映する方法

(著者:ラジカルブリッジ 斎藤栄

kintoneエバンジェリストに指名いただきましたラジカルブリッジの斎藤と申します。
当社Webサイト内の「kintoneブログ」でもkintoneに関する様々な小ネタを発信しておりますが、今後はこちらのdeveloper networkでも情報発信をしていきたいと思っていますのでどうぞ宜しくお願いいたします。

今回は、運用中のアプリに新たに「計算」フィールドを追加した際に、JavaScriptを用いて計算フィールドに一括で値を反映する方法を紹介します。

kintoneは、一度作成したアプリでも後で簡単にフィールドを追加することができるため、最初に全ての要件が揃っていなくてもまずは作り始められるというのが素晴らしいところです。

しかしながら、数値フィールドの計算結果を格納するような計算フィールドを後で追加した場合、そのままでは既存のレコードには自動的に計算結果が格納されません。

レコードの詳細画面を開いて、何も変更せずに再保存することで計算フィールドに計算結果を反映することはできますが、大量のレコードが登録されているような場合、全てのレコードに対してこのような作業を行うのはベターなやり方ではありません。

そこで、ボタンを一回押すだけで一括で値を反映させてみたいと思います。

サンプルイメージ

今回ご紹介するJavaScriptはどんなアプリにでも対応できるのですが、ここではある会合の「合計金額」と「参加人数」を記録するアプリを想定してみましょう。下の図はその一覧画面を表示したもので、3レコード登録されています。

table1.png

ここで参加者一人当たりの金額を計算で出してみたくなり、「一人当たりの金額」という計算フィールドを追加しました。もちろん計算式は「合計金額 / 参加人数」です。(フィールドのタイトルとフィールドコードを揃えています)

下の図は、「一人当たりの金額」フィールドを追加した直後の一覧画面です。

table2.png

ご覧のように、計算フィールドを追加しただけでは、まだ計算結果が格納されていません。
このサンプルでは3レコードしかありませんので、一つ一つのレコードを再保存することで計算結果を反映することもできるのですが、これが数百レコードある場合は作業する気にもなりません。。

そこで今回は複数レコードを空更新することで、一括で値を反映をしたいと思います。

複数レコードに空更新を行う

あとは、このパラメーターをもとにPUTメソッドでレコードを更新すれば更新完了です。
尚、このスクリプトは「レコード番号」フィールドのフィールドコードが、既定値である「レコード番号」になっていることを前提としています。

※このままスクリプトを作成すると100レコードまでのアプリの対応となります。100レコードより多い場合は「offset の制限値を考慮したレコード一括取得について」をご参照ください。

一括で値を反映させてみよう

JavaScriptでレコード一覧画面にボタンを配置して、一括で値を反映してみましょう。
ボタンの設置の仕方はこちらの記事をご参考ください。

button.png

このボタンをクリックして空更新を行う関数を呼び出します。
以下の図のように「一人当たりの金額」フィールドに正しい計算結果が格納されていることがわかります。

table3.png

とっても楽チンですね!

kintoneアプリの運用を続けているとフィールドの追加は必ず発生してくるものですが、今回ご覧いただいたような計算フィールドへの一括反映処理が必要となる場面が必ず出てくるかと思います。このスクリプトはどんなアプリにでも対応可能ですので、同様の場面に遭遇した際にぜひご活用ください。

このTipsは、2022年10月版で確認したものになります。

デモ環境

https://dev-demo.cybozu.com/k/71/

※デモ環境についての説明はこちら

記事に関するフィードバック

記事のコメント欄は記事に対するフィードバックをする場となっております。
右の記事フィードバックのためのガイドを参照してコメントしてください。
記事のリンク切れなど、気になる点がある場合も、こちらのフォームからフィードバックいただけますと幸いです。

Avatar
hatano

はじめましてKintoneを利用しはじめて2か月目のJS初心者です。
こちらを見て作成してみましたがうまく動きません、どこがおかしいのでしょうか?
お手数ですがご教授頂けますでしょうか、よろしくお願いいたします。

(function () {
"use strict";
kintone.events.on('app.record.index.show', function (event) {
if (document.getElementById ('my_index_button') != null) {
return;
}

    var myIndexButton = document.createElement('button');
    myIndexButton.id = 'my_index_button';
    myIndexButton.innerHTML = '更新ボタン';

    // ボタンクリック時の処理
    myIndexButton.onclick = function() {

    kintone.api('/k/v1/records', 'GET', {app: appId}, function(resp) {

            //////// 空更新オブジェクトの生成
            var param = {
                "app": appId,
                "records": []
            };

            for (var i = 0; i < resp['records'].length; i++) {
                param['records'][i] = {
                    "id": resp['records'][i]['売上NO']['value'],
                    "record": {}
                }
            }

    }

    kintone.app.getHeaderMenuSpaceElement().appendChild(myIndexButton);
});

})();

Avatar
cybozu development team

hatanoさん
cybozu.com developer network事務局です。
どのようなエラーになりますでしょうか?

Avatar
鈴木佑介

hatanoさん
はじめまして。
鈴木と申します。

// ボタンクリック時の処理
myIndexButton.onclick = function() {

// 下記を追加 -----
var appId = kintone.app.getId();
// -----
kintone.api('/k/v1/records', 'GET', {app: appId}, function(resp) {

としたらどうでしょうか?

Avatar
川合アサノリ

デモで使われてるコードがほしい

Avatar
吉村啓治郎

はじめまして

Kintone5か月、JS3か月の初心者です。

 

上記のサンプルと、その他のページのサンプルをつなぎ合わせて以下のコードを作りました。

一応ボタンは表示され、レコードを投げるまではできているようですが、データの更新はされていないみたいです。

(function () {

    "use strict";

    kintone.events.on('app.record.index.show', function (event) {

        if (document.getElementById ('my_index_button') != null) {

            return;

         }

         var myIndexButton = document.createElement('button');

         myIndexButton.id = 'my_index_button';

         myIndexButton.innerHTML = '再計算';

 

        // ボタンクリック時の処理

        myIndexButton.onclick = function() {

            var appId = kintone.app.getId();

            kintone.api('/k/v1/records', 'GET', {app: appId}, function(resp) {

                 //////// 空更新オブジェクトの生成

                 var param = {

                     "app": appId,

                     "records": []

                 };

                 for (var i = 0; i < resp['records'].length; i++) {

                     param['records'][i] = {

                         "id": resp['records'][i]['レコード番号']['value'],

                         "record": {}

                     }

                 }

                    kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', param, function(resp) {

                     // success

                     console.log(resp);

                 }, function(error) {

                     // error

                     console.log(param);

                     console.log(error);

                 });

             });

         }

         kintone.app.getHeaderMenuSpaceElement().appendChild(myIndexButton);

     });

 })();

 

IEの開発者ツールを開くと、コンソールに次のようなメッセージを含んだレコードが出力されています。

             messages: [

               0: "更新するレコードを、「id」か「updateKey」のいずれかのパラメーターで指定する必要があります。",

                length: 1

             ]

    id: "1505999166-1853162239",

       message: "入力内容が正しくありません。"

 

送ったレコードの書式が間違っているのでしょうか?

 

 

 

吉村啓治郎により編集されました
Avatar
斎藤 栄

吉村さん
初めまして。著者の斎藤です。

本記事では1レコードずつの更新ではなく、「一括更新」を想定した空更新オブジェクトの生成を行っていますので、
APIのURIは '/k/v1/record' ではなく '/k/v1/records' にする必要があります。
(最後にsがつきます)

kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', param, function(resp) {
                            ↓
kintone.api(kintone.api.url('/k/v1/records', true), 'PUT', param, function(resp) {

いかがでしょうか?

レコードの一括更新については、下記リファレンスもご確認いただければと思います。
https://cybozudev.zendesk.com/hc/ja/articles/201941784-%E3%83%AC%E3%82%B3%E3%83%BC%E3%83%89%E3%81%AE%E6%9B%B4%E6%96%B0-PUT-#step2

Avatar
吉村啓治郎

斎藤さん。

無事、動作しました。

ご指摘のリファレンスも見ながら作成したのですが、URIの記述の違いに気付かずに1レコード用のものをコピー&ペーストしてしまったようです。

修正したプログラムを実行して再計算ボタンを押した後、F5を押して再読み込みをしたら、計算結果が更新されました。

ありがとうございました。

Avatar
斎藤 栄

吉村さん

無事動いたようで何よりです。
kintone REST APIのGET, POST, PUTでは record とrecords を間違えることがよくあるので一目でわかりました(^^;

JSを始めてまだ間もない様子ですが、JSそのもののつまづきポイントとkintoneならではのつまづきポイントがあるので
また何かありましたら投稿いただければと思います。

Avatar
まさよし

同じボタンを設置したいと思い、このページを参考に試してみましたが、ボタンを押しても何も起こりませんでした。

提示されているデモ環境では、ボタンを押したあと、更新かかっているような動作をしますが、各レコードを表示しても、更新されていませんでした。

最新の環境で動作するコードを提供いただければ助かります。何卒よろしくお願いします。

まさよしにより編集されました
Avatar
cybozu Development team

grezou 様

本記事に記載されているサンプルコードは、行いたい処理(レコードの空更新)の記述方法を一部抜き出したものです。
この部分の処理に関しては、現状のkintoneでも動作するものになっています。

また、デモ環境は「複数の方が同時にアクセスして動作を見る環境である」という特性上、本記事に関しましては記事通りの動作を確認いただくものの用意はできません。
このため、デモアプリでは自動計算の設定を外し、更新日時でレコードの空更新をご確認いただく内容となっております。

「サンプルコードに書き足したり、書き換えた箇所でうまく動作しない」ということでしたら、以下の記事を参考にデバッグをお試しください。

デバッグしても解決できない場合には、コミュニティ をご活用いただければと思います。

どうぞよろしくお願いいたします。

Avatar
kana T

はじめまして。プログラムど素人です。

皆様の投稿を参考にしてみたのですが、どうもエラーが起きているようです。

どこが違うのか、根本的にどこを直したらいいのか教えて頂けると助かります。

(function() {
  'use strict';
  kintone.events.on('app.record.index.show', function(event) {
      if (document.getElementById ('my_index_button') !== null) {
            return;

         }

         var myIndexButton = document.createElement('button');

         myIndexButton.id = 'my_index_button';

         myIndexButton.innerHTML = '再計算';


       //////// 空更新オブジェクトの生成
       var param = {
           "app": appId,
           "records": []
       };

 
         for (var i = 0; i < resp['records'].length; i++) {
             param['records'][i] = {
                 "id": resp['records'][i]['レコード番号']['value'],
                 "record": {}
             }
         }
                    kintone.api(kintone.api.url('/k/v1/records', true), 'PUT', param, function(resp) {

                     // success

                     console.log(resp);

                 }, function(error) {

                     // error

                     console.log(param);

                     console.log(error);

                 });

             });

         }

    kintone.app.getHeaderMenuSpaceElement().appendChild(myIndexButton);
     });

 })();

JSEdit for kintoneで作成したのですが、最後の kintone.app.getHeaderMenuSpaceElement().appendChild(myIndexButton);の箇所が×になっています。

どうかお力をお貸しください。。。よろしくお願い致します。

Avatar
cybozu Development team

胤森 加菜様

下記の投稿と同様の要件を実現されたいということでよろしいでしょうか。

https://developer.cybozu.io/hc/ja/articles/201883830/comments/204526203

そうであれば、上記のリンク先のコードで下記の部分を

 kintone.api(kintone.api.url('/k/v1/record', true), 'PUT', param, function(resp) {

下記のように変更いただければ動作すると思います。
提示いただいたコードでは // ボタンクリック時の処理 下の3行が不足しているようです。

kintone.api(kintone.api.url('/k/v1/records', true), 'PUT', param, function(resp) {

本記事に記載されているサンプルコードは、行いたい処理(レコードの空更新)の記述方法を一部抜き出したものです。

こちらは記事のフィードバック欄のため、「サンプルコードに書き足したり、書き換えた箇所でうまく動作しない」ということでしたら、以下の記事を参考にデバッグをお試しください。

デバッグしても解決できない場合には、コミュニティ をご活用いただければと思います。

どうぞよろしくお願いいたします。

Avatar
T.H

気になった点があります。

'id': resp.records[i].レコード番号.value,

id にレコード番号を設定していますが、

アプリコードを指定している場合、レコードID ≠ レコード番号になるような気がします。

https://developer.cybozu.io/hc/ja/articles/202166330

こちらでもAPIを使う場合は、レコード番号でなくレコードIDを使うよう推奨されているようですし、

'id': resp.records[i].$id.value,

の方がよいのではないでしょうか?

Avatar
cybozu Development team

T.H 様
お世話になっております。cybozu developer network 運営でございます。

フィードバックをいただき、ありがとうございます。
ご指摘の内容を社内にフィードバックし、修正を検討します。

今後ともよろしくお願いいたします。

サインインしてコメントを残してください。