日数集計について

いつも大変お世話になっております。
以下の項目で、区分別の日数を集計したいですが
「総日数」は同じ日を除いて計算できるようになんとかできましたが
 さらに「区分」で分けた際の集計となると全然さまよいまして
なにかアドバイスいただけると幸いです。

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

(function () {
“use strict”;
kintone.events.on([“app.record.create.show”, “app.record.edit.show”,
“app.record.create.change.Table”, “app.record.edit.change.Table”,
“app.record.create.submit”, “app.record.edit.submit”,
“app.record.create.change.日付”, “app.record.edit.change.日付”, “app.record.index.edit.change.日付”,
“app.record.create.change.区分”, “app.record.edit.change.区分”,“app.record.index.edit.change.区分”,
“app.record.create.change.開始”, “app.record.edit.change.開始”,“app.record.index.edit.change.開始”,
“app.record.create.change.終了”, “app.record.edit.change.終了”,“app.record.index.edit.change.終了”,
“app.record.create.change.休憩”, “app.record.edit.change.休憩”, “app.record.index.edit.change.休憩”,

], function (event) {
var record = event.record;
var mwork = {
‘国内日数’: moment.duration(0),
‘アジア日数’: moment.duration(0),
‘アメリカ日数’: moment.duration(0),
};

var dailyWHours = {};//毎日
var table = record.Table.value;

table.forEach(function (row, index) {
var startTime = row.value.開始.value;
var endTime = row.value.終了.value;

var whours = moment.duration(row.value.終了.value).subtract(moment.duration(row.value.開始.value)).subtract(Number(row.value.休憩.value), ‘hours’);

if (whours.as(‘hours’) <= 0) {
row.value.終了.error = ‘開始 > 終了’;
} else { //whours.as(‘hours’) > 0
row.value.総時間.value = whours.as(‘hours’);
var dt1 = row.value.日付.value;

if (dt1) {
if (!dailyWHours.hasOwnProperty(dt1)) {//hasOwnProperty() メソッドは、オブジェクト自身が指定されたプロパティを持っているかどうかを示す真偽値を返します。
dailyWHours[dt1] = {
whours: whours.as(‘hours’),
table_index: index
};
} else {
dailyWHours[dt1].whours += whours.as(‘hours’);
dailyWHours[dt1].table_index = index;
}
}
var kubun = row.value.区分.value + ‘日数’;
if (mwork.hasOwnProperty(kubun)) {
// mwork[kubun] = mwork[kubun].add(whours);
mwork[kubun] = mwork[kubun].add(dailyWHours);
}

}

});

Object.keys(mwork).forEach(function (key) {//mwork 各合計類計算
// record[key].value = mwork[key].as(‘hours’);
record[key].value = mwork[key].as(dailyWHours);
});

record[‘総日数’].value = Object.keys(dailyWHours).length;//総日数計算

return event;
});
})();

kintoneの標準機能で自動計算のIF関数はご存じでしょうか?
今回であれば、そちらの機能が便利かと思います。

jsで行うのであれば、集計の条件分岐にswitchを使用すれば、
区分の値で集計先を分けることが可能かと思います。

岡崎 光輝様

お世話になっております。
アドバイスいただき、誠にありがとうございます。

今回は同じ日付に区分が違ったりすることもある想定で
var mwork = {
‘国内日数’: moment.duration(0),
‘アジア日数’: moment.duration(0),
‘アメリカ日数’: moment.duration(0),
};

Object.keys(mwork).forEach(function (key) {//mwork 各合計類計算
// record[key].value = mwork[key].as(‘hours’);
record[key].value = mwork[key].as(dailyWHours);
});

みたいに区分別に合計を計算したかったがうまく定義できなくて・・・

教えていただいたIF関数で計算して見たいですが
SUM(IF(CONTAINS(区分, “ヨーロッパ”),1,0))

⇒ 例えばヨーロッパを選択したときに、カウントとして1として
合計をしたいですが、カウントでは文字列となるみたいでその合計ができなくて・・

お忙しいところ恐縮ですが、再度アドバイスいただけることは可能でしょうか?
どうぞよろしくお願い致します。

 

IF(CONTAINS(区分,"国内"),SUM(計算),0)

のようにしたら動きました。

 

ただ、24時をまたぐことはないのでしょうか?

区分が海外なので時差とかは考慮しなくていいのかはわかりませんでした。

harada様

お世話になっております。
アドバイスいただき、誠にありがとうございます。

恐れ入りますが、今回計算する合計が時間数ではなく、日数となります。
総時間数とかが入って混乱させて申し訳ございません。

失礼しました。

そもそも、SUM(計算)するとテーブル全体の合計時間でした。

(function () {
"use strict";
kintone.events.on(["app.record.create.show", "app.record.edit.show",
"app.record.create.change.Table", "app.record.edit.change.Table",
"app.record.create.submit", "app.record.edit.submit",
], function (event) {
var record = event.record;

const domestic_count = []
var table = record.Table.value;

table.forEach(function (row, index) {
switch(row.value.区分.value){
case '国内':
domestic_count.push(row.value.日付.value)
break
default:
console.log("nothing")
}
});
const noduplication = Array.from(new Set(domestic_count))
record.国内日数.value = noduplication.length

return event;
});
})();

元のJavascriptがよくわからなかったです。

国内、アジア、アメリカ、ヨーロッパしかないのであれば、

それぞれ配列を用意して、tableの各行でswitch文で分けて配列に入れる

日付は重複しないのが要望のようなので重複をSetで消す。

コードは、国内分だけですので適宜追加してください。

harada様

 

お世話になっております。
お忙しいなか、再度コードのご提供までいただき、誠にありがとうございます。

こんなにコンパクトでなんと日付の合計ができるとは
Setを初めて知った私にとっては、奇跡でした!
お忙しいなか、大変恐れ入りますが

const noduplication = Array.from(new Set(domestic_count))
でどんな動きになってますでしょうか?
どうやって、同じ日付を1日としてカウントされているかが不思議です・・・
お手すきな際にコードのご解説していただけることは可能でしょうか。

また、大変恐縮ではございますが、
例えば区分に「国内半日」・「アジア半日」と設定した場合、
1日で①国内半日 ②アジア半日の際に
「国内日数」:1レコードで、1日ではなく、0.5日としてカウントさせる際は
record.国内日数.value = noduplication.length /2;
で大丈夫でしょうか?
なにかアドバイスいただけると幸いです。
どうぞよろしくお願い致します。

const noduplication = Array.from(new Set(domestic_count))

JavaScriptで重複排除を自分で実装してはいけない(Setを使う) - Qiita
https://qiita.com/netebakari/items/7c1db0b0cea14a3d4419

をみて使いました。

harada様

 

お世話になっております。
早速お返事いただき、誠にありがとうございます。
いただいたページを参考にさせていただきます。
本当にありがとうございました!
とても助かりました!
今後ともどうぞよろしくお願い致します。

例えば区分に「国内半日」・「アジア半日」と設定した場合、
1日で①国内半日 ②アジア半日の際に
「国内日数」:1レコードで、1日ではなく、0.5日としてカウントさせる際は

record.国内日数.value = noduplication.length /2;

という考え方で良いとおもいます。配列の数やswitch文も対応が必要です。

重複なしの国内日数が2、国内半日が1日で0.5となる場合は、2 + 0.5の合計をフォーム側に戻す必要があります。念のため。

record.国内日数.value = noduplication.length + (noduplicationhalfday.length / 2);

harada様

 

お世話になっております。
お忙しいなか、何度も貴重なアドバイスいただき、誠にありがとうございます。

とても勉強になりました。
本当にありがとうございました!

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