В таких задачах мне нравится использовать преобразование массивов к массивам объектов, чтобы не следить за порядком колонок и не думать, куда добавлять результат. Основное решение заключается в том, чтобы собрать уникальные ключи через reduce
и пересчитать для каждого вхождения результат. Также можно считать суммы, количество и т.п.
function groupOperationsByAppsScript() {
const sheet = SpreadsheetApp.getActive().getSheetByName('Групповые операции скриптами');
const values = toCollection_(sheet.getDataRange().getValues());
const data = values.reduce((a, c) => {
const outs = c['направление расходов'].__val;
if (outs) {
if (!a[outs])
a[outs] = {
result: 0,
};
a[outs].result += c['расходы'].__val;
}
const ins = c['направление прибыли'].__val;
if (ins) {
if (!a[ins])
a[ins] = {
result: 0,
};
a[ins].result += c['прибыль'].__val;
}
const adins = c['направление доп. расходов'].__val;
if (adins) {
if (!a[adins])
a[adins] = {
result: 0,
};
a[adins].result -= c['доп. расходы'].__val;
}
return a;
}, {});
const directs = [];
const balance = [];
Object.keys(data)
.sort()
.forEach((key) => {
directs.push([key]);
balance.push([data[key].result]);
});
sheet.getRange(2, values[0]['направление'].__col, directs.length, directs[0].length).setValues(directs);
sheet.getRange(2, values[0]['баланс'].__col, balance.length, balance[0].length).setValues(balance);
}
Преобразование строки в объект
function toCollection_(array) {
return array.slice(1).map(
(_, rowIndex) =>
array[0].reduce((rowCollection, header, columnIndex) => {
rowCollection[
String(header)
.toLowerCase()
.replace(/[\r\n]+/g, ' ') || `__col${columnIndex}`
] = {
__col: columnIndex + 1,
__row: rowIndex + 2,
__val: array[rowIndex + 1][columnIndex],
};
return rowCollection;
}, {}),
[],
);
}
Пример данных и рабочий код в Таблице https://docs.google.com/spreadsheets/d/1MqeW7LkEUcsDH8lUksXBLHWmSeu8up2Jr_3ujVwE4SE/edit#gid=1914353719&range=A1