谷歌应用程序脚本驱动的谷歌表单中的并发问题和丢失表单数据

时间:2012-09-29 08:10:00

标签: google-apps-script google-sheets google-form

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

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

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

 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);
    }

1 个答案:

答案 0 :(得分:1)

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

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

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