How do I call a mailApp function within an onEdit function? - google-apps-script

I have an onEdit function where if executed should send an email. However, some research has turned up that the mailApp functions don't work with onEdit. I'm currently toying around with workarounds but wondering if others have solutions they've come up with.
function onEdit(e) {
var sheet = e.source.getActiveSheet();
var sheetName = sheet.getName();
//if editing specific sheet
if (sheetName == "draft_test" ) {
//if editing 6th column
var r = e.source.getActiveRange();
if (r.getColumn() == 6 ) {
var player = sheet.getActiveCell().getValue();
// Display a dialog box with a message and "Yes" and "No" buttons.
var ui = SpreadsheetApp.getUi();
var response = ui.alert('Do you want to draft '+player+'?', ui.ButtonSet.YES_NO);
// Process the user's response.
if (response == ui.Button.YES) {
//***********FOR SOME REASON EXECUTING THIS FUNCTION ISNT WORKING******************
emailLeague();
//sortAutoRoster();
} else {
}
}
}
}
function emailLeague() {
var draftSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("draft_test");
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("test_email");
var emailSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Manager Info");
//actual email address omitted
var recipient = 'emailaddress#gmail.com';
//get array of all picks on "draft test" tab, and find latest one
var picks = draftSheet.getRange(3,6,146,1).getValues();
for (var i=0; i<picks.length; i++){
if (picks[i] == ""){
var latestPick = i;
break;
}
}
var subject = sheet.getRange(i+1, 2).getValue();
var body = sheet.getRange(i+1, 1).getValue();
MailApp.sendEmail(recipient, subject, body);
}

Related

Google App Script to trigger on cell value change with email notification

looking for a help to fix my script in Google spreadsheets.
I want to build a function that sends an email every time a certain cell in the list is updated.
Here is my code, but it doesn't work.
Looking for your help to find and fix my issue
function onEdit(e) {
const specificSheet = "Inventory"
const specificCell = "B1"
let sheetCheck = (e.range.getSheet().getName() == specificSheet)
let cellCheck = (e.range.getA1Notation() == specificCell)
if (!(sheetCheck && cellCheck)) {
return
}
else {
sendEmail(){
var subject = "New update";
var emailAddress = "example#gmail.com";
var message = "new update: link";
MailApp.sendEmail(emailAddress, subject, message)
}
}
}
Send email on an Edit
function onMyEdit(e) {
const sh = e.range.getSheet();
if (sh.getName() = "Inventory" && e.range.columnStart == 2 && e.range.rowStart == 1) {
var subject = "New update";
var emailAddress = "example#gmail.com";
var message = "new update: link";
MailApp.sendEmail(emailAddress, subject, message)
}
}
I think this needs to be an installable trigger in order to send an email.
Sometimes Sheet can not process complex operations related to onEdit(e), so maybe this could help:
function onEdit(e) {
const specificSheet = "Inventory";
const specificCell = "B1";
var range = e.range;
var ss = e.source;
var sheetName = ss.getActiveSheet().getName();
var a1Notation = range.getA1Notation();
if ((sheetName==specificSheet) && (a1Notation==specificCell)) {
var props = PropertiesService.getScriptProperties();
props.setProperty("CHECKED","TRUE");
}
}
function sendEmail(){
var subject = "New update";
var emailAddress = "example#gmail.com";
var message = "new update: link";
var props = PropertiesService.getScriptProperties();
var checked = props.getProperty("CHECKED");
if (checked == "TRUE"){
GmailApp.sendEmail(emailAddress, subject, message);
Utilities.sleep(3000);
props.setProperty("CHECKED","FALSE");
}
}
Another thing you should do is setting sendEmail() function is activated by time trigger every minute or so...

Searching a sheet for value stored in a cell fails

I'm an extreme novice in programming and am trying to work an assignment that keeps failing. My code searches a sheet(tab1) in Google sheets for a value that is in a cell in another sheet(tab2). For some reason, the search never finds the value. For simplicity I tested by changing the value that I'm looking for to a whole number, not a ".GetValue". I then had an if statement that would alert with message "Found" and "Not Found" if it wasnt found. The data is never found.
function editRecord(){
var myGoogleSheet=SpreadsheetApp.getActiveSpreadsheet();
var shUserForm=myGoogleSheet.getSheetByName("Form");
var datasheet=myGoogleSheet.getSheetByName("Records");
var ui=SpreadsheetApp.getUi();
var response=ui.alert("Submit", 'Do you want to submit your data?', ui.ButtonSet.YES_NO);
var str=shUserForm.getRange("F7").getValue();
var values=datasheet.getDataRange().getValues();
var valuesFound=false;
if(response==ui.Button.NO){
return;
}
for (var i=0;i<values.length;i++){
if (values[i][1]==str){
var iRow=i+1;
datasheet.getDataRange(iRow,5).setValue(shUserForm.getDataRange("F15").getValue());
datasheet.getDataRange(iRow,6).setValue(shUserForm.getDataRange("F17").getValue());
datasheet.getDataRange(iRow,7).setValue(shUserForm.getDataRange("F19").getValue());
ui.alert("Data updated.");
shUserForm.getDataRange("F15").clearContent;
shUserForm.getDataRange("F17").clearContent;
shUserForm.getDataRange("F19").clearContent;
shUserForm.getDataRange("F21").clearContent;
shUserForm.getDataRange("F23").clearContent;
shUserForm.getDataRange("F25").clearContent;
valuesFound=true;
return;
}
if (valuesFound==false){
ui.alert("Your ID was not found.");
return;
}
}
}
Modification points:
I think that in your script, by return of if (valuesFound==false){}, when values[i][1]==str is false, the for loop is finished. By this, for example, when values[i][1]==str is false at the 1st row of values, the for loop is finished. I thought that this might be the reason of your issue.
About getDataRange(iRow, 5) of datasheet.getDataRange(iRow, 5), unfortunately, getDataRange has no arguments. I think that an error also occurs at this part.
About clearContent of shUserForm.getDataRange("F15").clearContent, in this case, the method of clearContent is not run.
If you want to search the value, how about the following modification?
Modified script 1:
When your script is modified, it becomes as follows.
function editRecord() {
var myGoogleSheet = SpreadsheetApp.getActiveSpreadsheet();
var shUserForm = myGoogleSheet.getSheetByName("Form");
var datasheet = myGoogleSheet.getSheetByName("Records");
var ui = SpreadsheetApp.getUi();
var response = ui.alert("Submit", 'Do you want to submit your data?', ui.ButtonSet.YES_NO);
var str = shUserForm.getRange("F7").getValue();
var values = datasheet.getDataRange().getValues();
var valuesFound = false;
if (response == ui.Button.NO) {
return;
}
for (var i = 0; i < values.length; i++) {
if (values[i][1] == str) {
var iRow = i + 1;
datasheet.getRange(iRow, 5).setValue(shUserForm.getRange("F15").getValue());
datasheet.getRange(iRow, 6).setValue(shUserForm.getRange("F17").getValue());
datasheet.getRange(iRow, 7).setValue(shUserForm.getRange("F19").getValue());
ui.alert("Data updated.");
shUserForm.getRange("F15").clearContent();
shUserForm.getRange("F17").clearContent();
shUserForm.getRange("F19").clearContent();
shUserForm.getRange("F21").clearContent();
shUserForm.getRange("F23").clearContent();
shUserForm.getRange("F25").clearContent();
valuesFound = true;
return;
}
}
if (valuesFound == false) {
ui.alert("Your ID was not found.");
return;
}
}
Modified script 2:
I thought that in your script, getValue and setValue are used in the loop. In this case, the process cost will become high. So, as another modified script, how about the following modification?
unction editRecord() {
var myGoogleSheet = SpreadsheetApp.getActiveSpreadsheet();
var shUserForm = myGoogleSheet.getSheetByName("Form");
var datasheet = myGoogleSheet.getSheetByName("Records");
var ui = SpreadsheetApp.getUi();
var response = ui.alert("Submit", 'Do you want to submit your data?', ui.ButtonSet.YES_NO);
var str = shUserForm.getRange("F7").getValue();
if (response == ui.Button.NO) {
return;
}
var res = datasheet.getRange("B1:B" + datasheet.getLastRow()).createTextFinder(str).matchEntireCell(true).findNext();
if (!res) {
ui.alert("Your ID was not found.");
return;
}
var [[v1],,[v2],,[v3]] = shUserForm.getRange("F15:F19").getValues();
datasheet.getRange(res.getRow(), 5, 1, 3).setValues([[v1, v2, v3]]);
shUserForm.getRangeList(["F15","F17","F19","F21","F23","F25"]).clearContent();
SpreadsheetApp.flush();
ui.alert("Data updated.");
}
In this sample, the value is searched using TextFinder. And, the cells are cleared using the RangeList.
References:
getRange(row, column)
clearContent()
createTextFinder(findText)

Checkbox to approve entry on Google sheets and trigger an approval email

Currently im having a prompt window popup that collects the S. No of the entry and then approves that entry and sends out an approval email. Instead of this, i wanna have a check box that one checks to approve the entry and a function is triggered
function function1() {
var sheet= SpreadsheetApp.openById("xxxx").getSheetByName("payments");
var ui = SpreadsheetApp.getUi();
var result = ui.prompt('Please enter the S. No of the entry you want to approve', ui.ButtonSet.OK_CANCEL);
var button = result.getSelectedButton();
var sno = result.getResponseText();
for (var i=1; i<=100 ; i++)
{
Logger.log(sheet.getRange(i,1).getValue());
if(sno == sheet.getRange(i,1).getValue())
{
var index = i;
}
}
Logger.log(index);
var invitem = sheet.getRange(index,5).getValue();
var invdesc = sheet.getRange(index,6).getValue();
var reqby = sheet.getRange(index,3).getValue();
var amount = sheet.getRange(index,8).getValue();
if (button == ui.Button.OK)
{
var subject = 'Payment release request approved';
var body = '<p>Hello</p> <p>This particular payment release is approved from my end</p> <p>Invoice Item: '+ invitem +'</p> <p>Description: '+ invdesc +'</p> <p>Requested By: '+reqby+' </p> <p>Requested By: '+amount+' </p> <p> </p> <p><em>This is an automated email triggerred post approval</em></p>'
var email= 'finance#xxxx.xxx';
GmailApp.sendEmail(email, subject, "Requires HTML", {
htmlBody: body})
sheet.getRange(index,16).setValue("Approved").setBackground('#008000');
}
}
Okay here's a function and an installable trigger create function
function onMyEdit(e) {
const sh = e.range.getSheet();
if(sh.getName() == 'Your sheet name' && e.range.columnStart == '15' && e.value == "TRUE") {
let snum = sh.getRange(e.range.rowStart,1).getValue();
ApproveAndSendEmail({snum:snum});
}
}
function createTrigger() {
const ss = SpreadsheetApp.getActive();
if(ScriptApp.getProjectTriggers().filter(t => t.getHandlerFunction() == "onMyEdit").length == 0) {
ScriptApp.newTrigger('onMyEdit').forSpreadsheet(ss).onEdit().create();
}
}

Problem with the order of IF statements Google Script

I am struggling to set up my IF statements properly, basically I want to check if there is data in column J, if empty continue on with the rest of the script, if there is data ask if the user wants to continue, and then either continue or terminate depending on their response.
Here is the start of my code:
function exportSg() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Subgrade'); //source sheet
var testrange = sheet.getRange('J18:J'); //range to check
var testvalue = (testrange.getValues());
var ui = SpreadsheetApp.getUi();
for (i=0; i<testvalue.length;i++) {
if ( testvalue[i] != "") {
var response = ui.alert("Gaps greater than 50 meters identified in report, unhide column J to identify. \n\n Do you want to cancel the export?",ui.ButtonSet.YES_NO);
Logger.log(response);
if (response == ui.Button.YES) {
SpreadsheetApp.getActive().toast("Export Cancelled...")}else {
SpreadsheetApp.getActive().toast("Exporting Subgrade Report...");
The problem seems to be when there is no data in column J it does not continue with the export.
Anyone fancy shedding some light??
As mentioned in a previous answer to you, you can use a break to stop a loop.
In your case, that means to have a break when the user clicks the YES button:
if (response == ui.Button.YES) {
SpreadsheetApp.getActive().toast("Export Cancelled...");
break;
}
If you want to export even if there is no data to be used by the for statement, you need to move the export part to outside of it:
function exportSg() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Subgrade'); //source sheet
var testrange = sheet.getRange('J18:J'); //range to check
var testvalue = (testrange.getValues());
var ui = SpreadsheetApp.getUi();
var shouldExport = true;
for (i=0; i<testvalue.length;i++) {
if ( testvalue[i] != "") {
var response = ui.alert("Gaps greater than 50 meters identified in report, unhide column J to identify. \n\n Do you want to cancel the export?",ui.ButtonSet.YES_NO);
Logger.log(response);
if (response == ui.Button.YES) {
SpreadsheetApp.getActive().toast("Export Cancelled...");
shouldExport = false;
break;
}
}
}
if (shouldExport) {
myExportFunction();
}
}

Send automated email for specific value of a drop down column

I have tried many different codes to send an email alert when column F in my Google sheet has the value "Yes". I am selecting this value from a drop down. But no emails are sent. I have tried different emails also. Nothing works. This is the code I am trying right now.
function Email(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var s = ss.getSheetByName("FY");
var row = s.getActiveRange().getRow();
var status = s.getRange(row,6).getValue();
var subject = 'subject'; var message = 'body';
var email ="";
if (e.value === "Yes" && e.range.getColumn() === 6) {
GmailApp.sendEmail(email,subject,message);
}
};
You need to use an installed trigger see here to use this on edit script.
Go to 'Edit' -> 'Current project's triggers' and set a trigger as shown below.
Code:
function onEdit(e){
var getRange = e.range;
var getValue = getRange.getValue();
var getCol = getRange.getColumn();
if(getValue == "Yes" && getCol == 6){
var subject = 'subject';
var message = 'body';
var email = "---------------";
MailApp.sendEmail(email, subject, message);
}
}