maeda.d
(deMae)
1
実現したいこと
サブテーブルにjsで値をセットした場合、テーブル内の集計を行う計算フィールドがうまく動作しないことがあります。計算処理を必ず動作させる方法はないでしょうか。
アプリの詳細
売上を集計するアプリを作成しています。
jsで生成したボタンを押すと、他アプリから売上データを取得し、サブテーブルにセットしています。
サブテーブル内の金額を計算フィールドを使用して合計値を表示しています。
実行したコード
button.addEventListener('click', async function() {
// レコード情報を取得
var record = kintone.app.record.get()
// ------------------------
// 売上データを取得する処理
// ------------------------
// クライアントの作成
const client = new KintoneRestAPIClient();
// リクエストパラメータの設定
const params = {
app: APP_ID,
fields: fields,
condition: query,
orderBy: orderBy,
};
// レコード取得
const itemRecords = await client.record.getAllRecords(params);
// サブテーブルを生成する処理
subtable.push({
value:{
// 売上データ(itemRecords)から明細行を生成
}
});
// サブテーブルにセット
record.record.Table.value = subtable;
// レコード情報をセット
kintone.app.record.set(record);
});
jsで集計する方法に変更できない諸事情
jsと計算フィールドの相性が悪いことは理解しております。
本来なら計算フィールドから数値フィールドに変更し、js側でそのまま合計値を集計させれば済む話なのですが、以下の2点の理由からそれが難しい(というより、できればあまりやりたくない)という状況です。
- 既にかなりの数のアプリで同様の処理を行っており、運用していること
- その計算フィールドを参照して、さらに別の計算を行っていること
(例)[計算フィールドA]+[計算フィールドB]+[数値入力フィールド]+[計算フィールドC]
googleやこのコミュニティで、数日調査してみたのですが、なかなか解決策が見つからず、こちらに投稿させていただきました次第です。
何か足りない情報がありましたら、すぐに追加させていただきます。
どうぞよろしくお願いいたします。
maeda.d
(deMae)
3
Irasさん
返信が遅れてしまいすみません。
はじめまして。返信ありがとうございます。
そしてご丁寧にテストコードまで作ってくださりありがとうございます!
基本動作はその動画とコードの通りです。
【問題の動作について】
その中でいうところの「計算」のフィールドが、たいていの場合はきちんと動作してくれる(自動計算してくれる)のですが、テーブルには新しい行がセットされているのに、合計値だけが再計算してくれない(計算フィールドが空の状態)という現象が時々起こります。
ちなみに、空だった場合、再度ボタンを押すときちんと再計算してくれます。
おそらくkintone側の計算フィールドの処理とkintone.app.record.set()が動く処理のタイミングがずれた場合に起こっているのだと思います。
maeda.d
(deMae)
5
t.noriさん
返信ありがとうございます!
ご連絡が遅くなってしまいすみませんでした。
コードのご提供ありがとうございます。大変助かります。
ぜひ試してみたいと思うのですが、thenの中で処理する場合と、awaitのみで処理する場合とは、同期処理のタイミングが異なる、ということでしょうか?
maeda.d
(deMae)
7
t.noriさん
丁寧に解説、また参考サイトの記載までありがとうございます。
つまり、本来であれば、
const itemRecords = await client.record.getAllRecords(params); // 1
record.record.Table.value = subtable; // 2
kintone.app.record.set(record); // 3
// 4:計算フィールドの自動計算処理
という順番で動いてほしいのが、
const itemRecords = await client.record.getAllRecords(params); // 1
record.record.Table.value = subtable; // 2 処理中・・・
kintone.app.record.set(record); // 3 処理中・・・
// 4:計算フィールドの自動計算処理
// 2完了
// 3完了
という順番になっているために、起こっている現象かもしれない、ということで合っておりますでしょうか?
lenzras
(lras)
9
横ですみません。
ざっくりで試したところ、以下の順番でした。
コード
(function() {
'use strict';
const APP_ID = kintone.app.getId();
// クリックのコールバックを定義します。@deMase さん のコードのように、addEventListenerのコールバックに直接書くのも動作は同じです。
const onClickHandler = async function () {
console.log('---ボタンをクリックしました');
console.log('現在のレコードを取得します');
const currentRec = kintone.app.record.get();
console.log('現在のレコードを取得しました', currentRec);
console.log('別レコードを取得します。');
// テストのため、同アプリ。別アプリでも可
const params = {
app: APP_ID,
};
const client = new KintoneRestAPIClient();
const {records: otherRecords} = await client.record.getRecords(params);
console.log('別レコードを取得しました。', otherRecords);
console.log('テーブルを生成する')
// テストのため、処理をシンプル化。
otherRecords.forEach((otherRecordItem) => {
const newRows = otherRecordItem.テーブル.value
.map((row) => ({
id: '',
value: {
数値: {
type: 'NUMBER',
value: Number(row.value.数値.value) * 2},
数値_0: {
type: 'NUMBER',
value: Number(row.value.数値_0.value) * 3
},
計算_row: {
type: "CALC",
value: "" // 自動計算されるか、試しに空
}
}
}))
currentRec.record.テーブル.value.push(
...newRows
)
});
console.log('反映させる', currentRec);
kintone.app.record.set(currentRec);
}
kintone.events.on('app.record.edit.show', function() {
console.log('--- レコード編集画面を表示した後イベント');
console.log('ボタンを追加します。');
const btnContainerEl = kintone.app.record.getSpaceElement("button");
const button = document.createElement('button');
button.textContent = "クリック";
btnContainerEl.appendChild(button);
console.log('ボタンにクリックイベントを追加します');
button.addEventListener('click', onClickHandler);
});
// 以下はイベントの順を表すためのもので、処理はありません。削除しても、動作は変わりません。
kintone.events.on('app.record.edit.change.数値', function() {
console.log('---「数値」フィールドは更新されました ');
// テーブル内の数値が変更後、計算される。
});
})();
動作