Как передать уникальные значения из таблицы Google в шаблон электронной почты HTML - PullRequest
0 голосов
/ 12 июля 2020

У меня есть таблица Google с данными проекта (код проекта, имя, даты руководителей проекта и т. Д. c), и я пытаюсь получить данные строки для уникальных значений в этом случае электронных писем. Если, например, электронное письмо johndoe@testmail.com появляется x количество раз, данные строки должны быть захвачены и переданы в файл html, а затем отправлены по электронной почте johndoe@testmail.com в том же случае в другие электронные письма. Таким образом, определенные c руководители проектов должны получать электронные письма только по проектам, которые они возглавляют. У меня новичок ie в JavaScript / GA, я провел массу исследований, но не смог заставить его работать. Я буду признателен за помощь с этим.

Скрипт электронной почты, который читает лист

function Getdata(){

const ss= SpreadsheetApp.getActiveSpreadsheet();
const ws= ss.getSheetByName("Projects");
const headers= ws.getRange("A1:J").getValues();
const Project_Code = headers[0][0];
const End_Date = headers[0][1];
const Project_Name = headers[0][2];
const New_End_Date = headers[0][3];
const Contact_Finance = headers[0][5];
const Update_client = headers[0][6];
const Project_Leader = headers[0][7];
const Email = headers[0][11];

const lr = ws.getLastRow();
const tableRangeValues=ws.getRange(2,1, lr-1,9).getDisplayValues();

const htmlTemplate = HtmlService.createTemplateFromFile("Notify") 
htmlTemplate.Project_Code = Project_Code;
htmlTemplate.End_Date= End_Date;
htmlTemplate.Project_Name= Project_Name;
htmlTemplate.New_End_Date=Complete;
htmlTemplate.Contact_Finance=Contact_Finance;
htmlTemplate.Update_client=Upadate_client;
htmlTemplate.Project_Leader=Project_Leader;
htmlTemplate.tableRangeValues=tableRangeValues;

const htmlForEmail = htmlTemplate.evaluate().getContent();


// This is the part where email loop should happen? and only send emails to individual project leaders listing only the projects they work on.

MailApp.sendEmail({
to: // emails based on loops?
subject: 'Projects Ending',
htmlBody: htmlForEmail,
//Logger.log(tableRangeValues);
 });
}

1 Ответ

2 голосов
/ 13 июля 2020

Как разделить 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>
...