0

当人们几乎同时提交表单时,我最近遇到了我认为是并发问题的问题,这导致谷歌表单的数据丢失。我已经在使用 Lock 服务来防止这个问题,但我似乎仍然有问题。http://googleappsdeveloper.blogspot.com/2011/10/concurrency-and-google-apps-script.html

表单目前有 onFormSubmit 触发器:formSubmitReply 和 logMessage。formSubmitReply 向提交表单的人发送确认信息,并且 logMessage 应该在单独的电子表格中备份信息,以防常规电子表格中的行被破坏。它应该从 formSubmit 事件中提取值,然后将其附加到“日志”表中。

我已经包含了脚本的所有当前代码,并用占位符替换了电子邮件。我可以获得一些帮助来识别代码中可能阻止表单在表单中记录行的任何错误吗?

 function getColIndexbyName(colName){
      var sheet=SpreadsheetApp.getActiveSheet();
      var rowWidth=sheet.getLastColumn();
      var row=sheet.getRange(1,1,1,rowWidth).getValues();//this is the first row
      for ( i in row[0]){
        var name=row[0][i];
        if(name == colName || new RegExp(colName,'i').test(name)){
          return parseInt(i)+1;
        }
      }
      return -1
    }
    function makeReceipt(e){
      /*This is for Student Volunteer auto-confirmation*/
      var ss,sheet, rowWidth, headers, rowWidth,curRow, values, greeting, robot, msg, space, newline;
      curRow=e.range.getRow();
      ss=SpreadsheetApp.getActiveSpreadsheet();
      sheet=ss.getSheetByName("RAW");
      rowWidth=sheet.getLastColumn();
      headers=sheet.getRange(1,1,1,rowWidth).getValues();
      values=sheet.getRange(curRow,1,1,rowWidth).getValues();
      greeting='Hi '+sheet.getRange(curRow,getColIndexbyName('First Name'),1,1).getValue()+"! <br><br>"+ ' '; 
      robot="<i>Below are the responses you submitted. Please let us know if any changes arise!</i> <br><br>";
      msg=greeting+robot;
      space=' ';
      newline='<br>';
      for( i in headers[0]){
        //only write non "Reminders" column values
        if(headers[0][i]!="Reminders"){
          msg+="<b>";
          msg+=headers[0][i];
          msg+="</b>";
          msg+=":";
          msg+=space;
          msg+=values[0][i];
          msg+=newline;
        }
      }
      return msg;

    }



    /**
     * Triggered on form submit
     **/
    function formSubmitReply(e) {
      var ss, row, mailIndex, userEmail, message, appreciation;
      var lock = LockService.getPublicLock();
      if(lock.tryLock(60000)){
        try{
          ss=SpreadsheetApp.getActiveSheet();
          row=e.range.getRow();
          mailIndex=getColIndexbyName('Email Address');
          userEmail=e.values[mailIndex-1];
          message=makeReceipt(e);
          MailApp.sendEmail(userEmail, 'BP Day 2012 Confirmation for'+' '+userEmail,message,{name:"Name", htmlBody:message, replyTo:"example@example.com"});  
          messageAlert100(e);
        } catch(err){
          e.values.push("did not send email"); 
          MailApp.sendEmail(""example@example.com","error in formSubmitReply"+err.message, err.message);
        }
        logToSpreadsheet(e);
      } else {
        //timeOut
        try{
          if(e && e.values){
            logToSpreadsheet(e);
            e.values.push("did not send email");  
          }
        }catch(err){
          MailApp.sendEmail("example@example.com", "error in logging script block "+err.message, err.message)
        }

      }
    }


    /**
     * Triggered on form submit
     **/
    function messageAlert100(e){
      var cheer_list, curRow, cheer_list, cheer_index, cheer, ss=SpreadsheetApp.getActiveSpreadsheet();
      if(e && e.range.activate){
        curRow=e.range.getRow();
      }
      cheer_list=["Congratulations!", "Give yourself a pat on the back!", "Yes!", "Cheers!","It's time to Celebrate!"];
      cheer_index=Math.floor(Math.random()*cheer_list.length);
      cheer=cheer_list[cheer_index];
      if(typeof(curRow) != "undefined" && curRow % 100 ==0){
        MailApp.sendEmail("example@example.com", ss.getName()+": "+cheer+" We now have "+ curRow + " Volunteers!", cheer+" We now have "+ curRow + " Volunteers!");
      }
    }

    /**
     *
     **/
    function logToSpreadsheet(e){
      var ss=SpreadsheetApp.getActiveSpreadsheet(), sh;
      if(!ss.getSheetByName("log")){
        sh=ss.insertSheet("log");
      }
      sh=ss.getSheetByName("log");
      if(e && e.values !==null){
        sh.appendRow(e.values)
      } else {
        sh.appendRow(e);
      }
      Logger.log(e);
    }
4

1 回答 1

1

我使用一种非常简单的方法来避免表单的并发问题,我不得不想象在 GAS 提供锁定方法之前。我没有使用触发器,而是在on form submit检查列是否有标志(MAIL SENT)的函数上使用计时器触发器(每隔几分钟左右)......如果标志不存在,我发送带有处理数据的电子邮件,复制到备份表并设置标志。我从最后一行开始在每一行上执行此操作,并在找到标志时停止。这样,我确定所有数据行都已处理,并且不会发送重复的邮件。实际上实现起来非常简单,您的脚本只需要进行一些修改。

从用户的角度来看,结果几乎与他们在提交后几分钟收到的邮件相同。

编辑:当然,在此设置中,您不能使用 e 参数来获取表单数据,但您必须改为读取工作表上的数据......但这并不是一个很大的区别;-)

于 2012-09-30T08:33:21.470 回答