Search code examples
google-apps-scriptgoogle-sheetsgoogle-forms

onSubmit Trigger Executed Without Form Submission


I created a Google Form, linked to a Sheet to capture responses, and added an Apps Script that runs each time the Form is submitted. Ran through a bunch of tests and everything was working fine - form responses fed through, onSubmit function working great. Last night, though, we received a few executions of the script even though the Form was not submitted.

Looking at the Responses page on the Form itself, there were no submissions when I got the notification. Also, this is not a public Form in my organization, and only one other person has the link besides myself. He confirmed he didn't submit the form at the time of the executions.

There are two sheets in the Google Sheet: 1> Form Responses and 2> Data. The data sheet uses a few QUERY functions to pull data from the responses sheet, formatting it differently (e.g. putting hyphens in phone numbers, rendering some fields in upper case, etc.). Also, the data sheet headers are labeled differently than the Form questions (e.g. 'homeAdd1' instead of 'Home Address Line 1'). This is because the script creates a PDF, using the Form responses to replace placeholders ('%homeAdd1%') on a template Google Doc. The script then takes the generated PDF and emails it to the submitter.

Again, everything was working great until yesterday's testing. I didn't realize it at the time, but when my colleague was inputting random values to test the Form, for the Home Address Line 2 he only input a 5-digit ZIP code. It generated a PDF fine, and also emailed it to him, but this caused the QUERY function to render a #VALUE error. The functions look like this:

=QUERY(Responses!L2:S,"SELECT UPPER(L) UPPER(M)...

So when Sheets saw a cell with just 5 digits, it automatically rendered it as a number, and UPPER doesn't work on number values. I (stupidly) didn't think to pre-format all of both sheets as plain text, so this occurred.

Would a #VALUE error on a Google Sheet linked to a Form and an Apps Script cause a misfire of the onSubmit function? This is the only thing I can see that could have possibly caused it, but it doesn't make sense. I've fixed the formatting issue, but I don't know if an erroneous execution could mean some other issue.

With the extra submissions, the script just sent the most recent PDF again and again. Within 20 seconds, it fired 5 times, sending the last PDF that was generated via email each time. Looking at the Stackdriver logs, there's nothing different from when we were testing it earlier yesterday. The console.log and console.info commands work fine, and they all come through listed as having been triggered by the onSubmit function.

Here's the script:

Submit function:

function onSubmit(e) {
  var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Data');
  var list = ss.getRange("A1:A").getValues();
  var row = list.filter(String).length;
  var email = ss.getRange(row,2).getValue();
  var newResponse = ss.getRange(row,3).getValue();
  if (newResponse == 'Generate New') {
    newOne(ss,row,email);
  } else if (newResponse == 'Upload Completed') {
    completed(ss,row,email);
  } else {
  }
}

Function that was executed:

function newOne(ss,row,email) {
  var name = ss.getRange(row,4).getValue();
  console.log('Function Start - ' + name);
  var newType = ss.getRange(row,6).getValue();
  var copyFile = DriveApp.getFileById('[file id]').makeCopy();
  var copyDoc = DocumentApp.openById(copyFile.getId());
  var copyBody = copyDoc.getActiveSection();
  // Replacing variables with values on spreadsheet
  console.log('Create file start - ' + name);
  var newInfo = ss.getRange(row, 1, 1, 29).getDisplayValues();
  var header = ss.getRange(1, 1, 1, 29).getDisplayValues();
  for (var i = 1; i <= 5; i++) {
    copyBody.replaceText('%' + header[0][i] + '%', newInfo[0][i].toString());
  }
  var x;
  if (newType == 'Office 1') {
    x = 6;
  } else if (newType == 'Office 2') {
    x = 15;
  } else {
  }
  for (var i = x; i <= (x + 8); i++) {
    copyBody.replaceText('%' + header[0][i] + '%', newInfo[0][i].toString());
  }
  copyBody.replaceText('%' + header[0][26] + '%', newInfo[0][26].toString());
  // Create the PDF file, rename it, and delete the doc copy
  copyDoc.saveAndClose();
  var newFile = DriveApp.createFile(copyFile.getAs('application/pdf'));
  newFile.setName('New - ' + name + '.pdf');
  copyFile.setTrashed(true);
  console.log('Create file finished - ' + name);
  //Mails PDF to submitter
  console.info('Pre-email log for ' + name);
  MailApp.sendEmail(email,'Email Subject','', {
                    noReply: true,
                    htmlBody: "<body>Hello, and thank you.</body>",
                    attachments: [newFile]
                    });
  console.info('Email sent for ' + name);
  appFile.setTrashed(true);
}

Any insight / help would be appreciated; thanks!

Josh


Solution

  • Spurious unwanted Event Triggers

    I've had problems with spurious triggers coming from onFormSubmit event triggers. In my case they were always immediately after a real trigger occurred from a Form Submission. I found that I could identify them because none of my required questions were answered. I discuss it here.

    It might be worth your time to capture the e.values array and see if you can find a consistent way to keep them from causing a misfire of your processing function.