Cannot call DriveApp from Google sheet via onEdit() trigger [duplicate] - google-apps-script

really feel like I'm missing something with the Spreadsheet object scripts.
I'm trying to automatically email collaborators onEdit. I successfully emailed when explicitly runnign the script in test, but the onEdit event never seems to get fired (not seeing log messages even). Script seems pretty straightforward.
function onEdit(e) {
var sheet = e.source;
var viewers = sheet.getViewers();
var ct = viewers.length;
var recipients = [];
for(var i=0;i<ct;i++){
recipients.push(viewers[i].getEmail());
};
var subject = 'Update to '+sheet.getName();
var body = sheet.getName() + ' has been updated. Visit ' + sheet.getUrl() + ' to view the changes ' + e.range;
Logger.log('Running onedit');
MailApp.sendEmail(recipients, subject, body);
};

the simple onEdit function has a very limited set of possible actions since it runs without the authorization of the potential user. You have to create another function and set a specific trigger on this function.(installable trigger)
See this post as an example. It shows examples of simple onEdit and installable edit (for email send)
This is explained in the documentation here.
EDIT : here is your code working :
function sendAlert() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = ss.getActiveCell().getA1Notation()
var viewers = ss.getViewers();
var ct = viewers.length;
var recipients = [];
for(var i=0;i<ct;i++){
recipients.push(viewers[i].getEmail());
};
var subject = 'Update to '+sheet.getName();
var body = sheet.getName() + ' has been updated. Visit ' + ss.getUrl() + ' to view the changes on cell ' + cell;
MailApp.sendEmail(recipients, subject, body);
};

Related

How to have simple google apps script send mails from Sheets from owner account regardless of who's accessing file

I've clicked around for the past few days trying to find an answer but can't seem to find one that makes sense to me (forgive me, I'm fairly new to GAS). I am trying to set up a Fantasy Golf Draft sheet to be used by about 12 users, but over half of which don't have/aren't willing to use a Gmail address. Getting access to the file is no problem, where I am running into an issue is trying to run a script, where when a Button/Shape is clicked, it sends an automated email to the next person who's turn it is to pick. The functionality of the script is working, when it comes from myself or someone with a Google account who can authorize the script etc. I run into troubles when it's someone without a Google account.
My question - how can I set the script to ONLY send from my email, or the Sheet/Script Owner's email - regardless of who is modifying/clicking the button? I see links about creating the script as a webapp to do this, but I get lost quickly.
Here's a link to my sheet:
[https://docs.google.com/spreadsheets/d/16AppcmrcuhatnzcEs7eIQyD_p1swbRimRZZ4FdbhBKI/edit?usp=sharing][1]
And here is my send mail code:
function sendAlertEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("Send Mails"));
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange("A2:f2");
var data = dataRange.getValues();
for (i in data) {
var rowData = data[i];
var emailAddress = rowData[1];
var recipient = rowData[0];
var message1 = rowData[2];
var message2 = rowData[3];
var message3 = rowData[4];
var message4 = rowData[5];
var message = 'Hey ' + recipient + ',\n\n' + message1 + '\n\n' + ' The last player picked was ' + message2 + '\n\n' + message3 +'\n\n' + message4;
var subject = '*GOLF DRAFT 2018* - YOU ARE ON THE CLOCK';
MailApp.sendEmail(emailAddress, subject, message);
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("DRAFT"));
}
}
Any help would be greatly appreciated!
I felt interested in this issue and worked a bit more on it. I changed from it being a get request to being a post request.
Here is what I have in the Google sheet.
function sendAlertEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("Send Mails"));
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange("A2:f2");
var data = dataRange.getValues();
for (i in data) {
var rowData = data[i];
var emailAddress = rowData[1];
var recipient = rowData[0];
var message1 = rowData[2];
var message2 = rowData[3];
var message3 = rowData[4];
var message4 = rowData[5];
var message = 'Hey ' + recipient + ',\n\n' + message1 + '\n\n' + ' The last player picked was ' + message2 + '\n\n' + message3 +'\n\n' + message4;
var subject = '*GOLF DRAFT 2018* - YOU ARE ON THE CLOCK';
var data = {
'name': 'Bob Smith',
'email': 'a#b.com',
'message': message,
'subject': subject,
};
var options = {
'method' : 'post',
'contentType': 'application/json',
'payload' : data
};
var secondScriptID = 'STANDALONE_SCRIPT_ID'
var response = UrlFetchApp.fetch("https://script.google.com/macros/s/" + secondScriptID + "/exec", options);
Logger.log(response) // Expected to see sent data sent back
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("DRAFT"));
// Browser.msgbox("Your Pick Has Been Made");
}
}
Below is what I have in the standalone script. There are some provisos on the standalone script working:
It needs to be published under "Deploy as a webapp"
Access should be set to 'Anyone, even anonymous'
Every time you make a change to the standalone script publish again and
change the Project version to new. This is so the call from the first sheet calls to the latest code.
Standalone Script
function convertURItoObject(url){
url = url.replace(/\+/g,' ')
url = decodeURIComponent(url)
var parts = url.split("&");
var paramsObj = {};
parts.forEach(function(item){
var keyAndValue = item.split("=");
paramsObj[keyAndValue[0]] = keyAndValue[1]
})
return paramsObj; // here's your object
}
function doPost(e) {
var data = e.postData.contents;
data = convertURItoObject(data)
var recipient = data.email;
var body = data.message;
var subject = data.subject;
try {
MailApp.sendEmail(recipient, subject, body)
}
catch(e){
Logger.log(e)
}
return ContentService.createTextOutput(JSON.stringify(e));
}
No, you can't do that, because a script can be shared with a multiple users and it is always executed from their own account not from the script owners account and script uses the 'from email address' of the executing user, it is not allowed by Google to send email from another users account as a security policy.
You could use a second script that belongs to you. From your first script send a fetch request to the second script, the second script can send an email from your account to anyone. The second script would look like this:
function doGet(e) {
var recipient = e.parameter.email;
var body = e.parmeter.message
var subject = "My golf thing"
try {
MailApp.sendEmail(recipient, subject, body)
}
catch(e){
Logger.log(e)
}
}
The first script would need a fetch request something like this.
var response = UrlFetchApp.fetch("https://script.google.com/macros/s/SECOND_SCRIPT_ID/exec?email=b#b.com&message=somthing");
return response;

Need to sendNotification for multiple columns and sheets

In an attempt to automate some of my work, I am beginning to learn basics of google scripts.
I have a spreadsheet in which I want to send an email notification when data is input into one column or another. There are also two tabs within this spreadsheet in which I would like this to occur.
The current result from the script is an email on the second 'sendnotification' function.
Question: How do I get the script to consider both functions?
I know this code can be condensed by likely using an IF fucntion in a better way but I am at a loss.
For some context: This is used in a manufacturing operation. The production is done by an offsite company and when they enter quantity into column 10 on either sheet, I want it to send a group of people an email that I work with. Similarly, when the product quality testing is done I want to be able to input into Column 12 and it send the offsite company an email.
function sendNotification() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Get Active cell
var mycell = ss.getActiveSelection();
var cellcol = mycell.getColumn();
var cellrow = mycell.getRow();
//Define Notification Details
var recipients = "ryan.helms#company.com";
var subject = "Disc production was entered on the "+ss.getName();
var body = ss.getName() + " has been updated with an amount produced. Visit " + ss.getUrl() + " to view the quantities entered.";
//Check to see if column is A or B to trigger
if (cellcol == 10)
{
//Send the Email
MailApp.sendEmail(recipients, subject, body);
}
//End sendNotification
}
function sendNotification() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
//Get Active cell
var mycell = ss.getActiveSelection();
var cellcol = mycell.getColumn();
var cellrow = mycell.getRow();
//Define Notification Details
var recipients = "ryan.helms#company.com";
var subject = "A lot of disc has been RELEASED by XYZ Company";
var body = ss.getName() + " has been updated with a lot of disc that were released by XYZ Company. Visit " + ss.getUrl() + " to view this updated information.";
//Check to see if column is A or B to trigger
if (cellcol == 12)
{
//Send the Email
MailApp.sendEmail(recipients, subject, body);
}
//End sendNotification
}
You'll need to set up an onEdit installable trigger (if you haven't already) and assign it to the following function:
function onEditEmailSender(e) {
var sheetName = e.range.getSheet().getName();
if (sheetName === "tab1" || sheetName === "tab2") {
var col = e.range.getColumn();
if (col === 10)
//send col 10 email
else if (col === 12)
//send col 12 email
}
}
The onEdit trigger passes a parameter with all sorts of information, the most useful in your case being e.range. This Range object corresponds to the cell that was edited to trigger the onEdit event. You can use it to get the name of the sheet (what you call tab) and the column that was edited.
Using that information you can send the appropriate email. Good luck!

Script sendNotification doens't work correctly

I'm trying to make a script to send an email every day , after checking in a spreadsheet, two conditions. If the first condition for True , the data to e- mail will be " subject1 ", otherwise, will be " subject2 ".
The script works correctly when I run manually , however, through the trigger, the value I would like to send via email, simply does not appear in the body.
I can not understand what could be wrong if manually , works perfectly .
The trigger is "time-driven/hour time/every 12 hours".
Can anyone help me?
This is the code:
function sendNotificationD() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = ss.getActiveCell().getA1Notation();
var cellvalue = ss.getActiveCell().getValue().toString();
var column = ss.getRange('o13');
var cell = sheet.getRange('o13');
var value = column.getValue();
var emailSheet = ss.getSheetByName("totais");
var emails = emailSheet.getRange("q1:s1").getValues();
var range_bill_com = sheet.getRange('o13');
if (range_bill_com.getValue() !='CONGRATS'){
var recipients = emails;
var message = '';
var subject = 'subject1 here';
var body = 'IMPORTANT: ' + '\n\n' + 'your goal is' + ' ' + value;
MailApp.sendEmail(recipients, subject, body);
}
if (range_bill_com.getValue() =='CONGRATS'){
var recipients = emails;
var message = '';
var subject = 'subject2 here';
var body = 'you have reached your goal';
MailApp.sendEmail(recipients, subject, body);
}
};
At this line:
var sheet = ss.getActiveSheet();
The method getActiveSheet() gets the the active sheet that is being displayed in the spreadsheet UI when a user opens it, but when it runs from a time-driven trigger there is no active sheet, so you need to indicate the sheet, you can use getSheetByName() or getSheets() the line should look like this:
var sheet = ss.getSheetByName("Sheet1");
or
var sheet = ss.getSheets()[0]; // Index of the tab, 0 will return the first one
The function will still work if you fire it manually or from a trigger.

Sending an email whenever a cell is changed in a Google spreadsheet

I am trying to set up a script for a google spreadsheet that will email a specific person whenever a cell in Column M is modified to 'y'. I found this script,
email notification if cell is changed
and I am trying to modify it to suit my needs, but I am having an issue getting it to work. This is my script as it stands now.
function onEdit(e){
Logger.log(e)
var ss = SpreadsheetApp.getActiveSpreadsheet();
Logger.log(ss)
var sheet = ss.getActiveSheet();
Logger.log(sheet)
var cell = ss.getActiveCell().getA1Notation();
Logger.log(cell)
var row = sheet.getActiveRange().getRow();
Logger.log(row)
var column = sheet.getActiveRange().getColumn();
Logger.log(column)
var cellvalue = ss.getActiveCell().getValue().toString();
Logger.log(cellvalue)
var recipients = "08cylinders#gmail.com"; //email address will go here
var message = '';
if(cell.indexOf('M')!=-1){
message = sheet.getRange('M'+ sheet.getActiveCell().getRowIndex()).getValue()
}
Logger.log(message)
Logger.log(cell)
var subject = 'Update to '+sheet.getName();
var body = sheet.getName() + ' has been updated. Visit ' + ss.getUrl() + to view the changes on row: ' + row; //New comment: «' + cellvalue + '». For message: «' + message + '»';
MailApp.sendEmail(recipients, subject, body);
}
If anybody has an idea of what I'm missing, I would greatly appreciate any help.
Thank you,
Victor
i think this may solve your event problem:
function onEdit(e) {
var ssActive = e.source;
var ssActiveRange = ssActive.getActiveRange();
var ssActiveRangeVal = ssActiveRange.getValue();
var ActiveRow = ssActiveRange.getRow(); // if needed to put on body's message
var ActiveColumn = ssActiveRange.getColumn();
if((ssActiveRangeVal=='y' || ssActiveRangeVal=='Y') && ActiveColumn==13){ // ActiveColumn==13 for M
// write down your mail code here
}
}
You cannot send an email from the onEdit trigger. What you need to do is save the edits as a Document Property and then setup a 1-minute time based trigger that sends the content of the property in an email and flushes the queue.

Google App script onEdit?

really feel like I'm missing something with the Spreadsheet object scripts.
I'm trying to automatically email collaborators onEdit. I successfully emailed when explicitly runnign the script in test, but the onEdit event never seems to get fired (not seeing log messages even). Script seems pretty straightforward.
function onEdit(e) {
var sheet = e.source;
var viewers = sheet.getViewers();
var ct = viewers.length;
var recipients = [];
for(var i=0;i<ct;i++){
recipients.push(viewers[i].getEmail());
};
var subject = 'Update to '+sheet.getName();
var body = sheet.getName() + ' has been updated. Visit ' + sheet.getUrl() + ' to view the changes ' + e.range;
Logger.log('Running onedit');
MailApp.sendEmail(recipients, subject, body);
};
the simple onEdit function has a very limited set of possible actions since it runs without the authorization of the potential user. You have to create another function and set a specific trigger on this function.(installable trigger)
See this post as an example. It shows examples of simple onEdit and installable edit (for email send)
This is explained in the documentation here.
EDIT : here is your code working :
function sendAlert() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var cell = ss.getActiveCell().getA1Notation()
var viewers = ss.getViewers();
var ct = viewers.length;
var recipients = [];
for(var i=0;i<ct;i++){
recipients.push(viewers[i].getEmail());
};
var subject = 'Update to '+sheet.getName();
var body = sheet.getName() + ' has been updated. Visit ' + ss.getUrl() + ' to view the changes on cell ' + cell;
MailApp.sendEmail(recipients, subject, body);
};