通过电子邮件发送表格并在电子表格中跟踪回复

3

我正在使用Google Apps脚本发送电子邮件 - 我知道如何做到这一点。我想嵌入一个“是或否”响应链接或多项选择题,并记录收件人的响应在Google电子表格中。

我该如何做到这一点?

2个回答

16
这个工作流涉及的组件有:
  • 一个脚本,用于生成和发送带有 HTML 表单的电子邮件。
  • 一个电子邮件的 HTML 模板,使我们可以为每个收件人定制电子邮件。
  • doPost() 函数来处理响应。该脚本必须作为 部署为 Web 应用程序
  • 一个用于收集响应的电子表格。该脚本将包含在电子表格中,并通过菜单扩展电子表格 UI 来发送调查副本。(它也可以适应无 UI 组件的独立使用。)
以下是一个进行通勤调查的工作流示例。收件人将收到类似于以下的调查电子邮件:

Email

收件人可以在支持该功能的电子邮件客户端中直接填写表单。响应将被收集到类似于以下内容的电子表格中:
请在运行脚本之前自己创建电子表格标题。

Spreadsheet

“序列号”列已经添加,以说明将响应与特定调查对象相关联的一种方式;请注意,某些条目会重复。生成调查电子邮件时,它会被赋予一个唯一的序列号,并作为响应的隐藏值传回。我们可以扩展此系统以识别来自受访者的更新等。
现在是代码。(也可以作为Gist提供

emailTemplate.html

<div>
  <form action="<?= scriptUrl ?>" method="Post">
  <table>
  <tr>
  <td>
    <label for="commute">Do you commute to work?</label>
    </td>
    <td>
    <select name="commute">
      <option>Yes</option>
      <option>No</option>
    </select>
    </td>
  </tr>
  <tr>
    <td>
    <label for="vehicle">If "Yes", how do you get to work?</label>
    </td>
    <td>
      <input type="checkbox" name="vehicle" value="Bike">I have a bike<br>
      <input type="checkbox" name="vehicle" value="Car">I have a car
    </td>
  </tr>
  <tr>
    <td>
    <!-- A Hidden field is a handy way to pass information to the
         Server-side POST handler. For example, a serial number could
         be used to collate responses from a particular recipient. -->
    <input type="hidden" name="serial" value="<?= serialNumber ?>" />
    </td>
    <td>
    <input type="submit" value="Submit" />
    </td>
  </tr>
  </table>
  </form>
</div>

Code.gs

// doPost needs the spreadsheet ID, it has no concept of "active spreadsheet".
var _spreadsheetId = '--- Spreadsheet ID ---';

// Add custom menu with option to send survey
function onOpen() {
  var sheet = SpreadsheetApp.getActiveSpreadsheet();
  var entries = [{
    name : "Send Survey",
    functionName : "sendSurvey"
  }];
  sheet.addMenu("Custom Menu", entries);
};

/**
 * Build & Send Survey, an HTML form in email.
 */
function sendSurvey() {
  var recipient = Browser.inputBox("Send Survey", "Enter Recipient Email", Browser.Buttons.OK_CANCEL);
  if (recipient === 'cancel') return;

  var subject = 'Commuting Survey';

  // Get the URL of the published Web App, to include in email for POST of response
  var scriptUrl = ScriptApp.getService().getUrl();
  if (!scriptUrl) throw new Error( 'You must Deploy as Web App first.' ); 

  // Build email body
  var template = HtmlService.createTemplateFromFile('emailTemplate');
  template.scriptUrl = scriptUrl;
  template.serialNumber = getGUID();  // Generate serial number for this response
  var html = template.evaluate().getContent();

  // During debugging, send emails to self. Remove this line for real operation.
  recipient = Session.getActiveUser().getEmail();  

  // Send email form
  GmailApp.sendEmail(recipient, subject, 'Requires HTML', {htmlBody:html} );

  Browser.msgBox("Survey Sent");
}

/**
 * POST handler for responses; 
 */
function doPost(e) {
  Logger.log(e);
  var ss = SpreadsheetApp.openById(_spreadsheetId);
  var sheet = ss.getSheets()[0];  // Assume first sheet collects responses

  // Build a row of data with timestamp + posted response
  var row = [
    new Date(),                     // Timestamp
    e.parameters.serial[0],         // Serial Number
    e.parameters.commute[0],        // Commuter? Yes / No
    e.parameters.vehicle.join(',')  // Vehicle
  ];

  // Make sure we are the only people adding rows to the spreadsheet
  var lock = LockService.getPublicLock();
  // Wait for up to 30 seconds for other processes to finish.
  var locked = lock.tryLock(30000);

  if (locked) {
    // Save response to spreadsheet
    var rowNum = sheet.getLastRow()+1;
    sheet.getRange(rowNum, 1, 1, row.length).setValues([row]);

    // Release the lock so that other processes can continue.
    lock.releaseLock();
    var result = "Response Recorded: \n  "+row.join('\n  ');
  }
  else {
    // Failed to get lock
    result = "System busy, please try again.";
  }

  // Report result of POST, in plain text
  return ContentService.createTextOutput(result)
                       .setMimeType(ContentService.MimeType.TEXT);
}


/**
 * Returns an rfc4122 version 4 compliant GUID / UUID string
 * Thanks to @broofa!
 * https://dev59.com/7HVD5IYBdhLWcg3wDXF3#2117523
 */
function getGUID() {
  return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
    var r = Math.random()*16|0, v = c == 'x' ? r : (r&0x3|0x8);
    return v.toString(16);
  });
}

部署

要使用此调查系统:

  1. 在您的Drive帐户中创建一个新的电子表格。在第一行中添加“时间戳”,“序列号”,“通勤者?”和“车辆”标题。
  2. 选择“工具” - “脚本编辑器”。复制Code.gs内容。复制您的电子表格的ID,并更新文件顶部的_spreadsheetId变量。保存。
  3. 选择“文件” - “新建HTML文件”,将文件命名为emailTemplate。复制emailTemplate.html内容。保存。
  4. 发布 - 部署为Web应用程序...使其对任何人都可以访问,包括匿名用户。(在Google应用域中,您可以将其限制为域中的用户。)
  5. 通过重新加载电子表格或在编辑器中运行onOpen函数来授权脚本。

准备就绪!您会在电子表格中找到“自定义菜单”,其中包含“发送调查”命令。


谢谢Mogsdad,我会使用它 :) - Amany
当我发送这个表格时,Outlook或iPhone没有提交它,我们该如何解决? - Amany
如前所述,电子邮件客户端需要支持HTML表单才能正常工作。Outlook有自己的表单,但不支持HTML表单元素(参考:http://msdn.microsoft.com/en-us/library/office/aa338201%28v=office.12%29.aspx)。我会为其他用户提供代码来回答您的后续问题。https://dev59.com/yXbZa4cB1Zd3GeqPLu9e - Mogsdad

4
使用Google Apps基础设施创建一个表单,将表单通过电子邮件发送给自己并点击“显示原始邮件”,就可以轻松地完成UI开发和响应管理。您可以获取嵌入代码并在脚本中使用来发送邮件,响应将自动记录在与表单相关联的电子表格中。然后,您可以覆盖onFormSubmit事件并进行所需的处理。如果需要更多信息,请告诉我。

我想更好地理解这个问题。我在https://stackoverflow.com/questions/46454090/is-it-possible-to-email-a-form上有一个问题。 - user1592380

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接