新規投稿
フォローする

レコード一覧画面での年齢フィールド一括更新

お世話になっております。

下記投稿にてやり取りをさせていただいておりますが,REST APIを使用するためこちらに改めて投稿させていただきます。

レコード詳細画面・一覧表示画面でのフィールド値変更が定着しない

http://urx.red/BBZ3 

 

上記の投稿を経て,一覧画面にJSでボタンを設置し,クリックしたら全てのレコードの年齢フィールドを計算・年齢フィールドを最新の年齢に更新するというプログラムを作成中です。全レコード数はだいたい4000件ほどです。

下記のサイトを参考にさせていただき,プログラムを作成しておりますが,ボタンをクリックしても何も起こらない状況で困っております。Firebugを使用してブレークポイントを置いても何も反応しません。

行いたい処理の手順としては

①ボタンを設置・クリック

②レコードデータ取得(全件)

③取得したデータから年齢計算

④更新したデータでレコード更新

です。

毎度毎度大変お世話になっておりますが,どなたかおかしいところをご教授いただけますと幸いです。

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

 

参考にさせていただいたページ

多くのデータの取得と更新処理
http://urx.red/BC0e

レコードの一括更新について
http://urx.red/BC0k


第11回 REST APIを利用したレコード更新
http://urx.red/BC0p

 



念のため文字でも貼り付けさせていただきます。

(function() {

"use strict";
kintone.events.on('app.record.index.show', function(event) {

//ボタン作成
/////////////////////////////////////////////////////////////////
 // ボタン増殖防止
 if (document.getElementById('Menu_Button') !== null) {
 return;
 }

// メニュ右側の空白部分にボタンを設置
var MenuButton = document.createElement('button');
//ボタンのID指定
MenuButton.id = 'Menu_Button';
//ボタン名表示
MenuButton.innerHTML = '年齢一括更新';
//ボタンサイズ
MenuButton.style.width = '200px';
//左側のスペース
MenuButton.style.marginLeft = '250px';
//ボタンをクリックしたら
MenuButton.onclick = function () {

/////////////////////////////////////////////////////////////////////////////////////

//年齢更新
/////////////////////////////////////////////////////////////////////////////////////

  var afterRecord = event.record;
  var appId = kintone.app.getId();
  var recId = event.recordId;

  // まず、変更前のデータを取得する
  kintone.api('/k/v1/record', 'GET', {app: appId, id: recId}, function (resp) {
    var beforeRecord = resp.record;

    // 次に、更新対象レコードを取得する
    fetchRecords("37", 'id = "' + beforeRecord.id.value + '"').then(function (records) {
      var recCount = records.length;
      var putCount = Math.ceil(recCount / 100);
      for (var i = 0; i < putCount; i++) {
        var offset = i * 100;
        var limit = 100;
        if (offset + limit > recCount) {
          limit = recCount - offset;
        }
        var putLimit = limit + offset;

        var editRecords = [];

        // 更新対象レコードに更新後のデータを上書き
        for (offset; offset < putLimit; offset++) {
          var record = $.extend(true, {}, records[offset]);
          var recNo = record['$id'].value;
          var nenrei = getYearMonth(record['year'].value,record['month'].value,record['day'].value)
          delete record['$id'];
          delete record['$revision'];
          delete record['レコード番号'];
          delete record['作成日時'];
          delete record['作成者'];
          delete record['更新日時'];
          delete record['更新者'];
          record['id'] = afterRecord.id;
          record['agec'] = afterRecord.agec;
          editRecords.push({'id': recNo, 'record': nenrei});
        }

        // 最後に更新処理
        kintone.api('/k/v1/records', 'PUT', {app: 37, 'records': editRecords},
            function (resp) {}
        );
      }
    });
  });





/////////////////////////////////////////////////////////////////////////////////////


}; //onclickイベント終了

//////////////////////////////////////////////////////////////////////////////
// 現在の年齢計算する関数
function getYearMonth(year, month, day) {

  //本日の日付を取得
  var today=new Date();

  // 肝心の年齢計算について
  // 年月日の日は、そのまま引き算。
  // 年月日の月は、2ケタ左シフトして(100倍にする。1月は0なので+100からスタート)から、引き算。
  // 年月日の年は、4ケタ左シフトして(1万倍にする)から、引き算。
  // この計算方法の優れた所は、年・月・日を単独で計算して、足らなかったら上位からマイナスするという点!
  // 単純ながら、確実な年齢計算が出来る優れたアルゴリズムです!
  // ちなみに日数計算はできません。あくまで年数計算のみ
  // 参照URL:http://d.hatena.ne.jp/toku-hiro/20070824
  today=today.getFullYear()*10000+today.getMonth()*100+100+today.getDate();

  // 生年月日一列に
  var birthday=parseInt(year + month + day);

  // 単純に引き算して、下4ケタを切り捨てて、年部分だけを返す
  return(Math.floor((today-birthday)/10000));

}
//////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////////
// 全件取得関数
function fetchRecords(appId, query, opt_offset, opt_limit, opt_records) {
  var offset = opt_offset || 0;
  var limit = opt_limit || 100;
  var allRecords = opt_records || [];
  var params = {app: appId, query: query + ' limit ' + limit + ' offset ' + offset};
  return kintone.api('/k/v1/records', 'GET', params).then(function (resp) {
    allRecords = allRecords.concat(resp.records);
    if (resp.records.length === limit) {
      return fetchRecords(appId, query, offset + limit, limit, allRecords);
    }
    return allRecords;
  });
}
//////////////////////////////////////////////////////////////////////////////



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

})

})();

 

0

9件のコメント

Avatar
上海レンユアー 松村

Hiro さん

プログラムを一瞥しただけでは、どこに問題があるのか、わかりませんでした。

「ボタンをクリックしても何も起こらない状況」とのことで、この様な場合のデバッグ方法として、

1.元のソースをバックアップしておく

2.プログラムを最小限に減らして、動作確認 →  動作したら少しずつ拡張する

この手順が、良いかと思います。少し時間はかかりますが、急がば回れ。で。

例えば、第一ステップでは、

(function() {

"use strict";

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

    console.log('ここまで動いた');
});

})();

こんな感じで、最小限にして、まずは動くことを確認します。

(上記コードは適当です。動かないかも)

そのあとに、必要なコードをコピペで継ぎ足していけば、原因がつかめるかもしれません。

1
Avatar
kazuo urata

4100件のレコードを作り、     
Hiroさんの提示されたソースコードを試してみました。     
こちらで試した分には、「ボタンをクリックしても何も起こらない」ということはなくて、     
     
最初の1画面分、100件のレコードの年齢フィールド(agec)は、正しく更新されました。

     

     

こちらで注意した点は、     
・「year」、「month」、「day」フィールドは文字列フィールドにしました。     
(「agec」は数値フィールド)     
     
修正箇所が1つあって、     
     
// ;          var nenrei = getYearMonth(record['year'].value,record['month'].value,record['day'].value)     
          var nenrei = getYearMonth(record['year'].value,record['month'].value,record['day'].value);     
     
この行が、「;」がなかったので、付けました。     
     
それ以外は、デバッグ用の表示、(ex.)「window.alert('ZZZ today ' +today);」などを追加しただけで、     
変更はしていません。     
     
まずは、上記の点を試してみて頂けませんか。     
     
     
その上で、4000件全部を更新するには、レコード番号を100づつずらして、     
繰り返し処理すれば、できそうな気がします。     
     
よろしくお願い致します。

1
Avatar
Hiro

上海レンユアー松村様,kazuo urata様

ご丁寧にコメントしていただき誠にありがとうございます。

ご教授いただいた点を修正してみまして,結果が出ましたらまた

ご報告させていただきます。

返信が遅れてしまい申し訳ありません。

0
Avatar
Hiro

お世話になっております。

その後返信が遅くなり申し訳ありません。

kazuo urata様にご指摘いただいた点を修正し,プログラムを実行してみましたが,やはり動きませんでした。

Firebugを使用し,よく調べてみたところ,jsonのエラーが出ていました。

400 bad request というメッセージです。

F11で1行ずつプログラムを進めていたところ,この部分の末尾でエラーが発生してる模様です。

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

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

//ボタン作成
/////////////////////////////////////////////////////////////////
 // ボタン増殖防止
 if (document.getElementById('Menu_Button') !== null) {
 return;
 }

// メニュ右側の空白部分にボタンを設置
var MenuButton = document.createElement('button');
//ボタンのID指定
MenuButton.id = 'Menu_Button';
//ボタン名表示
MenuButton.innerHTML = '年齢一括更新';
//ボタンサイズ
MenuButton.style.width = '200px';
//左側のスペース
MenuButton.style.marginLeft = '250px';
//ボタンをクリックしたら
MenuButton.onclick = function () {

/////////////////////////////////////////////////////////////////////////////////////

//年齢更新
/////////////////////////////////////////////////////////////////////////////////////

  var afterRecord = event.record;
  var appId = kintone.app.getId();
  var recId = event.recordId;

  // まず、変更前のデータを取得する
  kintone.api('/k/v1/record', 'GET', {app: appId, id: recId}, function (resp) {

 

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

 

この var recId = event.recordId という部分のrecordIdが一覧表示画面では使用できないらしく,recordsに変えてみましたが

やはりエラーは変わりませんでした。

取り急ぎご報告まで申し上げます。

 

 

0
Avatar
Hiro

申し訳ありません。この部分は勘違いでした。

→ この var recId = event.recordId という部分のrecordIdが一覧表示画面では使用できないらしく,recordsに変えてみましたが

どうやら var recId = event.recordId の際に値が取得できていないらしく,それがエラーの原因のようです。

0
Avatar
kazuo urata

Hiroさん、

var recId = event.recordId は、値が「undefined」になっていました。

ただ、それが、この件のエラーの原因ではないのではとも、考えています。

改めて、当方のjsコードを見直しました。

デバッグ文を入れていただけと思っていましたが、

(function() {
"use strict";
.......

こちらのソースコードで、最初にあるべき「"use strict";」が、当方のコピペミスで、抜けていました!

「"use strict";」を入れたjsコードで、再度確認したところ、「年齢フィールドを最新の年齢に更新」まで行かずに、終了しました。

ご指摘の状況の通りです。

この点、とりあえず、ご報告いたします。こちらの確認が不十分で、大変申し訳ございませんでした。

改めて、「"use strict";」を入れたjsコードで、調べ直し致します。 

よろしくお願い申し上げます。

 

 

 

0
Avatar
kazuo urata

Hiroさん、

>var recId = event.recordId は、値が「undefined」になっていました。

>ただ、それが、この件のエラーの原因ではないのではとも

やはり、これが、「エラーの原因」ですね。失礼致しました。

その上で、こちらが、

>それ以外は、デバッグ用の表示、(ex.)「window.alert('ZZZ today ' +today);」などを追加しただけで、     
>変更はしていません。

などと書きましたのは、間違いで、いろいろやっていました。すみません!!

できた、できた、などと言っていたのは、次のようなコード部分を持っていたからでした。

もしも何か参考になればと思い、追記いたします。先の記載のこと、重ねてお詫び申し上げます。

(location.reload(); で更新されはしますが。)

.......
  // レコードの全件取得
  var parmAL = {  
     "app":2419,  
  };  
  
  kintone.api("/k/v1/records",  
      "GET",parmAL,  
       function(event){console.log(event);},  
       function(err){console.log(err);}  
  )

  //レコードの数取得
  var resplen = event.records.length;

  //書き換え用
  var params = {
    "app" : appId,
    "records" : []
  };
  // レコード番号を繰り返しアラート表示
  for (var i=0; i < resplen ; i+=1){

 //レコード番号を取得
 var recno = event.records[i].レコード番号.value;
 //フィールドから生年を取得
 var nen = event.records[i].year.value;
 //フィールドから生月を取得
 var tuki = event.records[i].month.value;
 //フィールドから生日を取得
 var nichi = event.records[i].day.value;

 //関数で計算
 var valBirthday = getYearMonth(nen,tuki,nichi, i);

    var x_today=new Date();
    var y_today=x_today.getFullYear()*10000+x_today.getMonth()*100+100+x_today.getDate();

    // 生年月日一列に
    var x_birthday=parseInt(nen + tuki + nichi);

    var x_valBirthday = Math.floor((y_today-x_birthday)/10000);

 params["records"][i] = {
   "id" : recno,
   "record" : {
     "agec" : {
       "value" : x_valBirthday
     }
   }
 };

  } //for終了

  kintone.api(kintone.api.url('/k/v1/records', true), 'PUT', params).then(function(resp) {
  // 成功時
  alert("更新成功");
  location.reload(); // 成功したら画面を更新
  }, function(resp) {
  // 失敗時
  alert("更新失敗");
  });

.....

 

 

 

 

 

 

 

 

1
Avatar
Hiro
 

kazuo urataさん

 

お世話になっております。

いつもお早いお返事ありがとうございます!

あれから色々調べ、試行錯誤した結果、以下のプログラムで希望した結果を得ることができました!

根気強くお付き合いいただき本当にありがとうございました。

(function() {
    "use strict";


    //書き換え用
    var params = {
      "app" : 37,
      "records" : []
    };

    //実際のプログラム
    fetchRecords(kintone.app.getId()).then(function(records) {
        console.log(records);
        console.log(records.length);
        console.log(records[0]['レコード番号'].value);
        console.log(records[0]['month'].value);
        //繰り返し用変数(レコード数取得)
        var kurikaeshi = records.length;
        //計算結果記録用配列

        //構造体にレコードほうりこむよう
        var recNo = 0
        //2個目のfor分の回転数
        var kaiten = kurikaeshi / 100

        //2個目のfor文 PUT用
        for(var Y = 0; Y < kaiten; Y++){

        //1個目のfor文 GET用
        for(var X = 0; X < 100; X++){
        //最新年齢計算 → 関数
        var valBirthday = getYearMonth(records[recNo]['year'].value, records[recNo]['month'].value, records[recNo]['day'].value);

        //paramsの配列0~99に毎回データを入れていく
        params["records"][X] = {
               "id" : records[recNo]['$id'].value,
               "record" : {
               "agec" : {
               "value" : valBirthday
                }
              }
            };

        //変数をキレイに
        valBirthday = 0;
        //recNoたしこみ
        recNo++;
      }//1個目のfor文のおしまい


      //実際の更新処理
      kintone.api(kintone.api.url('/k/v1/records', true), 'PUT', params).then(function(resp) {
       // 成功時
       console.log(params);
      }, function(error) {
       // 失敗時
       console.log(error);
     });

    }//2個目のforのおしまい

    });//実際のプログラムのおしまい



       //以下,関数
      ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////

})();

1
Avatar
福森 豊和

Hiroさま

Kazuo urataさま

お世話になります。

当方も同様なことを考えており、レコード一覧画面で一括更新をしたく

お二人のこの内容を取り込んで作成してみましたが

どうやってもJavaScript初心者の私にはうまくできません。

できればフルのスクリプトを頂けると助かります。

よろしくお願いいたします。

 フィールド:誕生日(yyyy-mm-dd型)

 フィールド:基準日(yyyy-mm-dd型) →最新日付を入力したい

 フィールド:年齢(number型)

 

0
ログインしてコメントを残してください。