You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Google表单提交后生成唯一ID并发送邮件的脚本问题

解决Google表单提交后邮件无法获取最新生成唯一ID的问题

问题背景

已实现两个Google Apps Script:

  • 表单提交后生成唯一ID(EMP前缀),存入Google Sheets并更新表单确认消息
  • 表单提交后发送包含受访者姓名和唯一ID的欢迎邮件

但邮件中的唯一ID始终为空,原因是ID生成并写入表格的操作晚于邮件触发时机,导致读取表格时ID还未被写入。

解决思路

将两个独立的触发器逻辑合并到同一个onFormSubmit函数中,确保先生成并写入唯一ID,再读取ID发送邮件,从根本上避免时序问题。

修改后的完整代码

const EMP = {
  HEADER: "EMP_HEADER",
  PREFIX: "EMP",
  LENGTH: 5,
}

class App{
  constructor(){
    this.ss = SpreadsheetApp.getActive()
    this.sheet = this.getLinkedSheet()
    if (!this.sheet) {
      throw Error(`此表格未关联任何表单。`)
    }
    this.form = FormApp.openByUrl(this.sheet.getFormUrl())
    this.message = this.form.getConfirmationMessage()
    this.empRegex = new RegExp(`${EMP.PREFIX}[\\d]{${EMP.LENGTH}}`, 'gi')
  }

  createEmpByNumber(number){
    return EMP.PREFIX + (10 ** EMP.LENGTH  + number).toString().slice(-EMP.LENGTH)
  }

  getLinkedSheet(){
    return this.ss.getSheets().find(sheet => sheet.getFormUrl())
  }

  getEmpFromConfirmationMessage(){
    const message = this.form.getConfirmationMessage()
    const results = message.match(this.empRegex)
    if (!results) throw Error(`当前确认消息中未找到符合格式的EMP编号,正则规则:${this.empRegex}`)
    return results[0]
  }

  createNextEmp(currentEmp){
    const nextEmpNumber = Number(currentEmp.replace(EMP.PREFIX, "")) + 1
    return this.createEmpByNumber(nextEmpNumber)
  }

  saveCurrentEmp(emp, rowStart){
    const [headers] = this.sheet.getDataRange().getDisplayValues()
    let empHeaderIndex = headers.indexOf(EMP.HEADER)
    if (empHeaderIndex === -1) {
      empHeaderIndex = headers.length
      this.sheet.getRange(1, empHeaderIndex + 1).setValue(EMP.HEADER)
    }
    this.sheet.getRange(rowStart, empHeaderIndex + 1).setValue(emp)
  }

  updateConfirmationMessage(nextEmp){
    const message = this.message.replace(this.empRegex, nextEmp)
    this.form.setConfirmationMessage(message)
  }

  sendWelcomeEmail(e, empId) {
    const name = e.namedValues["Name"][0];
    const email = e.namedValues["Email address"][0];
    const recipient = email;
    const subject = "欢迎加入ABC";
    const alias = GmailApp.getAliases();
    
    const template = HtmlService.createTemplateFromFile('messagebody');
    template.name = name;
    template.code = empId;
    const emailToSend = template.evaluate().getContent();
    
    const sendOptions = alias.length > 0 ? {from: alias[0], htmlBody: emailToSend} : {htmlBody: emailToSend};
    GmailApp.sendEmail(recipient, subject, emailToSend, sendOptions);
  }

  run(e){
    const {rowStart} = e.range
    // 1. 获取当前EMP编号
    const currentEmp = this.getEmpFromConfirmationMessage()
    // 2. 保存到表格
    this.saveCurrentEmp(currentEmp, rowStart)
    // 3. 更新确认消息的下一个编号
    const nextEmp = this.createNextEmp(currentEmp)
    this.updateConfirmationMessage(nextEmp)
    // 4. 发送包含当前EMP编号的邮件
    this.sendWelcomeEmail(e, currentEmp)
  }
}

function onFormSubmit(e) {
  new App().run(e)
}

关键修改点

  • 合并触发器逻辑:删除原有的两个独立onFormSubmit函数,统一到一个入口函数,确保执行顺序可控
  • 直接传递ID:生成currentEmp后直接作为参数传入邮件发送函数,无需再从表格读取,彻底避免时序问题
  • 修复数组取值:e.namedValues返回的是数组,需取第一个元素[0],避免模板中显示数组对象
  • 增加异常处理:发送邮件时判断别名是否存在,避免无别名时报错

邮件模板(保持原内容不变)

<div dir="ltr">
    <p>Hola <?= name ?>,
        <br>
    </p>
    <p style="text-align:justify">
        <br>
    </p>
    <p style="text-align:justify">Te damos la bienvenida a ABC.
        <br>Revisaremos tus datos y nos pondremos en contacto contigo para coordinar tu entrevista.</p>
    <p>Tu código para referir amigos es:</p>
    <p><b><font color="#0000ff"><?= code ?></font></b>.</p>
    <p style="text-align:justify">No olvides invitar a un amigo a registrarse.
        <br>
    </p>
    <p><span style="font-size:10px"><em><a href="https://example.com/pdf/terms">Aplican términos y condiciones</a></em></span></p>
    <p><span style="font-size:10px"><em>--</em></span></p>
    <p><span style="font-size:10px"><em>Equipo de ABC</em></span>
        <br><span style="font-size:10px"><em>&quot;Reinventamos&quot;</em><br><em><a href="mailto:info@example.com">info@abc.com<br></a></em></span></p>
    <p><span style="font-size:10px"><em><a href="https://example.com/assets/dist/images/Logo-go.png"><img alt="Logo" src="https://example.com/assets/dist/images/Logo-go.png" width="160" height="70" style="text-align: center; float: left; margin-right: 0px;"></a></em></span></p>
    <div><font color="#1155cc"><span style="font-size:10px"><i><br></i></span></font></div>
    <div><font color="#1155cc"><span style="font-size:10px"><i><br></i></span></font>
        <p>
            <br>
        </p>
    </div>
    <p>
        <br>
    </p>
</div>

注意事项

  • 确保表单的确认消息中已存在符合格式的EMP编号(如EMP00001),否则脚本会抛出错误
  • 测试时需提交表单触发onFormSubmit触发器,手动运行函数会因缺少e参数报错
  • 确保脚本拥有Gmail和Spreadsheet的授权权限

内容的提问来源于stack exchange,提问作者Darkoder

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 13:24:51