Как разделить 1 массив на несколько массивов по значению ключа
Я предлагаю использовать Array.prototype.reduce для организации вашего массива строк в объект, который имеет электронные письма в качестве ключей и массивы строк как значений (пример ниже). В итоге вы получите
{
"person1@email.com": [[value1],[value2],[value3]],
"person2@email.com": [[value1],[value2],[value3]],
// etc.
}
См. Ниже редуктор, который соответствует c вашим потребностям, но в целом идея такова:
function reducer(object, arrayOfValues) {
const key = arrayOfValues[INDEX_OF_KEY];
if (!(key in object)) object[key] = [];
object[key].push(arrayOfValues);
return object;
}
const groupedByKey = valuesFromSheet.reduce(reducer, {});
Вы можете настроить al oop через Объект с относительно недавним добавлением к глобальному Object
: Object.entries()
. Это вернет массив массивов, так что вы можете отправить электронное письмо с Array.prototype.forEach
(пример ниже).
Для каждого электронного письма создайте новый шаблон. Вам следует воспользоваться возможностью создания шаблонов в Apps Script, чтобы разбить ваши шаблоны на модули. Когда вы добавляете все свои стили, а затем начинаете добавлять теги сценариев <? ?>
, это может стать настоящим беспорядком. Ниже я продемонстрировал, как можно отделить шаблон таблицы от основного шаблона электронной почты и получить вложенные шаблоны. Это гораздо более управляемый и отлаживаемый / тестируемый.
Наконец, я также всегда рекомендую определять ваши заголовки в одном месте (см. Объект HEADINGS
ниже), чтобы вы могли легко изменить порядок заголовков позже, не обновляя код в нескольких местах (простой способ внести ошибку в ваш скрипт).
Code.gs
const HEADINGS = {
PROJECT_CODE: 0,
END_DATE: 1,
PROJECT_NAME: 2,
NEW_END_DATE: 3,
CONTACT_FINANCE: 5,
UPDATE_CLIENT: 6,
PROJECT_LEADER: 7,
LAST_NAME: 8,
FULL_NAME: 9,
EMAIL: 11
};
function Getdata(){
const ss = SpreadsheetApp.getActiveSpreadsheet();
const ws = ss.getSheetByName("Projects");
const headers = makeHeaders(ws.getRange("A1:J").getValues()[0]);
const lastRow = ws.getLastRow();
const tableRangeValues = ws
.getRange(2, 1, lastRow - 1, HEADINGS.EMAIL + 1)
.getDisplayValues();
const groupedByEmail = tableRangeValues.reduce(emailReducer, {});
Object.entries(groupedByEmail).forEach(function(emailGroup) {
const [email, values] = emailGroup;
MailApp.sendEmail({
to: email,
subject: "Projects Ending",
htmlBody: makeHtmlEmail(values[0][HEADINGS.FULL_NAME], headers, values)
});
});
}
function emailReducer(groups, row) {
const email = row[HEADINGS.EMAIL];
if (!(email in groups)) groups[email] = [];
groups[email].push(row.slice(HEADINGS.PROJECT_CODE, HEADINGS.FULL_NAME + 1));
return groups;
}
function makeHtmlEmail(name, header, values) {
const emailTemplate = HtmlService.createTemplateFromFile("Notify");
emailTemplate.name = name;
emailTemplate.header = header;
emailTemplate.values = values;
return emailTemplate.evaluate().getContent();
}
function makeTable(header, values) {
const table = HtmlService.createTemplateFromFile("table");
table.header = header;
table.values = values;
return table.evaluate().getContent();
}
function makeHeaders(headerRow) {
return [
headerRow[HEADINGS.PROJECT_CODE],
headerRow[HEADINGS.END_DATE],
headerRow[HEADINGS.PROJECT_NAME],
headerRow[HEADINGS.NEW_END_DATE],
headerRow[HEADINGS.CONTACT_FINANCE],
headerRow[HEADINGS.UPDATE_CLIENT],
headerRow[HEADINGS.PROJECT_LEADER]
];
}
Notify. html
<body>
<head><!-- style, etc... omitted for clarity --></head>
<body>
<p>Hi <?= name ?></p>
<!-- details omitted for clarity -->
<h4> Project Details </h4>
<?!= makeTable(header, values) ?>
</body>
</body>
таблица . html
<!-- styling omitted for clarity -->
<table>
<thead>
<tr>
<? header.forEach(heading => { ?>
<th><?= heading ?></th>
<? }) ?>
</tr>
</thead>
<tbody>
<? values.forEach(row => { ?>
<tr>
<? row.forEach(value => { ?>
<td><?= value ?></td>
<? }); ?>
</tr>
<? }); ?>
</tbody>
</table>