0

Introduction

I am creating a Google Script that fills a Google Doc template based on the fields of a Google Forms and sends the generated PDF via email to the user. Now I need to implement the possibility that the user can edit its submit after he press on "Send Form".

This is the Doc template example:

Doc template

This is how the Spreadsheet looks like (2nd row is added by me for columns enumeration):

Time stamp Dirección de correo electrónico Surname First name Year Model Birthday (1) Car (1) Add a new row? Birthday (2) Car (2) Add a new row? Birthday (3) Car (3) When
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
2/04/2021 20:30:53 example1@gmail.com A F1 2005 Z 15/03/2008 MM Y 12/12/1996 - N 3/05/2009
2/04/2021 20:31:05 example2@gmail.com B F2 2006 X 3/02/2005 WW N 24/08/2000
3/04/2021 21:40:04 example3@gmail.com C F3 2018 Y - TT Y 3/03/2004 54 Y - 43 24/12/2019

Script

Thanks to Rubén's answer I could handle some fields. This is my code so far:

function onSubmit(e) { // Function taken from https://medium.com/swlh/hacking-it-generate-pdfs-from-google-forms-3ca4fcc5a0aa
  const rg = e.range;
  const sh = rg.getSheet();

  const values =  e.range.getValues().flat();

  const cEmail = e.namedValues['Dirección de correo electrónico'][0] ? e.namedValues['Dirección de correo electrónico'][0] : values[1];
  const cSurname = e.namedValues['Surname'][0] ? e.namedValues['Surname'][0] : values[2];
  const cFirstName = e.namedValues['First name'][0] ? e.namedValues['First name'][0] : values[3];
  const cYear = e.namedValues['Year'][0] ? e.namedValues['Year'][0] : values[4];
  const cModel = e.namedValues['Model'][0] ? e.namedValues['Model'][0] : values[5];

  // EXTRACT DAY, MONTH AND YEAR from https://stackoverflow.com/a/66909780/11617040

  const monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];

  // Birthday 1
  var dateStrBirthday1 = e.namedValues['Birthday (1)'][0] ? e.namedValues['Birthday (1)'][0] : values[6];
  var dateArrBirthday1 = dateStrBirthday1.split("/");
  var newDateBirthday1 = dateArrBirthday1[1] + "/" + dateArrBirthday1[0] + "/" + dateArrBirthday1[2];
  var dateBirthday1 = new Date(newDateBirthday1);
  var cBDay1 = dateBirthday1.getDate();
  var cBMonth1 = dateBirthday1.getMonth()+1; // To use month with letters write monthNames[cMonth]
  var cBYear1 = dateBirthday1.getFullYear();
  // Birthday 2
  var dateStrBirthday2 = e.namedValues['Birthday (2)'][0] ? e.namedValues['Birthday (2)'][0] : values[9];
  var dateArrBirthday2 = dateStrBirthday2.split("/");
  var newDateBirthday2 = dateArrBirthday2[1] + "/" + dateArrBirthday2[0] + "/" + dateArrBirthday2[2];
  var dateBirthday2 = new Date(newDateBirthday2);
  var cBDay2 = dateBirthday2.getDate();
  var cBMonth2 = dateBirthday2.getMonth()+1; // To use month with letters write monthNames[cMonth]
  var cBYear2 = dateBirthday2.getFullYear();
  // Birthday 3
  var dateStrBirthday3 = e.namedValues['Birthday (3)'][0] ? e.namedValues['Birthday (3)'][0] : values[12];
  var dateArrBirthday3 = dateStrBirthday3.split("/");
  var newDateBirthday3 = dateArrBirthday3[1] + "/" + dateArrBirthday3[0] + "/" + dateArrBirthday3[2];
  var dateBirthday3 = new Date(newDateBirthday3);
  var cBDay3 = dateBirthday3.getDate();
  var cBMonth3 = dateBirthday3.getMonth()+1; // To use month with letters write monthNames[cMonth]
  var cBYear3 = dateBirthday3.getFullYear();

  const cCar = [];

  for (var i=1; i<=3; i++) {
    cCar.push(e.namedValues['Car (' + i + ')'][0] ? e.namedValues['Car (' + i + ')'][0] : values[7+(i-1)*3]);
  }

  const cWhen = e.namedValues['When'][0] ? e.namedValues['When'][0] : values[14];

  //Build a new invoice from the file
  //Folder and file IDs
  const folderAnswersID = '....';
  const folderAnswers = DriveApp.getFolderById(folderAnswersID);

  // Add actual time to the file name
  var today = new Date();
  const newFileName = 'Example - ' + cSurname + ' ' + cFirstName + ' ' + today.getDate() + ' ' + (today.getMonth()+1) + ' ' + today.getFullYear() + ' ' + today.getHours() + '_' + today.getMinutes();

  const temapleFileID = '........';
  
  //Make a copy of the template file
  const newAnswersFileID = DriveApp.getFileById(temapleFileID).makeCopy(newFileName, folderAnswers).getId();
  
  //Get the invoice body into a variable
  var document = DocumentApp.openById(newAnswersFileID);
  var body = document.getBody();

  //Replace all the < > text in the invoice body
  body.replaceText('<Surname>', cSurname);
  body.replaceText('<FirstName>', cFirstName);
  body.replaceText('<Year>', cYear);
  body.replaceText('<Model>', cModel);

  body.replaceText('<BDay1>', cBDay1);
  body.replaceText('<BDay2>', cBDay2);
  body.replaceText('<BDay3>', cBDay3);
  body.replaceText('<BMonth1>', cBMonth1);
  body.replaceText('<BMonth2>', cBMonth2);
  body.replaceText('<BMonth3>', cBMonth3);
  body.replaceText('<BYear1>', cBYear1);
  body.replaceText('<BYear2>', cBYear2);
  body.replaceText('<BYear3>', cBYear3);

  for (var i=1; i<=3; i++) {
    body.replaceText('<Car' + i + '>', cCar[i-1]);
  }
  
  body.replaceText('<When>', cWhen);

  document.saveAndClose();
  
  // From https://stackoverflow.com/a/66862676/11617040
  var docblob=document.getAs('application/pdf').setName(newFileName + '.pdf');
  var dupdocs=folderAnswers.getFilesByName(newFileName);
  while(dupdocs.hasNext()) {
    dupdocs.next().setTrashed(true);
  }
  var file=folderAnswers.createFile(docblob);

  var emailTitle = 'Your answer was submitted!';
  var emailBody = 'Dear <b>' + cSurname + '</b>:<br><br>The document <b>' + newFileName + '</b> was submitted correctly. Please see the attachment.';

  var attachment = DriveApp.getFileById(newAnswersFileID);
  GmailApp.sendEmail(
    cEmail,
    emailTitle,
    "",
    {
      htmlBody: emailBody,
      attachments: [attachment.getAs(MimeType.PDF)]
    }
  );
}

I also have 2 triggers:

  • On submit: When the user press "Send Form".
  • Edit: When the user edits its Form after he press "Send Form".

There are 2 types of "Fields" that I need to care about:

  1. "Non-repetitive fields": Surname, First name, Year, Model, WHEN. These fields do not require a for loop so the code is not so long:
    • "Non-date fields": Surname, First name, Year. They aren't special.
    • "Date fields": WHEN. This is a Date field on Google Forms but nothing special.
  2. "Repetitive fields": Day, Month, Year, Car. These fields do require a for loop so the code is not so long:
    • "Non-date fields": Car. I created a for loop for this field.
    • "Date fields": Day, Month, Year. These fields were Date fields but they need to be separated so I have days, months and years separately. This was solved in a previous question but I don't know how to make a for loop for this ones.

Test and results

The user submits the 1st row:

2/04/2021 20:30:53 example1@gmail.com A F1 2005 Z 15/03/2008 MM Y 12/12/1996 - N 3/05/2009

This is the output:

Output

Problem

There are a NaN values that I don't want them to appear. Instead they should be blank. How to solve this?

manooooh
  • 113
  • 2
  • 7
  • 1
    The code included is not a [mcve]. – Rubén Apr 05 '21 at 14:36
  • @Rubén why is not a minimal reproducible example? I would like to follow the rules. – manooooh Apr 05 '21 at 14:37
  • 1
    Because it include a lot of code lines that are not necessary to reproduce the problem of getting a `NaN` instead of the a date. – Rubén Apr 05 '21 at 14:53
  • In your [mcve], since the problem is related to reading data from an spreadsheet, besides include the displayed value, please also include the data type for values like `15/03/2008` in oder to be sure if hey are date or text values – Rubén Apr 05 '21 at 15:29

0 Answers0