サブテーブルの計算の仕方

いつもお世話になっております。

サブテーブルの計算のさせ方について質問させてください。

サブテーブル内で、自動計算をさせたいと思っています。

分類が小計を選択した場合に、該当するAとB区分が同じ場合、小計を出す、という感じです。

(function() {
  'use strict';
  var events = [
      "app.record.create.change.分類",
        "app.record.edit.change.分類",
        "app.record.create.change.A",
        "app.record.edit.change.A",
        "app.record.create.change.B",
        "app.record.edit.change.B",
        "app.record.create.change.数量",
        "app.record.edit.change.数量",
        "app.record.create.change.単価",
        "app.record.edit.change.単価"
    ];
  kintone.events.on(events, function(event) {
    var record = event.record;
    var row = event.changes.row;
    var mainTable = event.record.テーブル.value;
  var sumSyokei_tanka = 0;
    
    if(row){
      //小計の集計
    if(row.value['分類'].value !== "表紙" && row.value['A'].value && row.value['B'].value){
        //計算
        for (var i =0; i < mainTable.length; i++) {
            if(mainTable[i].value['分類'].value != "小計" && mainTable[i].value['A'].value == row.value['A'].value && mainTable[i].value['B'].value == row.value['B'].value){
                  if(mainTable[i].value['数量'].value && mainTable[i].value['単価'].value){
                    sumSyokei_tanka += Number(mainTable[i].value['数量'].value) * Number(mainTable[i].value['単価'].value);
                  }
            }
          }
          //書き込み
        for (var j = 0; j < mainTable.length; j++) {
                if(mainTable[j].value['分類'].value == "小計" && mainTable[j].value['A'].value == row.value['A'].value && mainTable[j].value['B'].value == row.value['B'].value){
                    if(sumSyokei_tanka !== 0){
                      mainTable[j].value['単価'].value = sumSyokei_tanka;
                      break;
                    }
              }
          }
      }
    }
    return event;
 });
})();

ただ、分類小計で選択すると処理が走り、単価が書き換えられ、単価が書き換えられるからまた処理が走る…という、2度もループが走ることになります。

また、空白行がある場合は無限ループに陥ります。

自動でなんとか集計させたいのですが、いい方法はないでしょうか?

ご教授お願いします。

matsu様

>分類が小計を選択した場合に、該当するAとB区分が同じ場合、小計を出す
…という仕様であれば,javascriptでなくてもできそうですが,
計算フィールドや文字列(1行)の自動計算が使えないような制限はありますか?
もし,フィールドの計算でまかなえるなら,javascriptよりも管理しやすいかと思います.

また,コードではchangeイベントが発火するたびにテーブル行すべてに対して処理を行っているように見えます.
分類,単価,小計が1行内にあり,それらの自動計算で良いならchangeイベントが発火した行だけで良いように思います.

なお,想定されている自動計算のトリガーは「分類が変わったとき」になりますが,
コードでは数量や単価もchangeイベントのトリガーになっています.
これだと分類が変わって処理が走れば,処理によって単価が「変わる」ので,
当然単価のchangeイベントが走ることになります.
なので,分類が変わったとき以外でchangeイベントを発火する必要がないなら,
トリガーに含めなくて良いかと思います.

上記について,確認ください.

TO様

ご返信ありがとうございます。

>分類が小計を選択した場合に、該当するAとB区分が同じ場合、小計を出すを計算フィールドで

計算でもいけますか?

分類 A区分 B区分 数 単価 金額

明細 1 1 1 300 300

明細 1 1 2 200 400

小計 1 1 1 700 700

上記のように700円の単価を出す計算式がわかりません…

もし計算でいけるのであればそうしたいです。

 

>発火した行だけ対象の処理

発火以外の行を集計したいので全テーブル回しています。

 

>分類が変わった時だけでいいのでは?

分類が変わった時、数が変更された時、単価が変更された時、

全てのタイミングで自動で数字が変更されればと思っています。

matsu様

テーブル内に小計を用意する仕様なのですね…想定していませんでした.
テーブル外に小計用の計算フィールドを置いて,SUM関数を使うことでテーブル内データの合計が可能ですが,
テーブル内で小計できたほうが良いですか?
上記が許容できるなら,テーブルに例えば「A金額」,「B金額」のように区分別に計算するフィールドを別にすることで,
テーブル外の小計フィールドに,任意の区分における小計求めることができます.
区分が増えるのであれば大変ですが,ある程度決まっているならこういう手もあるかと思います.

許容できないのであればjavascriptになるかと思います.
重複して処理が走る問題については,数量,単価ではなく,
おそらくフィールド上で計算していると思われる「金額」をトリガーにするのが良いかと思います.
これなら,入力によって数量,単価が変われば金額が変わって処理が走りますし,
処理によって金額が変わる箇所については,changeイベントの最初にrow(changeイベントのトリガーになっている行)の分類が"小計"であれば処理せずに抜ける,というコードを加えることで,処理が重複することはなくなると思います.
(処理に金額が変わるのは小計の行のみ)

参考になれば幸いです.

 

TO様

分類が小計以外にも他の分類があるため、一概に区分別にSUMするというわけにはいかず、javascriptで処理させてみました。

また、テーブル内の方が見やすいという上司の意見もあります。

 

金額で発火できればよかったのですが、計算フィールドは発火できないみたいなんです。

金額を計算フィールドではなく、数値にしてJS処理で数値を入れ、全体の計算を金額発火の方がスマートですかね?

matsu様

>計算フィールドはchangeイベントの対象外
そうでした.これをいつも忘れてしまいます.

メンテナンス性を考えると,フォーム内でできることはフォーム内のほうが良いようには思います.

現状で問題になっている重複処理と無限ループについて,
無限ループは空白行で起こる,とのことですが,具体的にはどのような状態で起きていますか?
単価,数量が空欄の場合の対応はされていますし,空白行がどのような形で発生するのかわからないので,
どこがループになっているのか把握できていません.
上記について,可能であれば教えてください.

TO様

無限ループに関しては、

if(row.value[‘分類’].value !== “表紙” && row.value[‘A’].value && row.value[‘B’].value){

の部分をif(row.value[‘分類’].value !== “表紙” && row.value[‘A’].value !== “” && row.value[‘B’].value !== “”){

にしていたからでした。

なので、今は無限ループにはなっていないので、一旦は解決しました。

重複に関しては、やろうとしたいことに関しては仕方ない…といった感じでしょうか?

matsu様

今は無限ループになっていないとのこと,よかったです.
重複処理については,仕様上「changeイベントが正常に動作している」といえるのと,
重複処理は小計の単価の値が変更された1回なので,許容してもよいのかな,と思います.
(2回目は小計の単価が変わらないのでchangeイベントが発火しない)

未検証ですが,kintone.events.onのスコープ外(var events = ~があるところ)で判定用変数を宣言して,
初回の発火時,小計の単価が発火前から変わるなら判定用変数に何かを格納(true/falseなど),
2回目の発火時に判定用変数で初回発火の確認,何もせずに抜ける際に判定用変数を空にする,
という運用であればやりたいことに近い状態になるかと思います.

少しだけ,コードが複雑化する(変数宣言,設定と小計単価の前後比較など)ので,
やりたいことの規模と相談していただければ良いかと思います.

TO様

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

判定用変数の件、やってみたいと思います!

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

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