お世話になっております。
下記投稿にてやり取りをさせていただいておりますが,REST APIを使用するためこちらに改めて投稿させていただきます。
レコード詳細画面・一覧表示画面でのフィールド値変更が定着しない
上記の投稿を経て,一覧画面に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);
})
})();
9件のコメント
Hiro さん
プログラムを一瞥しただけでは、どこに問題があるのか、わかりませんでした。
「ボタンをクリックしても何も起こらない状況」とのことで、この様な場合のデバッグ方法として、
1.元のソースをバックアップしておく
2.プログラムを最小限に減らして、動作確認 → 動作したら少しずつ拡張する
この手順が、良いかと思います。少し時間はかかりますが、急がば回れ。で。
例えば、第一ステップでは、
こんな感じで、最小限にして、まずは動くことを確認します。
(上記コードは適当です。動かないかも)
そのあとに、必要なコードをコピペで継ぎ足していけば、原因がつかめるかもしれません。
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づつずらして、
繰り返し処理すれば、できそうな気がします。
よろしくお願い致します。
上海レンユアー松村様,kazuo urata様
ご丁寧にコメントしていただき誠にありがとうございます。
ご教授いただいた点を修正してみまして,結果が出ましたらまた
ご報告させていただきます。
返信が遅れてしまい申し訳ありません。
お世話になっております。
その後返信が遅くなり申し訳ありません。
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に変えてみましたが
やはりエラーは変わりませんでした。
取り急ぎご報告まで申し上げます。
申し訳ありません。この部分は勘違いでした。
→ この var recId = event.recordId という部分のrecordIdが一覧表示画面では使用できないらしく,recordsに変えてみましたが
どうやら var recId = event.recordId の際に値が取得できていないらしく,それがエラーの原因のようです。
Hiroさん、
var recId = event.recordId は、値が「undefined」になっていました。
ただ、それが、この件のエラーの原因ではないのではとも、考えています。
改めて、当方のjsコードを見直しました。
デバッグ文を入れていただけと思っていましたが、
(function() {
"use strict";
.......
こちらのソースコードで、最初にあるべき「"use strict";」が、当方のコピペミスで、抜けていました!
「"use strict";」を入れたjsコードで、再度確認したところ、「年齢フィールドを最新の年齢に更新」まで行かずに、終了しました。
ご指摘の状況の通りです。
この点、とりあえず、ご報告いたします。こちらの確認が不十分で、大変申し訳ございませんでした。
改めて、「"use strict";」を入れたjsコードで、調べ直し致します。
よろしくお願い申し上げます。
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("更新失敗");
});
.....
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のおしまい
});//実際のプログラムのおしまい
//以下,関数
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////
})();
Hiroさま
Kazuo urataさま
お世話になります。
当方も同様なことを考えており、レコード一覧画面で一括更新をしたく
お二人のこの内容を取り込んで作成してみましたが
どうやってもJavaScript初心者の私にはうまくできません。
できればフルのスクリプトを頂けると助かります。
よろしくお願いいたします。
フィールド:誕生日(yyyy-mm-dd型)
フィールド:基準日(yyyy-mm-dd型) →最新日付を入力したい
フィールド:年齢(number型)