Time Off Request and Setting date to mm/dd/yyyy format - google-apps-script

To start with I am a total novice at GAS. Im trying to a digital time-off request using google forms and google sheets that sends out an email when approved.
I have it working but I am running into an issue because I want to print the time in a format without the extra time at the end.
I was able to get it to work by adding .toLocaleDateString("en-US") to the variables but I realized it wont work if the the cell is blank.
I would like that to run on the cell that is filled. Either column f&k when a full day is taken or column I if late.
A nice extra would be after the email is sent the row is moved to the "approved" tab.
A copy of the google sheet is here: https://docs.google.com/spreadsheets/d/1HdFERMvFtgcmqoPOe4yvD7i-HyFgo132wCnTaY-IGwA/edit?usp=sharing
function sendEmailedit(e){
if (e.range.columnStart != 12 || e.value != "TRUE") return;
const rData = e.source.getActiveSheet().getRange(e.range.rowStart,1,1,11).getValues();
let y = rData\[0\]\[10\];
let late = rData\[0\]\[8\]
let beg = rData\[0\]\[5\];
let end = rData\[0\]\[6\];
let ESLP = "https://docs.google.c"
let Subject = "Staff absence/time off request for";
let cc = "pn, td, ma"
let msg = "Your staff absence/late request for" + " " + beg + "-" + end + " " + late + " " + "has been approved by ." + "<p>" +
"<b>\<u\>All Staff:</b>\</u\>" + "<br>" +
"Please add a banner reminder (all day) onto Google Calendar and include both es and es" + " <p>" +
"<b>\<u\>Teachers:</b>\</u\>" + "<br>" +
"Please email your lesson plans to ma and pn by 8:00am the day you will be out" + "<p>" +
"<b>\<u\>Sub plans must include:</b>\</u\>" + "<br>" +
"classroom procedures, clear directions for the scholars/ substitute, and an agenda with time stamps. You can use your own template or the" + " " + '\<a href="' + ESLP + '"\>ESAT Sub Lesson Plan</a>' + "<p>" +
"Thank you!";
Logger.log(msg);
GmailApp.sendEmail( y , "Staff absence/late request", msg,{
htmlBody: msg});
}
Thank you for any help!
I would like that to run on the cell that is filled. Either column f&k when a full day is taken or column I if late.
A nice extra would be after the email is sent the row is moved to the "approved" tab.

From:
const rData = e.source.getActiveSheet().getRange(e.range.rowStart,1,1,11).getValues();
To:
const rData = e.source.getActiveSheet().getRange(e.range.rowStart,1,1,11).getDisplayValues();
Then you may also use this code to move that row to "Approved" sheet:
var sourceSheet = e.source.getActiveSheet();;
var row = e.range.getRow();
var rowRange = sourceSheet.getRange(row, 1, 1, sourceSheet.getLastColumn());
var rowValues = rowRange.getDisplayValues()[0];
var targetSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Approved");
targetSheet.appendRow(rowValues);
sourceSheet.deleteRow(row);
Final code:
Try:
function sendEmailedit(e) {
if (e.range.columnStart != 12 || e.value != "TRUE") return;
const rData = e.source.getActiveSheet().getRange(e.range.rowStart, 1, 1, 11).getDisplayValues();
let y = rData[0][10];
let late = rData[0][8]
let beg = rData[0][5];
let end = rData[0][6];
let ESLP = "https://docs.google.com/document/"
let Subject = "Staff absence/time off request for";
let cc = "test1#email.com, test2#email.com, test3#email.com"
let msg = "Your staff absence/late request for" + " " + beg + "-" + end + " " + late + " " + "has been approved by Ms." + "<p>" +
"<b><u>All Staff:</b></u>" + "<br>" +
"Please add a banner reminder (all day) onto Google Calendar and include both test4#email.com and test5#email.com" + "<p>" +
"<b><u>Teachers:</b></u>" + "<br>" +
"Please email your lesson plans to test#email.com and test2#email.com by 8:00am the day you will be out" + "<p>" +
"<b><u>Sub plans must include:</b></u>" + "<br>" +
"classroom procedures, clear directions for the scholars/ substitute, and an agenda with time stamps. You can use your own template or the" + " " + 'ESAT Sub Lesson Plan' + "<p>" +
"Thank you!";
Logger.log(msg);
GmailApp.sendEmail(y, "Staff absence/late request", msg, {
htmlBody: msg
});
//Move this row
var sourceSheet = e.source.getActiveSheet();;
var row = e.range.getRow();
var rowRange = sourceSheet.getRange(row, 1, 1, sourceSheet.getLastColumn());
var rowValues = rowRange.getDisplayValues()[0];
var targetSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Approved");
targetSheet.appendRow(rowValues);
sourceSheet.deleteRow(row);
}
Reference:
Copy/Move row to another sheet

Related

Trying to adapt this code for automatically sending emails from Google sheets

I am trying to adapt the code from this video https://www.youtube.com/watch?v=WS3T2_qzJ8k
but I'm getting errors, can anyone spot the coding error? Thanks
I think there's confusion because in the video column E is referenced, I'm trying to reference column A - I'm not sure if some of the E letters in the original code are supposed to be changed or not
ORIGINAL CODE FROM VIDEO
function sendMailEdit(e){
if (e.range.columnStart != 5 || e.value != "Approved") return;
const rData = e.source.getActiveSheet().getRange(e.range.rowStart,1,1,4).getValues();
let n = rData[0][2];
let d = new Date(rData[0][0]).toLocaleDateString("en-US");
let items = rData[0][3];
let loc = rData[0][1];
let now = new Date().toLocaleString("en-US");
let msg = "Order number " + n + " (" + d + ") containing " + items + " items from " + loc + " Approved at " + now;
Logger.log(msg);
GmailApp.sendEmail("receipient_email_address", "Approved Order", msg)
}
MY MODIFIED CODE
function sendMailEdit(a){
if (a.range.columnStart != 1 || a.value >=2) return;
const rData = a.source.getActiveSheet().getSheetByName('SUBSCRIPTIONS').getRange(a.range.rowStart,1,1,14).getValues();
let mis = rData[0][1];
let dat = new Date(rData[0][2]).toLocaleDateString("en-US");
let cos = rData[0][3];
let aut = rData[0][4];
let typ = rData[0][5];
let des = rData[0][6];
let pro = rData[0][7];
let not = rData[0][8];
let cnu = rData[0][9];
let cna = rData[0][10];
let sta = rData[0][13];
let now = new Date().toLocaleString("en-US");
let msg = "AUTOMATED EMAIL FROM :: NP PROJECTS SHEET 2021 :: " + sta + " " + dat + " " + mis + " | " + cna + " " + cnu + " | " + typ + " " + des + " " + pro + " " + not + " | " + cos + " " + aut + " | Change triggered at:" + now;
Logger.log(msg);
GmailApp.sendEmail("my_email#gmail.com",sta + " " + cna, msg)
}
When making an edit in a spreadsheet, you can benefit from the existence of an event object.
In your case, a is the event object and it can return the following properties:
authMode;
oldValue;
range;
source
triggerUid;
user;
value.
However, if you take a closer look at the range property, you can see that it returns an object of type Range but the columnStart is not a method specific to the Range object.
If you want to retrieve the column at which the edit has been made, you should use the getColumn method.
Reference
Apps Script Event Objects;
Apps Script Range Class - getColumn().

Google Apps Script to send out different emails based on conditions, list of date's calendar events

With the script below, I am trying to send different emails based on different conditions. The form is working off of meeting requests. One of the emails including a body part with that days' calendar events listed.
It falls apart quite quickly: "TypeError: Cannot read property 'list' of undefined" in the var events = CalendarApp.Events.list(calId, { line.
I get why the error is there, because list is not defined. However, it's one of the sample codes from the Advanced Calendar Services, so I was under the impression that it would just work.
function draftSendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Form Responses 1");
var Avals = ss.getRange("A1:A").getValues(); //Status request (pending, etc).
var lastRow = Avals.filter(String).length;
Logger.log(lastRow);
for (var i = 2; i <= lastRow ; i++) {
var approvalStatus = sheet.getRange(i,1).getValue();
var name = sheet.getRange(i,8).getValue();
var description = sheet.getRange(i,9).getValue(); //Description.
var date = sheet.getRange(i,5).getValue(); //Date.
var formattedStart = Utilities.formatDate(new Date(date), 'Europe/London', 'Mmmm dd, yyyy');
var startTime = sheet.getRange(i,6).getValue(); //Event starting time.
var formattedSTime = Utilities.formatDate(new Date(startTime), 'Europe/London','hh:mm');
var endTime = sheet.getRange(i,7).getValue(); //Estimated end time of event.
var formattedETime = Utilities.formatDate(new Date(endTime), 'Europe/London','hh:mm');
var guests = sheet.getRange(i,15,1,10).getValues(); //Event guests by email address.
var staffMember = sheet.getRange(i,10).getValue(); //Meeting with whom, determines Calendar ID (CalId).
var staffEmail = sheet.getRange(i,13).getValue(); //Email address staff member.
var calId = sheet.getRange(i,11).getValue(); //Calendar the meeting goes into.
var booker = sheet.getRange (i,3).getValue(); //The person booking the meeting.
var booEmail = sheet.getRange(i,4).getValue(); //Email booker.
var eventStatus = sheet.getRange(1,1,i,12).getCell(i,12);
var bookNotifyBoo = sheet.getRange(i,14).getValue(); //Booker emailed with confirmation?
//List of calId's events on date.
var events = Calendar.Events.list(calId, {
timeMin: date,
singleEvents: true,
orderBy: 'startTime',
maxResults: 50
});
if (events.items && events.items.length > 0) {
for (var o = 0; o < events.items.length; o++) {
var event = events.items[o];
if (event.start.date) {
// All-day event.
var start = new Date(event.start.date);
Logger.log('%s (%s)', event.summary, start.toLocaleDateString());
} else {
var start = new Date(event.start.dateTime);
Logger.log('%s (%s)', event.summary, start.toLocaleString());
}
}
} else {
Logger.log('No events found.');
}
if (approvalStatus == "Approved" && bookNotifyVol.isBlank()){
MailApp.sendEmail(booEmail,
name + " meeting is booked for " + formattedStart + " " + formattedSTime + " - " + formattedETime,
"Hello " + booker + "," + "\n" + "\n" + "Your request for a " + name + " meeting has been approved by " + staffMember + ". Any other attendees will also be notified." + "\n" + "\n" + "The agenda for this meeting has been recorded as following:" + "\n" + description + "\n" + "\n" + "Wishing you a wonderful day." + "\n" + "\n" + "Kind regards," + "\n" + staffMember,{cc: guests});
sheet.getRange(bookNotifyBoo).setValue("Notified");
}
if (approvalStatus == "Pending" && eventStatus.isBlank()){
MailApp.sendEmail(staffEmail,
"Request for " + name + " meeting on " + formattedStart + " " + formattedSTime + " - " + formattedETime,
"Hello " + staffMember + "," + "\n" + "\n" + volunteer + " has requested a " + name + " meeting on: " + "\n" + formattedStart + ", starting at " + formattedSTime + " and estimated to end around " + formattedETime + "." + "\n" + "\n" + booker + "has given the following reason or agenda for this meeting:" + "\n" + description + "\n" + "\n" + "The following people are also invited to attend this meeting: " + guests + "." + "\n" + "\n" + "Here is a list of the events in the calendar for " + date + ":" + "\n" + start + "\n" + "\n" + "Wishing you a wonderful day.");
}
if (approvalStatus == "Not available" && eventStatus.isBlank()){
MailApp.sendEmail(booEmail,
"Conflict: " + name + " meeting on " + formattedStart + " " + formattedSTime + ", please try a different time",
"Hello " + booker + "," + "\n" + "\n" + "I am not available for a " + name + " meeting on " + formattedStart + " " + formattedSTime + " - " + formattedETime + ". Please try a different time and/or date.");
}
}
}
Any thoughts? Anything that you'd do differently?
You're missing a closing parenthesis right here: time and/or date.);

Filter an Email Report for Criteria

I'd like to receive a daily report of items that are not marked "Completed" in my spreadsheet. I have the code that will email the report, but I need to add a line or two of code that filters out anything that has a status that is not equal to Completed. Additionally, as this project grows, I would like to add functionality to filter based on multiple items (e.g. show only items not marked completed in Col D assigned for action to Greg in Col B).
The sheet is here: https://docs.google.com/spreadsheets/d/1jA4XQa7MgQI7OOLwCcmGv7BcUKSjdIPyh6B0CeQI-PI/edit#gid=0
My code as it stands now...
function emailStatusReport() {
// Set variables.
var x = 13;
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = ss.getSheetByName('data');
var template = HtmlService.createTemplateFromFile("report.html");
var message;
var subject;
var emailQuotaRemaining = MailApp.getRemainingDailyQuota();
var theRange = ss.getDataRange();
var completeMessage = "";
//Logger.log(theRang.getA1Notation());
var theManualRange = ss.getRange("A1:C7");
// var dateTimeStamp = now();
var vals = theManualRange.getValues();
for(i=0; i<vals.length; i++){
var itemNumber = vals[i][0];
var title = vals[i][1];
var description = vals[i][2];
// Logger.log(itemNumber + " " + title + " " + description + " ");
completeMessage = completeMessage + ("<BR>" + itemNumber + " " + title + " " + description + "</BR>");
}
Logger.log(completeMessage);
// Logger.log (x);
// Logger.log (ss);
// Logger.log (sheetName);
// Logger.log ("Remaining email quota: " + emailQuotaRemaining);
// Logger.log (vals[i][0]);
subject = "Daily Status Report TEST..."
message = "<HTML><BODY>" +
"<Font Face='verdana' color='green' size='2'>" +
"<P><P><B>Daily Status Report TEST</B>" +
"<P>Please review the report listed below. " +
// "<P>The value of x is " + x + "." +
"<P>" + completeMessage +
"<P><P>" +
"For the most up-to-date information, please visit: <BR>" +
"https://docs.google.com/spreadsheets/d/1jA4XQa7MgQI7OOLwCcmGv7BcUKSjdIPyh6B0CeQI-PI/edit#gid=0" +
"<P>" +
"<P><B>Make it an amazing day!</B>" +
// "<P>Report generated at: " + dateTimeStamp + ". " +
"<P>Remaining daily email quota: " + emailQuotaRemaining + ". " +
// "<P>This report runs between ___ AM and ___ AM." +
"</HTML></BODY>";
MailApp.sendEmail("greg#gregbartonmba.com", subject, "", {htmlBody: message});
// Logger.log("Subject is :" + subject);
// Logger.log("Message is: " + message);
}
For your question: To receive a daily report of items that are not marked "Completed"
First change the ManualRange to include status column:
var theManualRange = ss.getRange("A1:D7");
then change your for loop to:
for(i=0; i<vals.length; i++){
var itemNumber = vals[i][0];
var title = vals[i][1];
var description = vals[i][2];
var status = vals[i][3];
// Logger.log(itemNumber + " " + title + " " + description + " ");
if (status != 'Completed') {
completeMessage = completeMessage + ("<BR>" + itemNumber + " " + title + " " + description + "</BR>");
}
}

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);
};

App Scripts - Spreadsheet to Gmail "Invalid Email <>" Error

I'm a teacher and new to AppScript. I have created a spreadsheet to automatically send feedback to students via gmail from a google spreadsheet. It does work and the emails get sent from the spreadsheet but I get the following error 'Invalid Email <>' on the spreadsheet.
If anybody could help it'd be much appreciated.
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menu = [{
name: "Send Email",
functionName: "uiSendEmail"
}];
ss.addMenu("Send Email", menu);
}
function uiSendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var range = sheet.getDataRange();
range = range.offset(1, 0, range.getNumRows()-1);
range.getValues().forEach( function( recipient, index, data ){
var msgHtml = "Hi " + recipient[0] + "," + "<p>" + "Atttitude to Learning Grade is: " + "<b><u>" + recipient[5] + "</b></u>" + "<p>" + "Feedback: " + recipient[6] + "<p>" + "Improvements to be made: " + recipient[7] + "<p>" + "Overall Grade: " + recipient[8];
var subject = recipient[3] + " - Teacher Feedback";
var msgPlain = msgHtml.replace(/(<([^>]+)>)/ig, ""); // clear html tags for plain mail
GmailApp.sendEmail(recipient[0] + " " + recipient[1] + "<" + recipient[2] + ">", subject, msgPlain, { htmlBody: msgHtml });
});
}
This was from long ago, so I assume you figured something out... (I stumbled upon this trying to solve a related problem).
From your above code and the error, I can see the that the recipient array contains no data.