Я пытаюсь написать скрипт приложений Google, похожий на SUMIF в листах Google. Моя цель - суммировать все значения в часах столбца для всех строк, которые содержат определенный идентификатор (id) в течение определенного периода (период столбца), которые помечены как продуктивные (продуктивный = 1) и значение единицы столбца для конкретной строки отличается от строки, указанной ниже. По какой-то причине это не работает. Я новичок в javascript и не могу понять, почему он не работает. Я попытался определить функцию суммы, а затем вызвать ее для каждого значения в столбце идентификатора (около 7000 строк).
//Productive hours
//=if ($A2<> "", SUMIFS(hours,hrmid,$AC2, productive,1,period,$A2)-SUMIFS(hours,hrmid,$AC2, productive,1,period,$A2, units,"Revision Stand-by"), "")
function sumPrdHrs (item) {
var hoursToSum = 0;
var summedHrs = [];
var hours = ytdSheet.getRange(2,18, ytdSheet.getLastRow()).getValues();
var productive = ytdSheet.getRange(2,33, ytdSheet.getLastRow()).getValues();
var units = ytdSheet.getRange(2, 9, ytdSheet.getLastRow()).getValues();
var id= ytdSheet.getRange(2,29, ytdSheet.getLastRow()).getValues();
var period = ytdSheet.getRange(2,1, ytdSheet.getLastRow()).getValues();
//var date = ytdSheet.getRange(2,1, ytdSheet.getLastRow()).getValues();
for (var i=0; i < hours.length; i++) {
if ((id[i][0] == item) && (productive[i][0] == 1) && (period[i][0] == period[i+1][0]) && (units[i][0] != "Revision Stand-by")) {
hoursToSum += hours[i][0];
summedHrs.push(hoursToSum);
}
}
return sumPrdHrs;
console.info(summedHrs);
}
function productiveHrs () {
var id= ytdSheet.getRange(2,29, ytdSheet.getLastRow()).getValues();
var sumHours = [];
id.forEach(function(item,i) {
var summedHours = sumPrdHrs (item);
//sumHours.push(summedHours);
//Logger.log(summedHours);
// ytdSheet.getRange(2,31,hrmId.length,1).setValues(summedHours);
});
}
Обновил мой ответ ниже. Также были внесены некоторые изменения в ваши условия, которые, как мне кажется, лучше подходят для того, что вы делаете. Пока что он делает то, чего хотят ваши функции. Если у вас есть дополнительные условия, которые вы хотите добавить, вы сможете легко их добавить. не стесняйтесь комментировать ниже, если вам нужна помощь.
Я вижу некоторые сомнительные строки в вашем коде, я расскажу о них ниже в сравнении с кодом, который я создал и протестировал на основе того, чего вы хотите достичь, и все еще имеет смысл.
function sumPrdHrs (item) {
var hoursToSum = 0;
// Removed summedHrs array. Based on your code structure, you want to return the sum of productive hours.
// I don't see any use of creating an array when you can already sum it up directly.
var hours = ytdSheet.getRange(2,18, ytdSheet.getLastRow()).getValues();
var productive = ytdSheet.getRange(2,33, ytdSheet.getLastRow()).getValues();
var units = ytdSheet.getRange(2, 9, ytdSheet.getLastRow()).getValues();
var id= ytdSheet.getRange(2,29, ytdSheet.getLastRow()).getValues();
var period = ytdSheet.getRange(2,1, ytdSheet.getLastRow()).getValues();
for (var i=0; i < hours.length; i++) {
// In the conditions below, I don't get why you want to compare current period to the period below.
// It always makes the last item with the same period invalid since there is no last date.
// But will include it since it might be important to you
// You also have another condition mentioned but wasn't added initially so I skipped it for now. But feel free to add it on your code.
if ((id[i][0] == item) && (productive[i][0] == 1) && (period[i][0] == period[i+1][0]) && (units[i][0] != "Revision Stand-by")) {
hoursToSum += hours[i][0];
// Total hours is calculated per item, that's all you need to return below.
}
}
return hoursToSum;
}
// Based on what you want, this will sum all hours per item that follows the conditions above.
function productiveHrs () {
// This will transform the 2d array into 1d array
var id = ytdSheet.getRange(2,29, ytdSheet.getLastRow()).getValues().flat();
// We want to loop only the unique items, removing duplicates
id = id.filter((item, i, ar) => ar.indexOf(item) === i);
var sumHours = [];
id.forEach(function(item,i) {
// Skip blank/invalid items
if (item) {
var summedHours = sumPrdHrs(item);
sumHours.push(summedHours);
}
});
Logger.log(sumHours);
}
Это мой образец листа
это результат
Видите, что общее количество предметов b
, которых должно быть 14, равно 10, верно? Это из-за условия периода, которое проверяет период ниже. Это то, что я обсуждал выше.
Вместо этого с условием «период против периода ниже» вы можете получить уникальные даты для каждого элемента, а затем суммировать их по дате для каждого элемента.
Это должно быть лучшим способом проверки периода.
// Added time for per item summation of hours
function sumPrdHrs (item, time) {
var hoursToSum = 0;
var hours = ytdSheet.getRange(2,18, ytdSheet.getLastRow()).getValues();
var productive = ytdSheet.getRange(2,33, ytdSheet.getLastRow()).getValues();
var units = ytdSheet.getRange(2, 9, ytdSheet.getLastRow()).getValues();
var id = ytdSheet.getRange(2,29, ytdSheet.getLastRow()).getValues();
var period = ytdSheet.getRange(2,1, ytdSheet.getLastRow()).getValues();
for (var i=0; i < hours.length; i++) {
// Compare period[i][0] to unique period fetched from productiveHrs() instead.
if ((id[i][0] == item) && (productive[i][0] == 1) && (period[i][0] == time) && (units[i][0] != "Revision Stand-by")) {
hoursToSum += hours[i][0];
}
}
return hoursToSum;
}
function productiveHrs () {
// Get unique ids and periods
var id = ytdSheet.getRange(2,29, ytdSheet.getLastRow()).getValues().flat();
var period = ytdSheet.getRange(2,1, ytdSheet.getLastRow()).getValues().flat();
id = id.filter((item, i, ar) => ar.indexOf(item) === i);
period = period.filter((item, i, ar) => ar.indexOf(item) === i);
var sumHours = [];
// Traverse all combination of id and period
id.forEach(function(item,i) {
if (item) {
period.forEach(function(time,j) {
if (time) {
// Pass period to sum hours under item per period
var summedHours = sumPrdHrs(item, time);
// Only push data when where is summedHours
if (summedHours) {
sumHours.push([item, time, summedHours]);
}
}
});
}
});
Logger.log(sumHours);
}
Это пример данных:
Это результат:
Как видите, более красивый и читаемый вывод и условия, которые имели бы смысл.
Если у вас есть уточнения и дополнительные вопросы, не стесняйтесь комментировать ниже.
Спасибо @Marios, я все еще жду комментариев/проверки ОП, поскольку он упомянул некоторые условия, которые я не включил в свой код. Хотя то, чего я думаю, он пытается добиться, уже включено сюда. и если он хочет добавить какие-то условия, он может легко добавить их.
Большое спасибо @Nazi A! Ваше решение отлично решило мою проблему! Я вижу, что не так с моим кодом.
Можете ли вы дать скриншот того, над чем вы пытаетесь работать?