This is an addenum of a previous question: Problems generating PDFs from Google Forms after it is submitted
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:
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 |
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(); // 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(); // 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(); // To use month with letters write monthNames[cMonth]
var cBYear3 = dateBirthday3.getFullYear();
// ^ This code should be done with a for loop
const cCar = [];
for (var i=1; i<=3; i++) {
// Here I should do the same but for Birthday (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>' + cFirstName + '</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".
I have marked 2 problems on the code. There are 2 types of "Fields" that I need to care about:
- "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.
- "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.
- "Non-date fields": Car. I created a
My question is: How can we work with a Form where the user can edit its submit after he press on "Send Form" and also not hardcoding the column headers and caring about descomposing Date fields and using for
loops in a fancy way?
If the for
loops question is too difficult to answer, you can forget about it, I need to implement the edits made by the user ASAP.