I recently came across a video from Kurt Kaiser where he goes through the process of creating an Appointment Booking System.
I'm new to coding and I followed his steps along with having the code that he has shared and I cannot seem to get this to work. For some reason after I submit the form and approve the request it never puts the event in my calendar.
I'm calling the calendar in the script I made by the ID. Is there something else I need to do after I create the calendar in order for this to work?
Do I need to make my calendar public in google?
Again I followed his instruction video to the T and still don't get the events in the calendar.
I also get an error for name under the :// Creates a calendar event using the submitted data in the code below, I believe it said it wasn't defined. But maybe that's because I was just running the script?
I have tried to reach out to the author of the code but he has not responded.
Again he has freely shared this code from his website.
Any help would greatly be appreciated as I have been pulling my hair out on this project and trying to come up with a booking system that uses google forms for my team.
`// Calendar Reservation Approval System
// Kurt Kaiser, 2018
// All Rights Reserved
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
**// Calendar to output requests
var calendar = CalendarApp.getCalendarById('bfpkrilvj3avj0srbelt3n89rc#group.calendar.google.com');**
// Creates an object from the last form submission
function Submission(row){
this.timestamp = sheet.getRange(row, 1).getValue();
this.name = sheet.getRange(row, 2).getValue();
this.reason = sheet.getRange(row, 3).getValue();
this.date = new Date(sheet.getRange(row, 4).getValue());
this.dateString = (this.date.getMonth() + 1) + '/' +
this.date.getDate() + '/' + this.date.getYear();
this.time = sheet.getRange(row,5).getValue();
this.timeString = this.time.toLocaleTimeString();
this.email = sheet.getRange(row, 6).getValue();
// Adjust time and make end time
this.date.setHours(this.time.getHours());
this.date.setMinutes(this.time.getMinutes());
this.endTime = new Date(this.date);
this.endTime.setHours(this.time.getHours() + 2);
}
// Check for conflicting events
function getConflicts(request) {
var conflicts = calendar.getEvents(request.date, request.endTime);
if (conflicts.length < 1) {
request.status = "New";
} else {
request.status = "Conflict";
sheet.getRange(lastRow, lastColumn - 1).setValue("Reject");
sheet.getRange(lastRow, lastColumn).setValue("Sent: Conflict");
}
}
// Convert data of status and notified columns into array
function StatusObject(){
this.statusArray = sheet.getRange(1, lastColumn -1, lastRow, 1).getValues();
this.notifiedArray = sheet.getRange(1, lastColumn, lastRow, 1).getValues();
this.statusArray = [].concat.apply([], this.statusArray);
this.notifiedArray = [].concat.apply([], this.notifiedArray);
}
// Get the index of the row that has had a status change
function getChangeIndex(statusChange){
statusChange.index = statusChange.notifiedArray.indexOf("");
statusChange.row = statusChange.index + 1;
if (statusChange.index == -1){
return;
} else if (statusChange.statusArray[statusChange.index] != "") {
statusChange.status = statusChange.statusArray[statusChange.index];
sheet.getRange(statusChange.row, lastColumn).setValue("Sent: " + statusChange.status);
statusChange.notifiedArray[statusChange.index] = "update";
} else {
statusChange.status = statusChange.statusArray[statusChange.index];
statusChange.notifiedArray[statusChange.index] = "no update";
}
}
// Draft contents for emails depending on needed message
function draftEmail(request){
request.buttonLink = "button URL" // I would have the URL in place here for the button
request.buttonText = "New Request";
switch (request.status) {
case "New":
request.subject = "Request for " + request.dateString + " Appointment Received";
request.header = "Request Received";
request.message = "Once the request has been reviewed you will receive an email updating you on it.";
break;
case "New2":
request.email = "myemail#address.com";
request.subject = "New Request for " + request.dateString;
request.header = "Request Received";
request.message = "A new request needs to be reviewed.";
request.buttonLink = "https://link to the spreadsheet";// I would have the URL to my spreadsheet here
request.buttonText = "View Request";
break;
case "Approve":
request.subject = "Confirmation: Appointment for " + request.dateString + " has been scheduled";
request.header = "Confirmation";
request.message = "Your appointment has been scheduled.";
break;
case "Conflict":
request.subject = "Conflict with " + request.dateString + " Appointment Request";
request.header = "Conflict";
request.message = "There was a scheduling conflict. Please reschedule.";
request.buttonText = "Reschedule";
break;
case "Reject":
request.subject = "Update on Appointment Requested for " + request.dateString;
request.header = "Reschedule";
request.message = "Unfortunately the request times does not work. Could "+
"we reschedule?";
request.buttonText = "Reschedule";
break;
}
}
// Creates a calendar event using the submitted data
function updateCalendar(request){
var event = calendar.createEvent(
request.name,
request.date,
request.endTime
)
}
// Send Email
function sendEmail(request){
MailApp.sendEmail({
to: request.email,
subject: request.subject,
htmlBody: makeEmail(request)
})
}
// -------------------- Main Functions ---------------------
function onFormSubmission(){
var request = new Submission(lastRow);
getConflicts(request);
draftEmail(request);
sendEmail(request);
if (request.status == "New"){
request.status = "New2";
draftEmail(request);
sendEmail(request);
}
}
// Triggered function to check if any status has changed
function onEdit(){
var statusChange = new StatusObject();
while (true){
getChangeIndex(statusChange);
if (statusChange.index == -1){
return;
} else {
var request = new Submission(statusChange.row);
if (statusChange.status){
request.status = statusChange.status;
if (statusChange.status == "Approve"){
updateCalendar(request);
}
draftEmail(request);
sendEmail(request);
}
}
}
}`
Personally I would do this a little differently:
function onFormSubmission(e){
var request = new Submission(e.range.rowStart);//this determines which row the form just modified
getConflicts(request);
draftEmail(request);
sendEmail(request);
if (request.status == "New"){
request.status = "New2";
draftEmail(request);
sendEmail(request);
}
}
also the below onEdit function cannot just be a simple trigger because some of the functions require permission. This will have to be an installable trigger and don't forget to change the name when you create the installable trigger otherwise the function will get two triggers a simple trigger and an installable trigger
function onEdit(){
var statusChange = new StatusObject();
while (true){
getChangeIndex(statusChange);
if (statusChange.index == -1){
return;
} else {
var request = new Submission(statusChange.row);
if (statusChange.status){
request.status = statusChange.status;
if (statusChange.status == "Approve"){
updateCalendar(request);
}
draftEmail(request);
sendEmail(request);
}
}
}
}
The above function must complete in 30 seconds. Actually I should say the above function will stop after 30 seconds whether it's complete or not
There have been a lot of changes to Google Apps Script since 2018 so some of this code may not work. Especially, with the new ES6.
I'm thinking that your missing an updateCalendar
function onFormSubmission(){
var request = new Submission(lastRow);
getConflicts(request);
draftEmail(request);
sendEmail(request);
if (request.status == "New"){
updateCalendar(request);//added this line
request.status = "New2";
draftEmail(request);
sendEmail(request);
}
}
Related
We use a Google form which is meant to create recurring Classroom assignments through Google Apps Script.
The script runs successfully once a user opens the form in edit mode, as she/he is prompted to authorise script execution scopes.
What is not working is when a generic user is accessing the form to only submit data: in this case there's no prompt to authorise script scopes execution, therefore the onSubmit script will run, throwing the following error:
GoogleJsonResponseException: API call to classroom.courses.courseWork.create failed with error: The caller does not have permission at onSubmit
Offending code:
var ret = Classroom.Courses.CourseWork.create(ClassSource, course);
BTW, we have set all scopes in manifest:
{
"timeZone": "Europe/Rome",
"dependencies": {
"enabledAdvancedServices": [
{
"userSymbol": "Classroom",
"version": "v1",
"serviceId": "classroom"
}
]
},
"oauthScopes": [
"https://www.googleapis.com/auth/classroom.courses",
"https://www.googleapis.com/auth/classroom.coursework.me.readonly",
"https://www.googleapis.com/auth/classroom.profile.emails",
"https://www.googleapis.com/auth/classroom.profile.photos",
"https://www.googleapis.com/auth/classroom.rosters",
"https://www.googleapis.com/auth/classroom.coursework.me",
"https://www.googleapis.com/auth/classroom.coursework.me.readonly",
"https://www.googleapis.com/auth/classroom.coursework.students",
"https://www.googleapis.com/auth/classroom.coursework.students.readonly"
],
"exceptionLogging": "STACKDRIVER",
"runtimeVersion": "V8"
}
I guess this is due to the fact the user is never prompted to authorise..... Is there a way to trigger the authorisation prompt when the form is being opened somehow?
Notice that the script uses multiple functions, and this is not helping triggering permissions authorisation as suggested here
Full script code:
function onSubmit(){
var subjects = [
['zzzzzzzzzzzz','Y9 - Art 2022-23'],
['yyyyyyyyyyyy','Y7 - Computing 2022-23'],
['xxxxxxxxxxxx','Y8 - English 2022-23']
];
try{
var formResponses = FormApp.getActiveForm().getResponses();
var length = formResponses.length;
var lastResponse = formResponses[length-1];
var respondent = lastResponse.getRespondentEmail();
var course = null;
var items = lastResponse.getItemResponses();
for (i in items){
var item = items[i].getItem();
var response = items[i].getResponse();
if (response){
var title = item.getTitle();
switch (title){
case 'Select the course':
var hwSubject = response;
var index = indexOf2dArray(subjects,response);
if (index[0] >=0){
// we've got the subject, grab course id
course = subjects[index[0]][0];
}
break;
case 'Homework title':
var hwTitle = response;
break;
case 'Instructions':
var hwInstructions = response;
break;
case 'Begin date':
var beginTextDate = response;
break;
case 'End date':
var endTextDate = response;
break;
case 'Status':
var status = (response == "Draft" ? 'DRAFT' : 'PUBLISHED');
break;
case 'Assignment Time slot':
var timeSlot = response;
break;
}
}
}
var beginDate = new Date(beginTextDate);
var endDate = new Date(endTextDate);
var creationResponse = '';
if (course && beginDate < endDate){
while(beginDate <= endDate){
console.log(beginDate);
var dueDate = {
"year": beginDate.getUTCFullYear(),
"month": beginDate.getUTCMonth()+1,
"day": beginDate.getUTCDate()
}
var dueTime = {
"hours": parseInt(timeSlot.split(':')[0]),
"minutes": parseInt(timeSlot.split(':')[1]),
"seconds": 0,
"nanos": 0
}
var ClassSource = {
title: hwTitle,
description: hwInstructions,
state: status,
dueDate : dueDate,
dueTime : dueTime,
workType: "ASSIGNMENT"
};
var ret = Classroom.Courses.CourseWork.create(ClassSource, course);
creationResponse += `<br> Assignment status ${status}, due date:${JSON.stringify(dueDate)}`;
Utilities.sleep(500);
var newDate = beginDate.setDate(beginDate.getDate() + 1);
beginDate = new Date(newDate);
}// end while
var emailSubject = "** Classroom recurring homework form response";
var emailBody = `<strong>Recurring assignment creation response</strong><br>Course: ${hwSubject}, begin date: ${beginTextDate}, end date: ${endTextDate} <br/>`;
emailBody += '<br><strong>Homework title:</strong> ' + hwTitle;
emailBody += '<br><strong>Homework instructions:</strong> ' + hwInstructions + '<br><br>';
emailBody += `<br/><strong>Status:</strong> ${creationResponse}<br/>`;
var emailRecipients = respondent;
doEmail(emailSubject,emailBody,emailRecipients);
}else{
var emailSubject = "** Classroom recurring homework form error";
var emailBody = `<strong>Course not selected or invalide date ranges</strong><br>course: ${course}, begin date: ${beginTextDate}, end date: ${endTextDate} <br/>`;
var emailRecipients = respondent;
doEmail(emailSubject,emailBody,emailRecipients);
}
}catch(err){
console.log(err);
var emailSubject = "** Classroom recurring homework form error";
var emailBody = "<strong>This is an automated message.</strong><br/>";
emailBody += `<br/>Could not schedule homework assignment.<br/>`;
emailBody += `<br/>${err.stack}<br/>`;
var emailRecipients = respondent;
doEmail(emailSubject,emailBody,emailRecipients);
}
}
function indexOf2dArray(array2d, itemtofind) {
index = [].concat.apply([], ([].concat.apply([], array2d))).indexOf(itemtofind);
// return "false" if the item is not found
if (index === -1) { return false; }
// Use any row to get the rows' array length
// Note, this assumes the rows are arrays of the same length
numColumns = array2d[0].length;
// row = the index in the 1d array divided by the row length (number of columns)
row = parseInt(index / numColumns);
// col = index modulus the number of columns
col = index % numColumns;
return [row, col];
}
function doEmail(emailSubject, emailBody,emailRecipients){
MailApp.sendEmail({
from: Session.getActiveUser().getEmail,
to: emailRecipients,
subject: emailSubject,
htmlBody: emailBody,
name: "Our Mailing"
});
}
EDIT:
To allow proper operations, not only the user is required to be a Form editor, but the user is required to debug at least once the onSubmit script, which will trigger the authorisation process.
I guess this is a Google Forms architecture limitation, since the onSubmit function is run on the server side, defeating any possibility to trigger authorisation on the client side beforehand :-(
I have a google sheet with a dropdown menu. When the cell the drop down is in is equal to a certain string a pop up shows up on screen. You answer yes or no.
When you answer yes it sends the email. If you answer no it does not send the email and resets the cell to its previous state.
The issue I am having is that if you select no it does reset to the previous data, but it still sends the email regardless. Please help. I am fairly new and still learning.
UPDATE:
Please see the update below. The only var I had to fix was for rData, other than that the script works as intended now. Thank you so much for your time and input. This was a headache for some time.
function sendMailEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ui = SpreadsheetApp.getUi();
if (ss.getSheetName() == 'Project List' &
ss.getActiveCell().getColumn() == 3 &
ss.getActiveCell().getValue() == "_Complete") {
var alertPromptText = 'Are you sure you want to select Complete? ' +
'This action will notify all parties in the next process that this job is ready for fabrication.';
var promptResponse = ui.alert(alertPromptText, ui.ButtonSet.YES_NO);
if (promptResponse == ui.Button.YES) {
// CHECK START
// variable email needs to be fixed. It gets the column of values.
// it needs to be converted to a comma separated list of recepients
var email = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Email").getRange(1, 1, 100).getValues();
// CHECK END
var rData = e.source.getActiveSheet().getRange(e.range.rowStart,1,1,12).getValues();
sendEmail(email,rData);
} else { // For both 'No' and cancel response to pop-up
fix(e);
}
}
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
function sendEmail(email,rData) {
var first = 0;
var email = 1;
var emailTemp = HtmlService.createTemplateFromFile("send");
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Email");
var data = ws.getRange("A1:B" + ws.getLastRow()).getValues();
var lj = rData[0][1];
var j = rData[0][5];
var d = rData[0][3];
var p = rData[0][4];
var m = rData[0][7];
var desc = rData[0][11];
var now = new Date().toLocaleString("en-US");
var msg1 = "Laser Job Number: " + lj + " (" + now + ")" +
"\nProject Job Number: " + j +
"\nDesigner: " + d +
"\nDate Project was Submitted to Programming: " + p +
"\nMaterial used: " + m +
"\nDescription: " + desc;
var subject = "Project Ready for Fab";
Logger.log(msg1);
data.forEach(function(row){
emailTemp.fn = row[first];
emailTemp.msg = msg1;
emailTemp.j = j;
emailTemp.d = d;
emailTemp.lj = lj;
emailTemp.p = p;
emailTemp.m = m;
emailTemp.desc = desc;
//emailTemp.cart = cart;
const htmlMessage = emailTemp.evaluate().getContent();
GmailApp.sendEmail(row[email], subject, "Please open with an email client that supports HTML",
{htmlBody: htmlMessage});
return;
});
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
function fix(e) {
e.range.setNote(e.oldValue);
e.range.setValue(e.range.getNote());
e.range.clearNote();
}
You need to set a variable to capture the response to the pop-up.
And then compare the value of the variable for the go-no-go part of the script.
For example:
var response = ui.prompt('Alert', 'Are you sure you want to select Complete?', ui.ButtonSet.YES_NO);
And then
if (response.getSelectedButton() == ui.Button.YES) { ... }
More here in the documentation.
Update
Try the following script. You'll need to set the onEdit trigger to run the function SendMailEdit
Also, check the code for getting the list of email recepients. Not sure if it will work.
function sendMailEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ui = SpreadsheetApp.getUi();
if (ss.getSheetName() == 'Project List' &
ss.getActiveCell().getColumn() == 3 &
ss.getActiveCell().getValue() == "_Compvare") {
var alertPromptText = 'Are you sure you want to select Compvare? ' +
'This action will notify all parties in the next process that this job is ready for fabrication.';
var promptResponse = ui.alert(alertPromptText, ui.ButtonSet.YES_NO);
if (promptResponse.getSelectedButton() == ui.Button.YES) {
// CHECK START
// variable email needs to be fixed. It gets the column of values.
// it needs to be converted to a comma separated list of recepients
var email = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Email").getRange(1, 1, 100).getValues();
// CHECK END
var rData = ss.getRange(ss.getActiveCell().getRow(), 1, 1, 12).getValues();
sendEmail(email, rData);
} else { // For both 'No' and cancel response to pop-up
fix(e);
}
}
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
function sendEmail(email, rData) {
var lj = rData[0][1];
var j = rData[0][5];
var d = rData[0][3];
var p = rData[0][4];
var m = rData[0][7];
var desc = rData[0][11];
var now = new Date().toLocaleString("en-US");
var msg = "Laser Job Number: " + lj + " (" + now + ")" +
"\nProject Job Number: " + j +
"\nDesigner: " + d +
"\nDate Project was Submitted to Programming: " + p +
"\nMaterial used: " + m +
"\nDescription: " + desc;
Logger.log(msg);
GmailApp.sendEmail(email, "Project Ready for Fab", msg);
return;
}
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
function fix(e) {
e.range.setNote(e.oldValue);
e.range.setValue(e.range.getNote());
e.range.clearNote();
}
Am trying to add a Guest to the calendar through google apps script that takes a calendar request from the user through Google forms---> it then updates a Google online excel sheet if no conflicts and makes the reservation if no conflict all this works fine but if the user tries to edit the time for the reservation they can't as they aren't the owner of the calendar to make edits so the only workaround I could think of is adding there email from the submitted request and add them as guest to that specific event but it ended unsuccessfully.
user submits a google form request with his email name time etc.
google forms update google excel sheet and checks that there are no conflicts.
updates the calendar successfully and sends a confirmation to the user's email.
The user needs to edit the time of his reservation on the calendar but can't as he is not a guest and can't edit the calendar (trying to solve this by automatically adding him as a guest to the requested event.
read so solutions here on adding location but was unsuccessful in adding the user as a guest.
tried adding
var body = {
'sendNotification': true,
'attendees': attendees
};
var ret = Calendar.Events.patch(body, calendarId, eventId);
but was unsuccessful
Code looks like:
// Room Reservation
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var lastRow = sheet.getLastRow();
var lastColumn = sheet.getLastColumn();
// Calendar to output reservations to
var cal145 = CalendarApp.getCalendarById('xxxxxx#resource.calendar.google.com');
// Create use data from user submission
// This function submits data from the google form and inputs it into the "Room Reservation" sheet by the user
function Submission(){
var row = lastRow;
this.timestamp = sheet.getRange(row, 1).getValue();
this.NameReason = sheet.getRange(row, 2).getValue();
this.email = sheet.getRange(row, 3).getValue();
this.date = sheet.getRange(row, 5).getValue();
this.time = sheet.getRange(row, 6).getValue();
this.duration = sheet.getRange(row, 7).getValue();
this.room = sheet.getRange(row, 8).getValue();
// Info not from spreadsheet
this.roomInt = this.room.replace(/\D+/g, '');
this.status;
this.dateString = (this.date.getMonth() + 1) + '/' + this.date.getDate() + '/' + this.date.getYear();
this.timeString = this.time.toLocaleTimeString();
this.date.setHours(this.time.getHours());
this.date.setMinutes(this.time.getMinutes());
this.calendar = eval('cal' + String(this.roomInt));
return this;
}
// Use duration to create endTime variable
function getEndTime(request){
request.endTime = new Date(request.date);
switch (request.duration){
case "1 hour":
request.endTime.setMinutes(request.date.getMinutes() + 60);
request.endTimeString = request.endTime.toLocaleTimeString();
break;
case "2 hours":
request.endTime.setMinutes(request.date.getMinutes() + 120);
request.endTimeString = request.endTime.toLocaleTimeString();
break;
case "3 hours":
request.endTime.setMinutes(request.date.getMinutes() + 180);
request.endTimeString = request.endTime.toLocaleTimeString();
break;
}
}
// Check for appointment conflicts
function getConflicts(request){
var conflicts = request.calendar.getEvents(request.date, request.endTime);
if (conflicts.length < 1) {
request.status = "Approve";
} else {
request.status = "Conflict";
}
}
function draftEmail(request){
request.buttonLink = "xxxxxxx ";
request.buttonText = "New Request";
switch (request.status) {
case "Approve":
request.subject = "Confirmation: " + request.room + " Reservation for " + request.dateString;
request.header = "Confirmation";
request.message = "Your room reservation has been scheduled.";
break;
case "Conflict":
request.subject = "Conflict with " + request.room + "Reservation for " + request.dateString;
request.header = "Conflict";
request.message = "There is a scheduling conflict. Please pick another time."
request.buttonText = "Reschedule";
break;
}
}
function updateCalendar(request){
var event = request.calendar.createEvent(
request.NameReason,
request.date,
//request.reason,
request.endTime
)
}
function sendEmail(request){
MailApp.sendEmail({
to: request.email,
subject: request.header,
htmlBody: makeEmail(request)
})
sheet.getRange(lastRow, lastColumn).setValue("Sent: " + request.status);
}
function sendinvite(request)
{
request.addGuest(email);
}
// --------------- main --------------------
function main(){
var request = new Submission();
getEndTime(request);
getConflicts(request);
draftEmail(request);
Logger.log(request);
sendEmail(request);
if (request.status == "Approve") updateCalendar(request);
if (request.status == "Approve")
{
sendinvite(request);
}
}
The final result should let the user edit the time of the event created although he is not the owner of the calendar. the function should add the user as a guest to that specific event he requested so he could edit the time.
this script works fine currently as is without the addition of guest sendinvite function.
thanks
Google App script not firing all JavaScript pop up boxes using on edit trigger. Does not fire when a change is made to the sheet for multiple users. Also only works when it feels like it. I have set the trigger to onEdit(). My code:
function Error() {
var sheet = SpreadsheetApp.getActiveSheet();
if (sheet.getName() == "Protocal Check List 2"){
var ui = SpreadsheetApp.getUi(); // Same variations.
var ss = SpreadsheetApp.getActiveSpreadsheet();
var active = ss.getActiveCell();
var getactive = ss.getActiveCell().getDisplayValue();
var column = ss.getActiveRange().getColumn();
var row = ss.getActiveRange().getRow();
var msg = '';
var section = sheet.getRange('C'+ row);
switch (column) {
case 9:
var msg = "error 1";
break;
case 10:
var msg = "Error 2";
break;
default:
msg = "Error";
break;
}
if(getactive == "TRUE"){
if(column >= 9 && column <= 60
){
var result = ui.alert(
"pika Says",
msg,
ui.ButtonSet.YES_NO);
// Process the user's response.
if (result == ui.Button.YES) {
// User clicked "Yes".
window.alert('Task Complete: \n\n' + msg);
active.setValue('True');
} else {
var i = 0;
while (i < 1) {
var result = ui.prompt(
'Please detail cause of the problem:',
ui.ButtonSet.OK);
var text = result.getResponseText();
var textcount = text.length;
if(textcount > 0) {
i++;
}}
var cell = "H" + row;
var emailAddress = "email#gmail.com";
var d = new Date();
var n = d.toDateString();
var t = d.toTimeString();
var staffname = ss.getRange(cell).getValues();
var message = "Date: " + n +"\n\nTime: " + t +"\n\nStaff: " + staffname + "\n\nError: " + msg + "\n\nProblem: " + text;
var subject = msg;
var thedate = n + " / " + t;
ss.getRange('A1').setValue(thedate);
ss.getRange('B1').setValue(staffname);
ss.getRange('C1').setValue(msg);
ss.getRange('D1').setValue(text);
var s1 = ss.getRange('A1:D1'); //assign the range you want to copy
var s1v = s1.getValues();
var tss = SpreadsheetApp.openById('1mOzdRgKxiP5iB9j7PqUWKKo5oymWuAeQZ1jJ1s6qL9E'); //replace with destination ID
var ts = tss.getSheetByName('AB Protocal'); //replace with destination Sheet tab name
ts.getRange(ts.getLastRow()+1, 1, 1,4).setValues(s1v); //you will need to define the size of the copied data see getRange()
MailApp.sendEmail(emailAddress, subject, message);
// User clicked "No" or X in the title bar.
//ui.alert("The following note has been sent to the Duty Manager: \n\n" + text);
active.setValue('FALSE');
}}}}
}
Any help would be appreciated. I need it to run every signal time for users who have access to the sheet.
You'll have to
assume that onEdit triggers are best-effort, but may not catch all
edits done to the spreadsheet.
Bug thread is here.
To get around the bug as mentioned by Edward implemente a dumb router.
// create a new file -> router.gs
function routerOnEdit(e) {
myOnEditHook1(e);
myOnEditHook2(e);
myOnEditHook3(e);
}
I have submitted an issue, which is the updated version of a long-running 7 year issue. They closed it in 2022, saying the feature is intended. They have now added a feature where onEdit can queue up to 2 trigger events. The issue I'm having is that the second edit still does not trigger. Despite what the documentation says.
Note: The onEdit() trigger only queues up to 2 trigger events.
View the new issue here: https://issuetracker.google.com/issues/221703754
I am try to figure out is, how to write the if statement, so that it will send a separate email based on the two values it will check in the spreadsheet.
Here are the two values that are in Column N:
"In Progress"
"Completed"
Here is the code section:
var sheetNameToWatch = "Active Discs"; // Active spreadsheet that contains the data
var columnNumberToWatch = 14; // Column N
var valueToWatch1 = "In Progress"; // First value to watch for in column N
var valueToWatch2 = "Completed"; // Second value to watch for in column N
/*var valueToWatch3 = "Rejected"; // Third value to watch for in columns for labeled PM Review and Date Discs Shipped*/
var timestamp = new Date(); // Timestamp
var activeSessionuser = Session.getEffectiveUser(); //Get the current user in the spreadsheet
var replyTo = 'test#test.com';
function sendEmailNotifications(e) {
//Logger.log(JSON.stringify(e));
try{
var ss = e.source;
var sheet = ss.getActiveSheet();
var range = e.range;
//Checks the variables sheetNameToWatch + columnNumberToWatch + valueToWatch1 ("in progress")
//Sends Email to Venue Colombo Team
if (sheet.getName() == sheetNameToWatch && range.columnStart == columnNumberToWatch && (e.value == valueToWatch1)){
var confirm = Browser.msgBox('Email will be sent to the Venue Colombo Team. Do you want to sent this email?', Browser.Buttons.YES_NO);
if(confirm.toLowerCase()=='yes'){sendColomboMessage(e.range.rowStart)};
SpreadsheetApp.getActiveSpreadsheet().toast('Email Sent to Venue Colombo Team')
}
This section I am stuck trying to write the "else" or "else if" statement that will watch for value "Completed and send a different email.
else (sheet.getName() == sheetNameToWatch && range.columnStart == columnNumberToWatch && (e.value == valueToWatch2)){
var confirm = Browser.msgBox('Email will be sent to the Venue Colombo Team. Do you want to sent this email?', Browser.Buttons.YES_NO);
if(confirm.toLowerCase()=='yes'){sendVCSMessage(e.range.rowStart)};
SpreadsheetApp.getActiveSpreadsheet().toast('Email Sent to VCS Team')*/
}catch(err){Logger.log('catch err = '+err)}
}
Lastly, when I add "return;" to the code for the Browser.msgbox, it does not stops the code from running or the entire function stops working. Where or how do I add the return; if the user click "No". Then it should close the message box and do nothing.
if(confirm.toLowerCase()=='yes'){sendColomboMessage(e.range.rowStart)};
SpreadsheetApp.getActiveSpreadsheet().toast('Email Sent to Venue Colombo Team')
This should do what you are after (there is a lot of repeated functionality that could be broken out into another function):
var sheetNameToWatch = "Active Discs"; // Active spreadsheet that contains the data
var columnNumberToWatch = 14; // Column N
var valueToWatch1 = "In Progress"; // First value to watch for in column N
var valueToWatch2 = "Completed"; // Second value to watch for in column N
/*var valueToWatch3 = "Rejected"; // Third value to watch for in columns for labeled PM Review and Date Discs Shipped*/
var timestamp = new Date(); // Timestamp
var activeSessionuser = Session.getEffectiveUser(); //Get the current user in the spreadsheet
var replyTo = 'venueclientservices#rrd.com';
function sendEmailNotifications(e) {
Logger.log(JSON.stringify(e));
Logger.log('sendEmailNotifications()');
try {
var ss = e.source;
var sheet = ss.getActiveSheet();
var range = e.range;
var ass = SpreadsheetApp.getActiveSpreadsheet();
var confirm;
var getName = sheet.getName();
var columnStart = range.columnStart;
Logger.log("getName: " + sheet.getName());
Logger.log("columnStart: " + range.columnStart);
Logger.log("e.value: " + e.value);
if (getName == sheetNameToWatch &&
columnStart == columnNumberToWatch) {
if (e.value == valueToWatch1) {
Logger.log("Value 1");
confirm = Browser.msgBox('Email will be sent to the Venue Colombo Team. Do you want to sent this email?',
Browser.Buttons.YES_NO);
if (confirm.toLowerCase() == 'yes') {
sendColomboMessage(e.range.rowStart)
ass.toast('Email Sent to Venue Colombo Team')
} else {
ass.toast('Edit In Progress but no email sent');
}
} else if (e.value == valueToWatch2) {
Logger.log("Value 2");
confirm = Browser.msgBox('Email will be sent to the VCS Team. Do you want to sent this email?',
Browser.Buttons.YES_NO);
if (confirm.toLowerCase() == 'yes') {
sendVCSMessage(e.range.rowStart);
ass.toast('Email Sent to VCS Team');
} else {
ass.toast('Edit Value 2 but no email sent');
}
} else {
ass.toast('Edit, but no email sent.');
}
} // matching sheet and col
} // try
catch (err) {
Logger.log('catch err = ' + err);
}
function sendColomboMessage(row) {
Logger.log("sendColomboMessage, row: " + row);
};
function sendVCSMessage(row) {
Logger.log("sendVCSMessage, row: " + row);
};
} // sendEmailNotifications()