D5 - 如何用 Google Apps Script 搭配 HTML 客制 Google 表单的回应信件?

来到了第五天,关於寄信可以进入比较进阶的操作。但一样先讲结论,如果你很急着用,可以直接使用这份 Add-On: Form Notification,这是 Google Cloud 官方开发的 Add-On,可信度很高。自己写的好处是,如果你突然想要寄送像是网页般的内容(HTML-Based)的内容的话,你可以知道怎麽做。让我们开始吧!

提醒:本篇需要一点点的 HTML 知识,一样是你大概有刷过 W3C 的应该就还可。


今天的目标

今天学妹问你说,「先辈,我们新活动能不能在报名时,就依据他的意愿,给他不同的客制化回答呀?」身为一个工具师,当然义不容辞地试试。今天的关键问题是...

「如何依据 Google 表单的回应客制化回应信件?」

网路上流传的一种解法 是可行但相对,但有没有另外比较靠(厉)谱(害)的写法?也就因此有了这篇。


如何依据 Google 表单的回应客制化回应信件?

假设我们今天想要「依据使用者回应的交通方式,给予不同的交通方式说明」。这次希望加上简单的 HTML 的运用。

Step 1 开启 Google 表单,并从回应的连结中串起 GAS

好,今天我们开一个新的 Google 表单,并将其回应连结到 GAS。

一样执行时会有「需要验证」出现,让我借用一下 D2 的影片。

Step 2 取得 Google Sheet 里面的回应资料并准备寄信

那这边,就会需要跟 D4 一样,读取回应,假设我们今天收到这样的回应们。

因为跟 D4 差不多,主要是设定范围并取得资料,这边我们就加速带过。

function readData() {
  let sheet = SpreadsheetApp.getActiveSheet();
  let startRow = 2;
  let startCol = 2;
  let numRows = 5;
  let numCols = 2;
  let dataRange = sheet.getRange(startRow, startCol, numRows, numCols);
  let data = dataRange.getValues();
  
  return data
}

function sendEmails() {
  let data = readData();
  for (let i in data) {
    let row = data[i];
    let emailAddress = row[0];
    let subject = "Hello";
    let message = "Content";
    MailApp.sendEmail(emailAddress, subject, message);
  }
}

这样在执行时,就会对表单中的收信者,寄出一封名为 "Hello" 的信件。

Step 3 设定客制化的内容

学妹希望针对自行开车的,给予开车路线;也希望针对大众运输的,给予大众运输的路线,两个我们都用图片(网址)来给予。先简单做了个示意图,汽车和捷运的网址分别是 https://i.imgur.com/m9zCXUV.pnghttps://i.imgur.com/h5kT4Fm.png 。之後我们再聊怎麽样寄出 Google Drive 里面的档案。

那设定方式就可以是简单弄一个 function 来达到,进阶班的朋友也可以用三元运算子(Conditional Operator)来写这段。

function customContent(commute_way){
  if(commute_way == "大众运输"){
    return "大众运输请参考: https://i.imgur.com/h5kT4Fm.png";
  }else if (commute_way == "自行开车"){
    return "开车请参考: https://i.imgur.com/m9zCXUV.png";
  }
}

function sendEmails() {
  let data = readData();
  for (let i in data) {
    let row = data[i];
    let emailAddress = row[0];
    let subject = "Subject";
    let message = customContent(row[1]);
    Logger.log(emailAddress +" "+ message);
    // MailApp.sendEmail(emailAddress, subject, message);
  }
}

然後 Print 一下看有没有给予不同的内容。确定都有跟表单上一样,开车给开车的,捷运给捷运的,没问题後就进到下一阶段。

Step 3-1 用 createHtmlOutput 寄出可以直接读取的信件

好,那如果不想还要点连结,除了作为附件(之後会教)外,还有什麽其他的方式?在 GAS 当中,我们是透过用信件送出 HTML 的,收信人预计会收到一个简单的 HTML 档案长这样——

一样,我们看程序码。

function customContent(commute_way){
  if(commute_way == "大众运输"){
    return HtmlService.createHtmlOutput('<span>请参考地图移动:\
                                               <img src="https://i.imgur.com/h5kT4Fm.png" \
                                                alt="大众运输地图"> \
                                        </span>');
  }else if (commute_way == "自行开车"){
    return HtmlService.createHtmlOutput('<span>请参考地图移动:\
                                               <img src="https://i.imgur.com/m9zCXUV.png" \
                                                alt="自行开车地图"> \
                                        </span>');
  }
}

function sendEmails() {
  let data = readData();
  for (let i in data) {
    let row = data[i];
    let emailAddress = row[0];
    let subject = "Subject";
    let message = customContent(row[1]);
    MailApp.sendEmail({
      to: emailAddress,
      subject: subject,
      htmlBody: message.getContent()
  });
  }
}

基本上是直接在 HtmlService.createHtmlOutput() 中写上你的简易 HTML 程序码。并在 MailApp.sendEmail 寄送的部分使用 htmlBody 来送出,记得要在内容的部分加用 getContent() 。这是针对简易版的 HTML,就几行而已的那种。

但如果是复杂版的,可能有动画、大小差异的,又要怎麽处理?此时就要透过 createTemplateFromFile 了。

Step 3-2 用 createTemplateFromFile() 寄出可以直接读取的信件

要使用 createTemplateFromFile(),那我们就会需要 template HTML,而 GAS 里面是可以做到直接创建的。在档案的 + 上按下新增并输入想要的名字。在程序码的部分,再透过 HtmlService.createTemplateFromFile('mrt') 来呼叫。记得不用再加上 .html,纯粹呼叫 mrt 即可。

完整的程序码在这——

function customContent(commute_way){
  if(commute_way == "大众运输"){
    return HtmlService.createTemplateFromFile('mrt')
  }else if (commute_way == "自行开车"){
    return HtmlService.createTemplateFromFile('driving')
  }
}

function sendEmails() {
  let data = readData();
  for (let i in data) {
    let row = data[i];
    let emailAddress = row[0];
    let subject = "Subject";
    let message = customContent(row[1]);
    MailApp.sendEmail({
      to: emailAddress,
      subject: "Your application is approved!",
      htmlBody: message.evaluate().getContent()
    });
  }
}

最後功能会如下的运作, 这边用 Step 3-2 的方式示范,但 Step 3-1 的 Code 也有试过,都行。

透过在 GAS 中创建 HTML File,将其用 HtmlService.createTemplateFromFile 引用为 Template,再在 MailApp.sendEmail({htmlBody}) 中读取。这边要注意的是,和 createHtmlOutput 相比,这边的内容在寄出之前,是使用 message.evaluate().getContent() 这之後再跟大家说明细节。

如果希望在不同时间触发,可以搭配 D3 的 Trigger,或是想要打包成按钮、UI,则可以透过 D2 的打包说明。之後会跟大家说明如何将回应整合进 Google Calendar,并再更之後会说明如何即时的在有人回应表单时,就即时回传客制化的内容。


好,那今天我们知道了要怎麽样:

  1. 单次性针对 Google 表单的结果创建客制化的回应
  2. 客制化的回应中,寄送 HTML 的信件。
  3. 透过 createTemplateFromFilecreateTemplateFromFile 加入简单与复杂的 HTML 档案。

好,那今天就是我们的 D5,原本预计今天要说「依据表单结果客制化回应说有没有报名成功」,但发现篇幅有点多(五千六百多字了囧),所以会拉到之後讲。明天 D6 会继续介绍怎麽将「表单中的回应」丢到「Google Calendar」当中。的方式,如果不想错过可以订阅按赞小铃铛(?),也欢迎留言跟我说你还想知道什麽做法/主题。如果有执行上的疑问,透过留言之外,也可以到 Facebook Group,想成立了几年,感谢这次铁人赛才真的实践,欢迎来当 Founding Member。我们明天见。


<<:  前端工程师也能开发全端网页:挑战 30 天用 React 加上 Firebase 打造社群网站|Day5 注册登入页面

>>:  【Day 2】词嵌入与BERT的输入

企划实现(23)

立案後的费用产生 很多人会产生一个疑问,立案後如果没有营业跟有营业的费用产生的差别。 这里必须要先说...

EP 03 - Hash ID 计算

Youtube 频道:https://www.youtube.com/c/kaochenlong ...

@Day17 | C# WixToolset + WPF 帅到不行的安装包 [系统上的授权书]

超 简单的系统授权书 我们先看一下原本长怎麽样 ! 我们在网路上找可以使用的授权书范本, WixTo...

[Day30]用Canvas打造自己的游乐场-挑战心得

30天的挑战就这样结束了,现在的心情怎麽有些空虚呢?? 哈哈哈,为什麽会这样呢??我想跟题目有关吧,...

Day8灯灯灯灯登入

延续昨日 今天来研究一下登入! 首先要先有一个登入画面 在views新增一个档案 档案名称叫做log...