How to execute multiple functions in google apps script? - google-apps-script

thanks in advance for your time. I am new to google apps scripting, so apologies if the question below is a basic one.
I have created functions for a sheet, which individually seem to run just fine. When both functions are combined, only one actually runs while the other doesn't work.
I'm hoping for some help as I'm sure the way that I have both laid out is incorrect.
Please see examples below.
function onEdit(){
autoNotes();
moveTabs();
}
function autoNotes() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var sheet = ss.getActiveSheet()
var lr = sheet.getLastRow()
var data = sheet.getRange("A3:AQ"+lr).getValues()
var activeCell = sheet.getActiveCell()
var col = activeCell.getColumn()
var row = activeCell.getRow()
var mailAddress = data\[row-3\]\[11\]
var instructorName = '\<b\>Instructor: \</b\>'+ data\[row-3\]\[1\] + ' ' + data\[row-3\]\[2\]
var instructorFirst = '\<b\>\</b\>'+ data\[row-3\]\[1\]
var instructorFirstLast = data\[row-3\]\[1\] + ' ' + data\[row-3\]\[2\]
var instructorCourse = "\<b\>Course Build Training Track: \</b\>"+ data\[row-3\]\[5\] + ', ' + data\[row-3\]\[6\]
var totalDays = data\[row-3\]\[28\].toFixed(1)
var programrepFirstLast = data\[row-3\]\[10\]
var instructorEmail = data\[row-3\]\[3\]
var totalPercent = Number(data\[row-3\]\[29\]).toLocaleString(undefined, { style: "percent", minimumFractionDigits: 0,})
var formatDate1 = new Date(data\[row-3\]\[7\]).toLocaleDateString()
var courseDate = '\<b\>Course Start Date: \</b\>'+ formatDate1
var courseDate2 = formatDate1
var formatDate = new Date(data\[row-3\]\[27\]).toLocaleDateString()
var startDate = '\<b\>Training Start Date: \</b\>'+ formatDate
var startDate2 = formatDate
var urlsheet = "https://docs.google.com/spreadsheets/d/1DI074UNhvj_LNM35bb9WTsf9aFkxsTcmjOWnNT3nXts/edit?usp=sharing"
var recipients = mailAddress
var body = instructorName + '\\n' + instructorCourse + '\\n' + instructorFirst + '\\n' + startDate + '\\n' + courseDate + '\\n' + totalDays + '\\n' + programrepFirstLast + '\\n' + totalPercent + '\\n' + instructorEmail + '\\n' + startDate2 + '\\n' + courseDate2
// var contentHTML = "<body><p>"+ instructorName + "</p><p>" +instructorCourse + "</p><p>" +startDate + "</p><p><br> <a href='" + urlsheet + "'>MASTER Enrollment Sheet</a> </p><br> </body>"
if(row\>2 && col == 31 && activeCell.getValue()==true){
var subject = data\[row-3\]\[1\] + ' ' + data\[row-3\]\[2\]+ ' Training Update: Attended Kick-Off Meeting'
var contentHTML ="\<br\>" + instructorName + "\<br\>" + instructorCourse + "\<br\>" + courseDate + "\<br\>" + startDate + "\<br\>\<br\>" + "\<b\>Training Update:\</b\>" + "\<br\>\<br\>" + "Dear " + programrepFirstLast + "," + "\<br\>\<br\>" + "Instructor " + instructorFirstLast + " has attended the Canvas Course Development Kick-off Meeting with an instructional designer. The instructor has approximately \<b\>" + totalDays + " weeks\</b\> from their course start date to participate in training and build their Canvas course." + "\<br\>\<br\>" + "Next steps: \<ul\>\<li\>The instructor will use their personalized \<b\>Action Plan checklist\</b\> and reference the \<b\>CSGCB course\</b\> to learn Canvas and build relevant course elements.\</li\>\<li\>The instructor can attend live training sessions held each week to learn more about using Canvas, Zoom, and Panopto for video recording. \</li\>\<li\>The instructor can contact ATLI with questions at any point as they work their way through the Action Plan. \</li\>\</ul\> You will receive the next training update when " + instructorFirst + " completes the first set of major milestone tasks in the Action Plan." + "\<br\>\<br\>\<br\>" + "\<span style='background-color: #daebfd; font-size: 16px; padding: 1px;'\>\<b\>Please do not reply to this message via e-mail.\</b\> This address is automated, unattended, and cannot help with questions or requests. For assistance, contact UCLA Extension Learning Support at " + "\<b\>\<a href='mailto:atli#uclaextension.edu'\>atli#uclaextension.edu\</a\>\</b\>\</span\>." + "\<br\>\<br\>"
MailApp.sendEmail(recipients, subject, body,{htmlBody: contentHTML})
ss.toast("Email notification has been sent successfully.",'Status')
return
}
function moveTabs() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = e.source.getActiveSheet();
var r = e.source.getActiveRange();
if(s.getName() == "InProgress" && r.getColumn() == 35 && r.getValue() == "Y") {
var row = r.getRow();
var numColumns = s.getLastColumn();
var targetSheet = ss.getSheetByName("Completed");
var target = targetSheet.getRange(targetSheet.getLastRow() + 1, 1);
s.getRange(row, 1, 1, numColumns).moveTo(target);
s.deleteRow(row);
}
}
Just hoping to get both functions to work. Right now, combined, only the top function works and triggers an email to go out.

Related

Referencing Edited Row Instead of getLastRow

My current code is listed below (triggered by on change). It creates a calendar event when a new "lead" is entered in our lead sheet via AppSheet. It currently only runs when a new lead aka new row is added. I would like it to also run when the appointment date is added or modified, so if a lead is entered but appointment is not set up at that time, it can be entered later and the calendar event will be created. Therefore, I know that if (e.changeType == "OTHER") will need to be changed to if (e.changeType == "OTHER" || "EDIT") and that I can no longer use sheet.getLastRow().
My question is what should I replace sheet.getLastRow() with and most importantly, how will I call/reference the row that was impacted by:
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("Y:Y");
if (e.changeType == "OTHER" || "EDIT")
Essentially, what do I need to set the current var lastRow equal to so that it will call the row where the change was made instead of the last row? (I will of course change the name of the variable from lastRow to something more applicable when I do so)
Original Code:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
// Calendar to output requests
var calendar = CalendarApp.getCalendarById('youremail#gmail.com');
// Creates an object from the last form submission
function getSubmission() {
this.timestamp = sheet.getRange(lastRow, 9).getValue();
this.accountNumber = sheet.getRange(lastRow, 10).getValue();
this.contactLastName = sheet.getRange(lastRow, 11).getValue();
this.contactFirstName = sheet.getRange(lastRow, 12).getValue();
this.contactPhoneNumber = sheet.getRange(lastRow, 15).getValue();
this.contactEmail = sheet.getRange(lastRow, 16).getValue();
this.userLastName = sheet.getRange(lastRow, 37).getValue();
this.userFirstName = sheet.getRange(lastRow, 38).getValue();
this.userPhoneNumber = sheet.getRange(lastRow, 39).getValue();
this.userEmail = sheet.getRange(lastRow, 40).getValue();
this.streetAddress = sheet.getRange(lastRow, 17).getValue();
this.city = sheet.getRange(lastRow, 18).getValue();
this.state = sheet.getRange(lastRow, 19).getValue();
this.zipCode = sheet.getRange(lastRow, 20).getValue();
this.type = sheet.getRange(lastRow, 21).getValue();
this.equipment = sheet.getRange(lastRow, 22).getValue();
this.typeOfLead = sheet.getRange(lastRow, 13).getValue();
this.sourceOfLead = sheet.getRange(lastRow, 14).getValue();
this.notes = sheet.getRange(lastRow, 23).getValue();
this.date = new Date(sheet.getRange(lastRow, 24).getValue());
this.appointmentStart = sheet.getRange(lastRow, 25).getValue();
this.appointmentEnd = sheet.getRange(lastRow, 26).getValue();
this.direction = sheet.getRange(lastRow, 27).getValue();
this.callOnWay = sheet.getRange(lastRow, 28).getValue();
return this;
}
// Creates a calendar event using the submitted data
function updateCalendar(request) {
request.date.setHours(request.appointmentStart.getHours());
request.date.setMinutes(request.appointmentStart.getMinutes());
var endTime = new Date(request.date);
endTime.setHours(request.appointmentEnd.getHours());
endTime.setMinutes(request.appointmentEnd.getMinutes())
var event = calendar.createEvent(
request.state + " " + request.direction + " EST " + request.contactLastName + ", " + request.contactFirstName + " " + request.callOnWay,
request.date,
endTime
)
.setLocation(request.streetAddress + " " + request.city + ", " + request.state + " " + request.zipCode
)
.setDescription("Account # " + request.accountNumber + "\n" + "\n" + request.contactFirstName + " " + request.contactLastName + "\n" + request.contactPhoneNumber + "\n" + request.contactEmail + "\n" + "\n" + "Notes: " + request.type + " - " + request.equipment + ". " + request.notes + ".\n" + "Lead: " + request.typeOfLead + " - " + request.sourceOfLead + "." + "\n" + "\n" + "Jim: Scanned:____ " + "Inv. Adj:____ " + "QB:____ " + "Est. SL:____" + "\n" + "\n" + "Tracy: QB:____" + " Scan:____" + " Letter:____" + " Lead Sheet:____" + " Ref. Check #:____"
)
}
// --------------Main--------------
function main() {
var request = getSubmission();
updateCalendar(request);
}
function runMain(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("Y:Y");
if (e.changeType == "OTHER") {
main();
}
}
I am still quite new to writing in App Script, so any help is greatly appreciated!
Updated code with suggestions from #YuriKhristich:
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
// Calendar to output requests to
var calendar = CalendarApp.getCalendarById('youremail#gmail.com');
// Creates an object from the last submission
function getSubmission(row) {
var data = sheet.getRange(row,9,1,40).getValues();
this.timestamp = row[ 9];
this.accountNumber = row[10];
this.contactLastName = row[11];
this.contactFirstName = row[12];
this.contactPhoneNumber = row[15];
this.contactEmail = row[16];
this.userLastName = row[37];
this.userFirstName = row[38];
this.userPhoneNumber = row[39];
this.userEmail = row[40];
this.streetAddress = row[17];
this.city = row[18];
this.state = row[19];
this.zipCode = row[20];
this.type = row[21];
this.equipment = row[22];
this.typeOfLead = row[13];
this.sourceOfLead = row[14];
this.notes = row[23];
this.date = new Date(row[24]);
this.appointmentStart = row[25];
this.appointmentEnd = row[26];
this.direction = row[27];
this.callOnWay = row[28];
return this;
}
// Creates a calendar event using the submitted data
function updateCalendar(request) {
request.date.setHours(request.appointmentStart.getHours());
request.date.setMinutes(request.appointmentStart.getMinutes());
var endTime = new Date(request.date);
endTime.setHours(request.appointmentEnd.getHours());
endTime.setMinutes(request.appointmentEnd.getMinutes())
var event = calendar.createEvent(
request.state + " " + request.direction + " EST " + request.contactLastName + ", " + request.contactFirstName + " " + request.callOnWay,
request.date,
endTime
)
.setLocation(request.streetAddress + " " + request.city + ", " + request.state + " " + request.zipCode
)
.setDescription("Account # " + request.accountNumber + "\n" + "\n" + request.contactFirstName + " " + request.contactLastName + "\n" + request.contactPhoneNumber + "\n" + request.contactEmail + "\n" + "\n" + "Notes: " + request.type + " - " + request.equipment + ". " + request.notes + ".\n" + "Lead: " + request.typeOfLead + " - " + request.sourceOfLead + "." + "\n" + "\n" + "Jim: Scanned:____ " + "Inv. Adj:____ " + "QB:____ " + "Est. SL:____" + "\n" + "\n" + "Tracy: QB:____" + " Scan:____" + " Letter:____" + " Lead Sheet:____" + " Ref. Check #:____"
)
}
// --------------Main--------------
function main() {
var request = getSubmission(lastRow);
updateCalendar(request);
}
function runMain(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange("Y:Y");
if (e.changeType == "OTHER") {
main();
}
}
function onEdit(e) {
if (e.range.columnStart != 25) return;
var request = getSubmission(e.range.rowStart);
updateCalendar(request);
}
Receiving the error message "TypeError: Cannot read property 'getHours' of undefined" when adding a new lead or editing appointment date.
runMain is being triggered via the installable trigger On Change.
Will an On Edit trigger need to be implemented to run the onEdit function or is that repetitive?
You can create another installable trigger onEdit (either manually or in Apps Script) to check which row was edited and then call getSubmission with that row number as parameter.
function getRow(e) {
var currentRow = e.range.getRow();
var request = getSubmission(currentRow);
updateCalendar(request);
}
Try to change the functions getSubmission() this way:
function getSubmission(row) { // <-- add 'row' argument here
var data = sheet.getRange(row,9,1,40).getValues(); // make one call to server instead of 24
this.timestamp = row[ 9];
this.accountNumber = row[10];
this.contactLastName = row[11];
this.contactFirstName = row[12];
this.contactPhoneNumber = row[15];
this.contactEmail = row[16];
this.userLastName = row[37];
this.userFirstName = row[38];
this.userPhoneNumber = row[39];
this.userEmail = row[40];
this.streetAddress = row[17];
this.city = row[18];
this.state = row[19];
this.zipCode = row[20];
this.type = row[21];
this.equipment = row[22];
this.typeOfLead = row[13];
this.sourceOfLead = row[14];
this.notes = row[23];
this.date = new Date(row[24]);
this.appointmentStart = row[25];
this.appointmentEnd = row[26];
this.direction = row[27];
this.callOnWay = row[28];
return this;
}
Change the main() function this way:
function main() {
var request = getSubmission(lastRow); // <-- add 'lastRow' argument here
updateCalendar(request);
}
And add the onEdit() function:
function onEdit(e) {
if (e.range.columnStart != 25) return; // if column Y
// probably it makes sense to check the name of the sheet as well
var request = getSubmission(e.range.rowStart);
updateCalendar(request);
}

Create Trigger to Run Script Only When New Row is Added to Spreadsheet

I have what seems to be a relatively simple task, but cannot seem to figure it out. I've written a script that creates a calendar event when a form is submitted. We will no longer be using the form (moving to AppSheet instead) so, I need the trigger to fire ONLY when a new row is added. I believe "onChange" is the way to go about this, but I only want the script to run when a row is added, not when it is edited, deleted, or changed in any other way. Any suggestions?
// Create Calendar Event From Spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
// Calendar to output requests
var calendar = CalendarApp.getCalendarById('youremail#gmail.com');
// Creates an object from the last row
function getSubmission() {
this.timestamp = sheet.getRange(lastRow, 1).getValue();
this.accountNumber = sheet.getRange(lastRow, 2).getValue();
this.contactLastName = sheet.getRange(lastRow, 3).getValue();
this.contactFirstName = sheet.getRange(lastRow, 4).getValue();
this.contactPhoneNumber = sheet.getRange(lastRow, 5).getValue();
this.contactEmail = sheet.getRange(lastRow, 6).getValue();
this.userLastName = sheet.getRange(lastRow, 7).getValue();
this.userFirstName = sheet.getRange(lastRow, 8).getValue();
this.userPhoneNumber = sheet.getRange(lastRow, 9).getValue();
this.userEmail = sheet.getRange(lastRow, 10).getValue();
this.streetAddress = sheet.getRange(lastRow, 11).getValue();
this.city = sheet.getRange(lastRow, 12).getValue();
this.state = sheet.getRange(lastRow, 13).getValue();
this.zipCode = sheet.getRange(lastRow, 14).getValue();
this.type = sheet.getRange(lastRow, 15).getValue();
this.equipment = sheet.getRange(lastRow, 16).getValue();
this.typeOfLead = sheet.getRange(lastRow, 17).getValue();
this.sourceOfLead = sheet.getRange(lastRow, 18).getValue();
this.notes = sheet.getRange(lastRow, 19).getValue();
this.date = new Date(sheet.getRange(lastRow, 20).getValue());
this.appointmentStart = sheet.getRange(lastRow, 21).getValue();
this.appointmentEnd = sheet.getRange(lastRow, 22).getValue();
this.direction = sheet.getRange(lastRow, 23).getValue();
this.callOnWay = sheet.getRange(lastRow, 24).getValue();
return this;
}
// Creates a calendar event using the last row
function updateCalendar(request) {
request.date.setHours(request.appointmentStart.getHours());
request.date.setMinutes(request.appointmentStart.getMinutes());
var endTime = new Date(request.date);
endTime.setHours(request.appointmentEnd.getHours());
endTime.setMinutes(request.appointmentEnd.getMinutes())
var event = calendar.createEvent(
request.state + " " + request.direction + " EST " + request.contactLastName + ", " + request.contactFirstName + " " + request.callOnWay,
request.date,
endTime
)
.setLocation(request.streetAddress + " " + request.city + ", " + request.state + " " + request.zipCode
)
.setDescription("Account # " + request.accountNumber + "\n" + "\n" + request.contactFirstName + " " + request.contactLastName + "\n" + request.contactPhoneNumber + "\n" + request.contactEmail + "\n" + "\n" + "Notes: " + request.type + " - " + request.equipment + ". " + request.notes + ".\n" + "Lead: " + request.typeOfLead + " - " + request.sourceOfLead + "." + "\n" + "\n" + "Jim: Scanned:____ " + "Inv. Adj:____ " + "QB:____ " + "Est. SL:____" + "\n" + "\n" + "Tracy: QB:____" + " Scan:____" + " Letter:____" + " Lead Sheet:____" + " Ref. Check #:____"
)
}
// --------------Main--------------
function main() {
var request = getSubmission();
updateCalendar(request);
}
Use onChange with changeType = "INSERT_ROW"
Your code will run probably ten times faster if you use one getValues();
I would just correlate the column numbers to the names with an array and an object.
I'm not going to actually do it. I'll leave that as an exercise for the reader.
By the way using the lastRow for a form submission is a bad idea. You should use event object values or namedValues. If you get a lot of submissions at the same time your code will have problems.
function getSubmission(e) {
if(e.changeType == "INSERT_ROW") {
//put code here
}
}
It seems that INSERT_ROW only registers when a row is manually inserted (right click, insert row above or below). It does not run when data is added via AppSheet, a form, or typed in. Below is the code I have added o my script which behaves as expected when a row is manually inserted. Is there any way to have the script run when data is entered into a new row via an outside source or typed into the row?
function runMain(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
if (e.changeType == "INSERT_ROW") {
main();
}
}
Here is a simple standalone test script I have been using to check what inputs into the sheet fire the script.
function notify(e) {
MailApp.sendEmail("youremail#gmail.com.com", "Row Added", "A row was added to your sheet.");
}
function runNotify(e) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
if (e.changeType == "INSERT_ROW") {
notify(e);
}
}

Trouble automating email from google sheets

I am very new to google script and cannot work out why my script is not functioning. When I try to run the code I get the following error code -
TypeError: Cannot read property "range" from undefined. (line 2, file "Code"
If anybody could give a novice some help that would be greatly appreciated!
function sendEmail(event){
var sheet = event.range.getSheet();
if(sheet.getName() !== 'Sheet1') {
// if it's not the correct sheet we end the function here
return;
}
var range = event.range;
var row = range.getRow(); // we get the index of the row of the
edited
cell
var dataRange = sheet.getRange("A" + row + ":C" + row);
var values = dataRange.getValues();
var rowValues = values[0];
var recipient = rowValues[0];
var email = rowValues[1];
var refillsNumber = rowValues[2];
if (refillsNumber = 2) {
// if 'refillsNumber' is not equal to 2 we end the function here
var message = 'Dear ' + recipient + ',\n\n'+ 'You have ' +
refillsNumber + ' remaining would you like to buy more?' + '\n\n' +
'Kind regards,' + '\n\n' + 'The revol team.';
var subject = 'Refill reminder';
MailApp.sendEmail(email,subject,message);
return
}
if (refillsNumber !== 0) {
return}
var message = 'Dear ' + recipient + ',\n\n'+ 'You have ' +
refillsNumber + ' remaining would you like to buy more? If not then
would you like to end your subsription?' + '\n\n' + 'Kind regards,'
+ '\n\n' + 'The revol team.';
var subject = 'Refill reminder';
MailApp.sendEmail(email,subject,message);
return
}
// in addition to this script which aims to send an email to the
customer when they only have 2 refill remaining -
/// I also want to set up a function that sends an email when they
have 0 refills remaining
Send Emails by Editing Column C
I changed the Sheet name and added an extra condition. I also commented out the MailApp.sends and replaced them with writes to the sidebar so that I could test it without trying to send emails.
You will need to create an onEdit trigger for this function.
function sendMailOnEdit(event){
var sheet = event.range.getSheet();
if(sheet.getName() !== 'Sheet2' || event.range.columnStart!=3) {return;}
var range=event.range;
var row=range.rowStart;
var dataRange = sheet.getRange(row,1,1,3);
var values=dataRange.getValues();
var rowValues=values[0];
var recipient = rowValues[0];
var email = rowValues[1];
var refillsNumber = rowValues[2];
if (refillsNumber==2) {
var message = 'Dear ' + recipient + ',\n\n'+ 'You have ' + refillsNumber + ' remaining would you like to buy more?' + '\n\n' + 'Kind regards,' + '\n\n' + 'The revol team.';
var subject = 'Refill reminder';
//MailApp.sendEmail(email,subject,message);
var html=Utilities.formatString('<br />Email: %s<br />Subject: %s<br />message: %s<br /><hr>', email,subject,message);
var userInterface=HtmlService.createHtmlOutput(html);
SpreadsheetApp.getUi().showSidebar(userInterface);
return
}
if (refillsNumber !== 0) {return}
var message = 'Dear ' + recipient + ',\n\n'+ 'You have ' + refillsNumber + ' remaining would you like to buy more? If not then would you like to end your subsription?' + '\n\n' + 'Kind regards,' + '\n\n' + 'The revol team.';
var subject = 'Refill reminder';
//MailApp.sendEmail(email,subject,message);
var html=Utilities.formatString('<br />Email: %s<br />Subject: %s<br />message: %s<br /><hr>', email,subject,message);
var userInterface=HtmlService.createHtmlOutput(html);
SpreadsheetApp.getUi().showSidebar(userInterface);
}
This is what my spreadsheet looks like:
And let me remind you that you cannot run this function without an event object.

Sending emails once a cell has changed in Google SpreadSheets

I need help with a script that I have created. I need to send an email to myself or manager any time cell "F" is changed to "Yes". I think my code is okay, but I don't think my triggers are allowing me to complete the function. Any help would be appreciated.
function sendNotification() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = ss.getActiveCell().getA1Notation();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
var sendto = 'd.hammond#permasteelisagroup.com';
if(cell.indexOf('F')!=-1){
sendto = sheet.getRange('F'+ sheet.getActiveCell().getRowIndex()).getValue()
}
var designer = '';
designer = sheet.getRange('A' + sheet.getActiveCell().getRowIndex()).getValue()
var assignment = '';
assignment = sheet.getRange('B' + sheet.getActiveCell().getRowIndex()).getValue()
var comment = '';
comment = sheet.getRange('I' + sheet.getActiveCell().getRowIndex()).getValue()
var checked_by = '';
checked_by = sheet.getRange('G' + sheet.getActiveCell().getRowIndex()).getValue()
var mysubject = ss.getName() + ':' + 'Review Drawing: \n';
var mybody = 'Please review: ' + assignment + ' \n' + 'Drawn by: ' + designer + '\n' + 'Please review any comments' + comment + ' \n' + 'Due by: ' + checked_by;
MailApp.sendEmail({
to:sendto,
subject:mysubject,
body:mybody});
};
*

Store and Increment a value by one on every new Google Form submission

When a customer completes a form, I want a new ticket number to be created and sent in an email.
The first error:
"cannot read property "range" from undefined (line 9, file "Code")
and then, on lines 11, 13, and 21, I have some code to control a ticket counter to generate a unique ticket number each time the form is submitted. When I ran 2 test forms through the system, the ticket number did not populate and the counter variable did not change.
function onFormSubmit(e) {
var activateSheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(activateSheet.getSheetByName('Form Responses 1'));
var sheet = SpreadsheetApp.getActiveSheet();
var row = e.range.getRowIndex(); *** line 9***
var ticketCounter = 100; ***line 11***
var ticketNumber = "FCB" + ticketCounter; ***line 13***
var etrolControlsServiceEmail = "controls-service#etrol.net";
var timestamp = sheet.getRange(row, 1).getValues();
var ticketNumberLocation = sheet.getRange(row, 2);
ticketNumberLocation.setValue(ticketNumber); ***line 21***
var location = sheet.getRange(row, 3).getValues();
var reportedBy = sheet.getRange(row, 4).getValues();
var customerEmailAddress = sheet.getRange(row, 5).getValues();
var priority = sheet.getRange(row, 6).getValues();
var customerIssue = sheet.getRange(row, 7).getValues();
var subject = "An issue has been reported at " + location + " " + timestamp + " " + "Ticket Number " + ticketNumber;
var emailBody = "To: Envirotrol Controls Service Department " + "\nRE: Issue reported at " + location + "." + "\n\nAn issue has been reported at " + location + ". Please see the details below:" + "\n\nTicket Number: " + ticketNumber + "\nLocation: " + location + "\nReported By: " + reportedBy + "\nPriority Level: " + priority + "\nIssue: " + customerIssue;
MailApp.sendEmail(customerEmailAddress + ", " + etrolControlsServiceEmail, subject, emailBody);
ticketCounter += 1};
This code shows the strategy for storing, retrieving and incrementing the ticketCounter value in the Spreadsheets Document Properties.
function onFormSubmit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet(),
shFormResponses = ss.getSheetByName('Form Responses 1');
ss.setActiveSheet(shFormResponses);
var row = e.range.getRowIndex(),
ticketCounter = PropertiesService
.getDocumentProperties()
.getProperty('ticketCounter');
if (ticketCounter === undefined || ticketCounter === null) {
PropertiesService.getDocumentProperties().setProperty('ticketCounter', '100');
ticketCounter = '100';
};
var ticketNumber = "FCB" + ticketCounter,
etrolControlsServiceEmail = "controls-service#etrol.net",
timestamp = shFormResponses.getRange(row, 1).getValues(),
ticketNumberLocation = shFormResponses.getRange(row, 2);
ticketNumberLocation.setValue(ticketNumber);
var location = shFormResponses.getRange(row, 3).getValues();
var reportedBy = shFormResponses.getRange(row, 4).getValues();
var customerEmailAddress = shFormResponses.getRange(row, 5).getValues();
var priority = shFormResponses.getRange(row, 6).getValues();
var customerIssue = shFormResponses.getRange(row, 7).getValues();
var subject = "An issue has been reported at " + location + " " +
timestamp + " " + "Ticket Number " + ticketNumber;
var emailBody = "To: Envirotrol Controls Service Department " +
"\nRE: Issue reported at " + location + "." +
"\n\nAn issue has been reported at " + location +
". Please see the details below:" + "\n\nTicket Number: " +
ticketNumber + "\nLocation: " + location + "\nReported By: " +
reportedBy + "\nPriority Level: " + priority + "\nIssue: " +
customerIssue;
MailApp.sendEmail(customerEmailAddress + ", " + etrolControlsServiceEmail, subject, emailBody);
//Values are stored as text in the Properties Service
var numberAsNumber = Number(ticketCounter);
ticketCounter = (numberAsNumber + 1).toString();
PropertiesService
.getDocumentProperties()
.setProperty('ticketCounter', ticketCounter);
};