Excluding Sheet with OnEdit - google-apps-script

I'm looking to run an automated email script, but exclude two specific tabs, named "Data" and "Carpet". I wrote this to test on just the "Data" tab, but couldn't get it to work.
I have excluded the sheet url and email address for purpose of posting.
Edit - rest of the code works fine, just want to prevent it from running on the specified tabs above
`
function autoemail(e) {
let sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
let range = e.range;
let row = e.range.getRow();
let col = e.range.getColumn();
let cellValue = sheet.getActiveCell().getValue();
let address = sheet.getRange(row,1).getValue();
let ordernumber = sheet.getRange(row,2).getValue();
let installdate = sheet.getRange(row,3).getValue();
let jobtype = sheet.getRange(row,4).getValue();
let fieldsuper = sheet.getRange(row,5).getValue();
let notes = sheet.getRange(row,11).getValue();
let holdstatus = sheet.getRange(row,12).getValue();
let user = Session.getActiveUser().getEmail();
let cellLocation = sheet.getActiveCell().getA1Notation();
let url = "MyURL"
if(col == 11 && sheet != "Data") {
MailApp.sendEmail(
'MyEmail',
address + ' has been updated🔥',
'This an automated notice that ' + fieldsuper + ' has updated ' + address + ' (' + ordernumber + ') with the notes ' + notes + ', the current status is ' + holdstatus + ' for the install date of ' + installdate + '. For more information, please check the carpet sheet directly at ' + url
);
};
}
`

Try it this way:
function autoemail(e) {
const sh = e.range.getSheet();
const excl = ["Sheet1", "Sheet2"];
const idx = excl.indexOf(sh.getName());
if (!~idx && e.range.columnStart == 11) {
const [address, ordernumber, installdate, jobtype, fieldsuper, , , , , , notes, holdstatus] = sh.getRange(e.range.rowStart, 1, 1, 12).getValues();
let user = Session.getActiveUser().getEmail();
let cellLocation = e.range.getA1Notation();
let url = "MyURL"
MailApp.sendEmail('MyEmail', address + ' has been updated🔥','This an automated notice that ' + fieldsuper + ' has updated ' + address + ' (' + ordernumber + ') with the notes ' + notes + ', the current status is ' + holdstatus + ' for the install date of ' + installdate + '. For more information, please check the carpet sheet directly at ' + url
);
};
}

Related

Google sheets edit trigger email sheet range

can anyone help me get sheet by name before the if conditional? I'm trying to limit the range to column C on a specific sheet and right now it gets triggered by all sheets.
function sendMailEdit(e){
if (e.range.columnStart!= 3 || e.value != "REMOVAL") return;
const rData = e.source.getActiveSheet().getRange(e.range.rowStart,1,1,14).getValues();
let n = rData[0][3];
let f = rData[0][1];
let d = rData[0][13];
let items = rData[0][2];
let now = new Date().toLocaleString("en-US");
let msg = "This is an auto generated message to inform you that the removal date of " + f + " for project " + n + " (" + d + ") has been added to the Logistics Schedule at " + now;
Logger.log(msg);
GmailApp.sendEmail("x#x.com", "Project Removal Scheduled", msg)
}
I tried adding getSheetByName on line 3 and the trigger still worked with all other sheets but with no data. Also on line 2 I added e.source.set or get SheetByName etc no success.
function sendMailEdit(e){
const sh = e.range.getSheet();
if (sh.getName() != "Your sheet name" && e.range.columnStart!= 3 || e.value != "REMOVAL") return;
const rData = e.source.getActiveSheet().getRange(e.range.rowStart,1,1,14).getValues();
let n = rData[0][3];
let f = rData[0][1];
let d = rData[0][13];
let items = rData[0][2];
let now = new Date().toLocaleString("en-US");
let msg = "This is an auto generated message to inform you that the removal date of " + f + " for project " + n + " (" + d + ") has been added to the Logistics Schedule at " + now;
Logger.log(msg);
GmailApp.sendEmail("x#x.com", "Project Removal Scheduled", msg)
}

Is there a way to send multiple emails to multiple users from google sheets while looping through a list of messages?

Hey this is my first question on StackOverflow.
I've been struggling with this code for two days and tried to move the loops up and down but nothing happened. The code doesn't show any error but i don't get a mail.
What I'm trying to do is to send multiple messages (sheet: buysignals) to multiple users (sheet: Sheet1). It should appear that everyone gets each email as the only receiver. f.ex. you get a new mail if there is a text in the Buysignals sheet.
Anyone here who can help me how to fix it?
function sendBuySignal() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Buysignals");
const dataRange = sheet.getRange("A2:R17");
const data = dataRange.getValues();
data.forEach(function (rowData) {
const ticker = rowData[0];
// Stock info
const kurtosis = rowData[1];
const sigma = rowData[2];
const mCap = rowData[17];
const std = rowData[4];
const timeStamp = rowData[6];
const buyPrice = rowData[8];
const buyIndicator = rowData[16];
// Send Signal Mail
if (buyIndicator > 0) {
const greeting = 'The stock ' + ticker + ',\n'
const buyMessage = 'Is at ' + timeStamp + ' in the buy zone at ' + buyPrice + '. With a kurtosis of ' + kurtosis + ', sigma ' + sigma + ', mcap in bill ' + mCap + '.';
const greatJobMessage = 'Hurry up! Go buy it :)';
const message = [greeting, buyMessage, greatJobMessage].join('\n');
const subject = 'Test: New Buy ' + ticker;
// Fetch the email address
const emailRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
const n=emailRange.getLastRow();
for (var i = 2; i > n+1 ; i++ ) {
const emailAddress = emailRange.getRange(i,1).getValue();
}
MailApp.sendEmail(emailAddress, subject, message);
}
return
})
}
The issue is related to looping
The syntax for (var i = 2; i > n+1 ; i++ ) { cannot work
Assuming that the last row is bigger than the start row (that is bigger than 2) the condition i > n+1 will never be fulfilled, so you will not enter the loop - instead you should specify i < n
It is n and not n+1 because you start with the second row instead of the first (i = 2)
MailApp.sendEmail(emailAddress, subject, message); is located outside of the for loop
This means that in each loop the function overwrites the emailAddress and after exiting the loop you will send a single email - to the last saved email address
This issue can be solved by inserting MailApp.sendEmail(emailAddress, subject, message); inside the for loop
Sample:
function sendBuySignal() {
const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Buysignals");
const dataRange = sheet.getRange("A2:R17");
const data = dataRange.getValues();
var sheet1 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var n = sheet1.getLastRow();
const emails = sheet1.getRange("A2:A" + n).getValues();
data.forEach(function (rowData) {
const ticker = rowData[0];
// Stock info
const kurtosis = rowData[1];
const sigma = rowData[2];
const mCap = rowData[17];
const std = rowData[4];
const timeStamp = rowData[6];
const buyPrice = rowData[8];
const buyIndicator = rowData[16];
// Send Signal Mail
if (buyIndicator > 0) {
Logger.log("buyIndicator > 0");
const greeting = 'The stock ' + ticker + ',\n'
const buyMessage = 'Is at ' + timeStamp + ' in the buy zone at ' + buyPrice + '. With a kurtosis of ' + kurtosis + ', sigma ' + sigma + ', mcap in bill ' + mCap + '.';
const greatJobMessage = 'Hurry up! Go buy it :)';
const message = [greeting, buyMessage, greatJobMessage].join('\n');
const subject = 'Test: New Buy ' + ticker;
// Fetch the email address
for (var i = 0; i < emails.length ; i++ ) {
var emailAddress = emails[i][0];
Logger.log("email: " + emailAddress);
MailApp.sendEmail(emailAddress, subject, message);
}
}
})
}
Note that for this sample I allowed myself to retrieve all emails before entering the loop. This is more efficient than multiple calls of getRange() within each loop iteration.

How to stop program from executing if date is not today's date in Google Apps Script

what I am trying to do is to check to see if the date in column RTC is 90 days past the date in column "Initial Date Seen by Dr." I have already done that using Sheet's formulas. Works perfectly. But then I want to compare this date in column L to see if today date (The computer's date) matches this date in column L. If so, I want to send an email.
So far everything works. But here's one little problem. As you can see in the image below, the first record shows that the date in column RTC is 7/21/20 which doesn't match today's date 5/26/20 but I still receive email for this record saying follow up with the patient.
Is there any fix for this?
function ifItsBeen90Days()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
sheet = ss.getSheetByName("PAOS");
range = sheet.getDataRange();
values = range.getValues();
var lR = sheet.getLastRow();
var dateinfo = sheet.getRange('L3:L').offset(0, 0, lR, 1).getValues();
var today = new Date();
var y0 = today.getFullYear();
var m0 = today.getMonth() + 1;
var d0 = today.getDate();
for (var i=0; i<dateinfo.length; i++){
x = Date.parse(dateinfo[i]);
var date = new Date(x);
var y = date.getFullYear();
var m = date.getMonth() + 1;
var d = date.getDate();
if (y0 === y && m0 === m && d0 === d) {
SendItIf90daysPast();
} else {
Logger.log("error:" + i) // difference date
};
};
}
function SendItIf90daysPast(){
const ss = SpreadsheetApp.getActiveSheet();
const dataRange = ss.getDataRange();
const headers = 2;
const dataValues=ss.getRange(3,1,ss.getLastRow()-2,ss.getLastColumn()).getValues();
dataValues.forEach(function(row){
if(row[11] !== "") {
let message = " It's been 90 days since your last visit with the following Patient. " + '\n' +
" Can you please do a follow visit with this Patient? " + '\n' + '\n' +
" Thank you for your time and effort. " + '\n' +
" _______________________________________________________________ " + '\n' +
" Patient#: " + row[0] + '\n' +
" Patient Name: " + row[1] + '\n' +
" P-Code: " + row[2] + '\n' +
" PAO/INF: " + row[3] + '\n' +
" Score 1: " + row[4] + '\n' +
" Score 1 Date: " + new Date(row[5]).toLocaleDateString("en-US") + '\n' +
" Score 2: " + row[6] + '\n' +
" Score 2 Date: " + new Date(row[7]).toLocaleDateString("en-US") + '\n' +
" Tx Plan Entry Date: " + new Date(row[8]).toLocaleDateString("en-US") + '\n' +
" First Date: " + new Date(row[9]).toLocaleDateString("en-US") + '\n' +
" Initial Date Seen by DR: " + new Date(row[10]).toLocaleDateString("en-US") + '\n' +
" RTC: " + new Date(row[11]).toLocaleDateString("en-US") + '\n' +
" Notes: " + row[13];
let email = row[12];
let subject = 'Encrypt: Please Follow Up With Patient:' + " " + row[1] + " Patient #: " + row[0];
MailApp.sendEmail(email, subject, message);
Logger.log(`${subject}: ${message} sent to ${email}`);
}
});
}
If you want to check if a date is the same in one column as it is in another, or even if a particular date is 90 days after / before another date, I recommend creating additional columns (which can be hidden) for this purpose. Why? Well, once you grab the date, you (can) actually get the day before, see here for more infos which is an annoying issue.
So your for loop would then create the condition like this:
// lets assume column 15 contains your date check logic
function ifItsBeen90Days(){
const rows = SpreadsheetApp.getActive().getSheetByName("PAOS").getDataRange().getValues();
rows.forEach( (row, index) => {
const doesConditionApply = row[16]; // 15th col, is 16th index
// skip if the value is not what you are looking for
if( doesConditionApply != true ){
return
}
SendItIf90daysPast()
});
}
function ifItsBeen90Days() {
const ss=SpreadsheetApp.getActive();
const shsr=3;
const sh=ss.getSheetByName("PAOS");
const rg=sh.getDataRange();
const v=sh.getRange(shsr,11,sh.getlastr()-shsr+1,1).getValues();
const dt=new Date();
const today=new Date(dt.getFullYear(),dt.getMonth(),dt.getDate());
const t90v=new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()-90).getTime();
const t91v=new Date(dt.getFullYear(),dt.getMonth(),dt.getDate()-91).getTime();
const tv=today.getTime();
v.forEach(function(r,i){
var d=new Date(r[0]);
var dv=new Date(d.getFullYear(),d.getMonth(),d.getDate()).valueOf();
var diff=dv-tv;
if(diff>=t90v && diff<t91v){
//it has been 90 days
}
});
}

Google Apps Script - How do i get my AdminDirectory.Users.List query to be accepted?

I'm using GAS to create a contact lookup, where the function parameters build a query that is used in AdminDirectory.Users.List . This problem only happens when the orgTitle and orgDepartment parameters are used. When I copy and paste the Logger output in place of the q variable, the query works. If I used the q variable, it fails.
function listAllUsersBase(name = null, familyName = null, givenName = null, orgTitle = 'Help Desk', orgDepartment = null) {
var aQuery = 'query:\''
if (name !== null){
Logger.log('Name: ' + name);
var aQuery = aQuery + 'name:' + name + ' ';
} if (familyName !== null){
Logger.log('familyName: ' + familyName);
var aQuery = aQuery + 'familyName:' + familyName + ' ';
} if (givenName !== null){
Logger.log('givenName: ' + givenName);
var aQuery = aQuery + 'givenName:' + givenName + ' ';
} if (orgTitle !== null){
Logger.log('orgTitle: ' + orgTitle);
var aQuery = aQuery + 'orgTitle:\\\'' + orgTitle + '\\\' ';
} if (orgDepartment !== null){
Logger.log('orgDepartment: ' + orgDepartment)
var aQuery = aQuery + 'orgDepartment:\\\'' + orgDepartment + '\\\' ';
}
var aQuery = aQuery + '\''
var q = aQuery.toString();
Logger.log(q);
var pageToken;
var page;
do {
page = AdminDirectory.Users.list({
domain: 'yourdomain.com',
query: q,
orderBy: 'givenName',
maxResults: 100,
pageToken: pageToken
});
var users = page.users;
if (users) {
for (var i = 0; i < users.length; i++) {
var user = users[i];
Logger.log('%s (%s)', user.name.fullName, user.primaryEmail);
}
} else {
Logger.log('No users found.');
}
pageToken = page.nextPageToken;
} while (pageToken);
}
There are a number of issues with your script.
First, you do not need to re-declare the aQuery variable. The first declaration of var aQuery = ... is sufficient for your use-case.
Second, query is not a valid field for a search clause so it is not necessary (see documentation with list of valid fields available to search clauses). To clarify, when you first declare your aQuery variable you initialized it as var aQuery = 'query:\'';. Here, query is being used as a field in a search clause. However, it is not a valid option in this context.
Third, the position of the opening single-quotes on the field values for orgTitle and orgDepartment are incorrect, the opening escaped single-quote should precede the escaped backslash.
So, instead of:
var aQuery = aQuery + 'orgTitle:\\\'' + orgTitle + '\\\' ';
you should have:
var aQuery = aQuery + 'orgTitle:\'\\' + orgTitle + '\\\' ';

It is about sending an email based on the changes in the sheet

I want my function to activate on specific sheet only. But I really do not know how to write. I have like 14 sheets. And anytime one of the sheets' values are changed. It automatically sends out an email which I do not want. I want my function to send email only based on the sheet I want. (I have add the trigger manually on my current project trigger).
function CheckbudgetAUD() {
for(var i=2;i<1000; i++){
var num1 = i;
var r = 4;
var department = "AUD";
var transactionIDRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(department).getRange(num1,14);
var transactionID = transactionIDRange.getValue();
var monthRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(department).getRange(num1,12);
var month = monthRange.getValue() ;
var costdescriptionRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(department).getRange(num1,3);
var costdescription = costdescriptionRange.getValue();
var costRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(department).getRange(num1,4);
var cost = costRange.getValue();
var actualbudgetRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(department).getRange(num1,4);
var actualbudget = actualbudgetRange.getValue();
var ApprovalRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(department).getRange(num1,18);
var Approval = ApprovalRange.getValue();
var purposeRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(department).getRange(num1,7);
var purpose = purposeRange.getValue();
var timeRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(department).getRange(num1,1);
var time = timeRange.getValue();
var CEOsapprovalRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(department).getRange(num1,19);
var CEOsapproval = CEOsapprovalRange.getValue();
var addinformationRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(department).getRange(num1,5);
var addi = addinformationRange.getValue();
var thisisdoneRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(department).getRange(num1,30);
var thisisdone = thisisdoneRange.getValue();
var BlankRange = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(department).getRange(num1,2);
var Blank = BlankRange.getValue();
//Emails Range
var email1Range = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Forecasted budget").getRange("F18");
var email1address = email1Range.getValue();
var email2Range = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Forecasted budget").getRange("F21");
var email2address = email2Range.getValue();
var email3Range = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(department).getRange(num1,6);
var email3address = email3Range.getValue();
// Messages Range
var message1 = "Your request has been " + Approval + "d." + "\n" + "\n" + "Transaction ID: " + transactionID;
var message = "For the " + month + ", " + department + "'s " + costdescription + ' budget exceeded the limit'+ '\n'+ '\n'+ "CURRENT BUDGET APPLICATION INFORMATION" + "\n" + "COST: "+ cost + '\n' + "Transaction ID: "+ transactionID +'\n' + "Cost item: " + costdescription + "\n" + "Purpose: "+ purpose + "\n" + "Department Name: " + department + "\n" + "Timestamp: " + time + "\n" + "additional information: " + addi+ "\n" + 'Click the link below to approve'+ '\n' + 'https://docs.google.com/forms/d/e/1FAIpQLSduX3ol31Ddy3klEpynlO33wprEivAr-e9BL7fZ6Th-JQgjZA/viewform';
var subject = 'Exceeded the budget limit for current month';
var subject1 = 'Form Approval/Decline';
if ( Blank !== "" && thisisdone == "Apple"){
MailApp.sendEmail(email3address, subject1, message1);
}
//Over budget email
if ( Approval == "Decline" && thisisdone == "Apple"){
if ( cost < 200000 ) {
MailApp.sendEmail(email1address, subject, message);}
else if ( cost >= 200000 ) {
MailApp.sendEmail(email2address, subject, message);
}
}
}
}
I am also basically sending out email to 3 different parties at the same time in one function. Just FYI.
You might like to consider this sort of approach. You will find it to run much faster. Although there may be some corrections you will want to make. I noticed some duplication in the range assignments which are reflected in my assignments as well. Keep in mind that column number start at one and array indices start at zero.
function CheckbudgetAUD() {
var department = "AUD";
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName(department)
var fsh=ss.getSheetByName("Forcasted budget");
var vA=sh.getRange(2,1,sh.getLastRow()-1,sh.getLastColumn()).getValues();
for(var i=0;i<vA.length; i++){
var transactionID = vA[i][13];
var month = vA[i][11];
var costdescription = vA[i][2];
var cost = vA[i][3];
var actualbudget=vA[i][3];
var Approval=vA[i][17];
var purpose=vA[i][6];
var time=vA[i][0];
var CEOsapproval=vA[i][18];
var addi=vA[i][4];
var thisisdone=vA[i][29];
var Blank=vA[i][1];
var email1address = fsh.getRange("F18").getValue();
var email2address = fsh.getRange("F21").getValue();
var email3address = vA[i][5];
var message1 = "Your request has been " + Approval + "d." + "\n" + "\n" + "Transaction ID: " + transactionID;
var message = "For the " + month + ", " + department + "'s " + costdescription + ' budget exceeded the limit'+ '\n'+ '\n'+ "CURRENT BUDGET APPLICATION INFORMATION" + "\n" + "COST: "+ cost + '\n' + "Transaction ID: "+ transactionID +'\n' + "Cost item: " + costdescription + "\n" + "Purpose: "+ purpose + "\n" + "Department Name: " + department + "\n" + "Timestamp: " + time + "\n" + "additional information: " + addi+ "\n" + 'Click the link below to approve'+ '\n' + 'https://docs.google.com/forms/d/e/1FAIpQLSduX3ol31Ddy3klEpynlO33wprEivAr-e9BL7fZ6Th-JQgjZA/viewform';
var subject = 'Exceeded the budget limit for current month';
var subject1 = 'Form Approval/Decline';
if (Blank!=="" && thisisdone=="Apple"){
MailApp.sendEmail(email3address, subject1, message1);
}
if (Approval=="Decline" && thisisdone=="Apple"){
if (cost<200000) {
MailApp.sendEmail(email1address, subject, message);
}else if( cost >= 200000 ) {
MailApp.sendEmail(email2address, subject, message);
}
}
}
}
If you're attempting to run something like this from onEdit() then you will want to limit which sheets that you want it to run on. For example consider the event object to be represented by an e then
function onEdit(e) {
var sh=e.range.getSheet();
if(sh.getName()!='AUD')return;
This will limit the script to running only for sheet AUD.