3

I'm pretty new to Javascript and have been working on this script to take the most recent entry in a spreadsheet (created from a Google form), match the users email address that is collected to a roster in a second sheet, and send an email to parents. I'm a teacher and the idea is to be able to create a google form that compiles the info students enter and email it to their parents once they submit the form/update the sheet.

I know it's pretty messy...there are some extra variables and things, but the script works perfectly/as expected when you "Run" the script. The only thing is, I have tried to have the script run on a trigger when the form is submitted, but it doesn't. Am I missing something with using triggers?

Code is below:

function createEmail() {
  // Sets variables for both sheets
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  var sheet1 = ss.getSheets()[0];
  var sheet2 = ss.getSheets()[1];

  // This gathers information from the most recent entry and write it to an array called newReflectionValues
  var reflectionLastRow = sheet1.getLastRow();
  var reflectionLastColumn = sheet1.getLastColumn();
  var reflectionLastCell = sheet1.getRange(reflectionLastRow, reflectionLastColumn).getValue();
  var reflectionRange = sheet1.getRange(reflectionLastRow, 1, 1, reflectionLastColumn);  
  var newReflectionValues = reflectionRange.getValues();

  var studentEmail = newReflectionValues[0][3];

    Logger.log("NEW REFLECTION VALUES")
    Logger.log(newReflectionValues);

    Logger.log("Email will send to student email:")
    Logger.log(studentEmail)

  // Makes an array of the parent email addresses
  var rosterLastRow = sheet2.getLastRow();
  var rosterLastColumn = sheet2.getLastColumn();
  var rosterEmails = sheet2.getSheetValues(2, 1, rosterLastRow, rosterLastColumn);

  Logger.log("PARENT EMAILS")
  Logger.log(rosterEmails);  

  // Cross check emails - if a match, write emails to variable
  var parentEntriesLength = rosterLastRow;

  for (i = 0; i < parentEntriesLength; i++) {
    var currentRange = rosterEmails[i];

    if (currentRange[2] == studentEmail) {
      var toParents = String(currentRange[3]) + ", " + String(currentRange[4]);
      var studentName = String(currentRange[0]);
      var countOfReflections = currentRange[6];
      break;
    } else {
    var toParents = "NO PARENT EMAILS FOUND";
    }
  } 

// FINISH EMAIL BELOW

  MailApp.sendEmail({
     to: toParents,
     bcc: "rdoyle@rafos.org" + ", " + String(studentEmail),
     subject: "Behavior Reflection Notification",

    htmlBody: "<p>Hello,</p>" +
    "<p>Today studentName received a behavior reflection for the following action:</p>" +
    "<p>newReflectionValues</p>" +
    "<p>They took a short break in class and completed the following reflection:</p>" +
    "<p>reflectionInformation</p>" +
   "<p>" + String(studentName) + " has recieved " + countOfReflections + " reflections this year." + "</p>" +
    "<p>This email has been sent with information that the student completed directly on the reflection form and has been bcc'd to them as well as myself. If you have any questions regarding this behavior or incident, please feel free to ask.</p>"

  });

}
Rubén
  • 34,714
  • 9
  • 70
  • 166
Ryan
  • 79
  • 2
  • 10
  • How have you constructed your trigger? There are some restrictions on the actions that a trigger can apply. I am not certain if that applies to your issue. https://developers.google.com/apps-script/guides/triggers/ – terrywb Jul 18 '17 at 02:11
  • I guess that's what I'm lost on. I've seen that documentation, but I'm uncertain as to whether or not I am supposed to make my own trigger, or simple be able to set it up by going to Edit > Current Project Triggers > and then setting it up that way. – Ryan Jul 18 '17 at 02:38
  • In many situations it is pointless to write code to set up a trigger. If you need to install a trigger for a user, and they can't do it themselves, that is a situation where you would create the trigger with code. If it's for yourself, and you only need to install it once, and then let it run for some indefinite time, it's better to do it manually. – Alan Wells Jul 18 '17 at 02:48
  • Ok, that makes sense now. I just watched an hour long intro to google scripts trigger video from a google developers live thing. I belive that manually setting up the trigger is what I should do, but it leads me back to the main problem. If I run the script from the script editing page directly everything works, but if I manually create a trigger...nothing. – Ryan Jul 18 '17 at 03:28

2 Answers2

5

You are aware that there are 2 types of trigger simple and installable but I think you are a little confused as to what they actually mean/ do. I'll try to explain the key points from documentation here.

A simple trigger is used by simply naming the function with the trigger name. For example, with Sheets / Forms, the trigger onFormSubmit(e) is fired when the user submits a form. The parameter e contains all the information relating to the submission, you should look into this as it's much more reliable than your current method of getting the submitted information. See here: 'e' parameter

Simple triggers are limited in their functionality since the script doesn't have to be authorised for the trigger to fire. A simple trigger cannot access other files, send emails or perform any action that requires authorisation. See here

An installed trigger is one that is either manually set up by the user or a script. Installed triggers have a lot more functionality but they still have some restrictions. See here

An installed trigger can call any named function and e parameter works in the same way as it does with simple triggers.

From your code above your installed trigger should look like this. enter image description here

When you click save you should be asked for authorisation, if you are not asked, click the debug/ run button to authorise the script.

If it still doesn't work check the execution transcript in view -> execution transcript, the last line will indicate the error.

James D
  • 3,102
  • 1
  • 11
  • 21
0

Ok, James helped out a lot, but I was seeming to have a lot of problems authenticating the permissions to send emails. I decided in the end to re-write everything more clearly, add some functions so others I work with could use the same script, and keep a record of whether or not emails were actually sent to parents. This final version uses a if statement to look in a column at whether or not an email was sent for each response, then sends an email if needed and records when it was sent. I also added a function to set up that "confirmation" column and create a roster sheet as a single function as well as seperately. Oh, and it also looks for an html template to format the email. I found that info on a Google developers live stream: https://www.youtube.com/watch?v=U9Ej6PCeO6s

Thanks everyone!

function createConfirmationColumn() {
var ss = SpreadsheetApp.getActiveSpreadsheet();

var sheet1 = ss.getSheets()[0];

var lastColumn = sheet1.getLastColumn();
var lastColumnValue = sheet1.getRange(1,lastColumn).getValue();

// Creates the final column to log the time that emails are sent
if (lastColumnValue != "Email Sent On:") {
    sheet1.insertColumnsAfter(lastColumn, 1);
    var emailSentOnColumn = sheet1.getRange(1,lastColumn+1).setValue("Email Sent On:");
}
}

function createRosterSheet() {
  var ss = SpreadsheetApp.getActiveSpreadsheet();

  ss.insertSheet("Roster & Parent Emails", 1);
  var rosterSheet = ss.getSheets()[1];

  rosterSheet.getRange(1,1).setValue("First Name")
  rosterSheet.getRange(1,2).setValue("Last Name")
  rosterSheet.getRange(1,3).setValue("Student Email")
  rosterSheet.getRange(1,4).setValue("Parent Email 1")
  rosterSheet.getRange(1,5).setValue("Parent Email 2")
  rosterSheet.getRange(1,6).setValue("Notes")
  rosterSheet.getRange(1,7).setValue("Total Reflections")

}

function formSetup() {
var ss = SpreadsheetApp.getActiveSpreadsheet();

var sheet1 = ss.getSheets()[0];

var lastColumn = sheet1.getLastColumn();
var lastColumnValue = sheet1.getRange(1,lastColumn).getValue();

// Creates the final column to log the time that emails are sent
if (lastColumnValue != "Email Sent On:") {
    sheet1.insertColumnsAfter(lastColumn, 1);
    var emailSentOnColumn = sheet1.getRange(1,lastColumn+1).setValue("Email Sent On:");
}

ss.insertSheet("Roster & Parent Emails", 1);
  var rosterSheet = ss.getSheets()[1];

   rosterSheet.getRange(1,1).setValue("First Name")
   rosterSheet.getRange(1,2).setValue("Last Name")
  rosterSheet.getRange(1,3).setValue("Student Email")
  rosterSheet.getRange(1,4).setValue("Parent Email 1")
  rosterSheet.getRange(1,5).setValue("Parent Email 2")
  rosterSheet.getRange(1,6).setValue("Notes")
  rosterSheet.getRange(1,7).setValue("Total Reflections")
}

function sendEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();

var sheet1 = ss.getSheets()[0];
var sheet2 = ss.getSheets()[1];

var lastColumn = sheet1.getLastColumn();
var lastColumnValue = sheet1.getRange(1,lastColumn).getValue();

var allFormEntries = sheet1.getDataRange().getValues();
var allRosterValues = sheet2.getDataRange().getValues()

  for (e = 1; e < sheet1.getLastRow(); e++) {
var formRange = allFormEntries[e];

var studentEmailInForm = formRange[1];
var emailSentOn = formRange[4];

if (emailSentOn == "") {

for (i = 1; i < sheet2.getLastRow(); i++) {
  var individualRosterEntry = allRosterValues[i];

  if (studentEmailInForm == individualRosterEntry[2]) {
    var parentEmails = String(individualRosterEntry[3]) + ", " + String(individualRosterEntry[4]);

    var emailTemplate = HtmlService.createTemplateFromFile("emailTemplate");
    emailTemplate.studentName = individualRosterEntry[0];
    emailTemplate.reflectionCount = individualRosterEntry[6];
    emailTemplate.reason = formRange[2];

    MailApp.sendEmail({
      to: parentEmails,
      bcc: "rdoyle@rafos.org" + ", " + String(studentEmailInForm),
      subject: "Behavior Reflection Notification",
      htmlBody: emailTemplate.evaluate().getContent(),
    })

    sheet1.getRange((e+1), lastColumn).setValue(new Date());
    break;
  } else {
   sheet1.getRange((e+1), lastColumn).setValue("No valid email found") ;
  }

} // for i loop

} //if email sent == ""

  } //for e loop

} //function
Ryan
  • 79
  • 2
  • 10