I am trying to send auto generated mail based on text value of Google sheet.
In My Sheet column, F is the row with the status " Approved' Or "Rejected"
If Status is " Approved' mail should generate
I have created the code, however, i think need small modifications
function myNotification() {
var ss = SpreadsheetApp.getActiveSpreadsheet()
var ss_sheet = ss.getSheetByName('Form Responses 1')
var ss_sheet_datarange = ss.getDataRange().getValues();
var ss_sheet_lastrow = ss_sheet.getLastRow()
for (var i = 5; i < ss_sheet_lastrow; i++)
var approvalstatus = ss_sheet_datarange[5][i] // column F is the row with the status in
var approval_status = 5;
if (approval_status == 'Approved') {
var email = Session.getUser().getEmail();
MailApp.sendEmail(email, "Test", "Test");
}
Change
if (approval_status == 'Approved') {
For
if (approvalstatus == 'Approved') {
You have two variables very similar, but in your code, approval_status will ALWAYS be 5
Related
I'm trying to get the data from an original sheet named "Interface Boletagem" that is column C rows 6 to 28 and paste this data in a new sheet named "Boletador (Dados)" on the last blank row and in different columns. Basically transposing all the data from the original sheet.
I managed to make it work, but the current script is taking a long time to complete... Any tips on how to optimize it?
function submitDataInbound(){
//declare a variable and set the reference of active google sheet
var myGoogleSheet=SpreadsheetApp.getActiveSpreadsheet();
var shUserForm=myGoogleSheet.getSheetByName("Interface Boletagem");
var datasheet=myGoogleSheet.getSheetByName("Boletador (Dados)");
//code to update the data on database sheet
var ui=SpreadsheetApp.getUi();
var columnToCheck = datasheet.getRange("A:A").getValues();
function getLastRowSpecial(range){
var rowNum = 0;
var blank = false;
for(var row = 0; row < range.length; row++)
if(range[row][0] === "" && !blank){
rowNum = row;
blank = true;
}else if(range[row][0] !== ""){
blank = false;
};
return rowNum;
};
var blankRow=getLastRowSpecial(columnToCheck) + 1;
datasheet.getRange(blankRow,1).setValue(shUserForm.getRange("C26").getValue());//ID
datasheet.getRange(blankRow,2).setValue(shUserForm.getRange("C27").getValue());//DF
datasheet.getRange(blankRow,3).setValue(shUserForm.getRange("C11").getValue());//VMN
datasheet.getRange(blankRow,4).setValue(shUserForm.getRange("C12").getValue());//VME
datasheet.getRange(blankRow,5).setValue(shUserForm.getRange("C21").getValue());//Dea
datasheet.getRange(blankRow,6).setValue(shUserForm.getRange("C22").getValue());//PS
datasheet.getRange(blankRow,7).setValue(shUserForm.getRange("C23").getValue());//LSBD
datasheet.getRange(blankRow,8).setValue(shUserForm.getRange("C24").getValue());//SS
datasheet.getRange(blankRow,9).setValue(shUserForm.getRange("C20").getValue());//TID
datasheet.getRange(blankRow,10).setValue(shUserForm.getRange("C6").getValue());//Cli
datasheet.getRange(blankRow,11).setValue(shUserForm.getRange("C28").getValue());//CV
datasheet.getRange(blankRow,12).setValue(shUserForm.getRange("C7").getValue());//Moe
datasheet.getRange(blankRow,13).setValue(shUserForm.getRange("C16").getValue());//TFX
datasheet.getRange(blankRow,14).setValue(shUserForm.getRange("C8").getValue());//QtME
datasheet.getRange(blankRow,15).setValue(shUserForm.getRange("C9").getValue());//TxBco
datasheet.getRange(blankRow,16).setValue(shUserForm.getRange("C10").getValue());//TxCli
datasheet.getRange(blankRow,17).setValue(shUserForm.getRange("C14").getValue());//IOF
datasheet.getRange(blankRow,18).setValue(shUserForm.getRange("C13").getValue());//Tar
datasheet.getRange(blankRow,19).setValue(shUserForm.getRange("C17").getValue());//BPar
datasheet.getRange(blankRow,20).setValue(shUserForm.getRange("C19").getValue());//Nat
datasheet.getRange(blankRow,21).setValue(shUserForm.getRange("C18").getValue());//CBPar
datasheet.getRange(blankRow,22).setValue(shUserForm.getRange("C15").getValue());//IR
ui.alert('Boletado')
shUserForm.getRange("C6").clear();
shUserForm.getRange("C7").clear();
shUserForm.getRange("C8").clear();
shUserForm.getRange("C9").clear();
shUserForm.getRange("C10").clear();
shUserForm.getRange("C11").clear();
shUserForm.getRange("C12").clear();
shUserForm.getRange("C13").clear();
shUserForm.getRange("C14").clear();
shUserForm.getRange("C15").clear();
shUserForm.getRange("C16").clear();
shUserForm.getRange("C17").clear();
shUserForm.getRange("C18").clear();
shUserForm.getRange("C19").clear();
shUserForm.getRange("C6").setBackground('#BEBEBE');
shUserForm.getRange("C7").setBackground('#BEBEBE');
shUserForm.getRange("C8").setBackground('#BEBEBE');
shUserForm.getRange("C9").setBackground('#BEBEBE');
shUserForm.getRange("C10").setBackground('#BEBEBE');
shUserForm.getRange("C11").setBackground('#BEBEBE');
shUserForm.getRange("C12").setBackground('#BEBEBE');
shUserForm.getRange("C13").setBackground('#BEBEBE');
shUserForm.getRange("C14").setBackground('#BEBEBE');
shUserForm.getRange("C15").setBackground('#BEBEBE');
shUserForm.getRange("C16").setBackground('#BEBEBE');
shUserForm.getRange("C17").setBackground('#BEBEBE');
shUserForm.getRange("C18").setBackground('#BEBEBE');
shUserForm.getRange("C19").setBackground('#BEBEBE');
}
I believe your goal is as follows.
You want to reduce the process cost of your script.
In this case, how about the following modification? In order to retrieve the values from the scattered cells, I used Sheets API. And, in order to clear and set background to the cells "C6", "C7", "C8", "C9", "C10", "C11", "C12", "C13", "C14", "C15", "C16", "C17", "C18", "C19", shUserForm.getRange(6, 3, 14).clear().setBackground('#BEBEBE') is used.
Modified script:
Before you use this script, please enable Sheets API at Advanced Google services.
function submitDataInbound() {
var myGoogleSheet = SpreadsheetApp.getActiveSpreadsheet();
var shUserForm = myGoogleSheet.getSheetByName("Interface Boletagem");
var datasheet = myGoogleSheet.getSheetByName("Boletador (Dados)");
var ui = SpreadsheetApp.getUi();
var columnToCheck = datasheet.getRange("A:A").getValues();
function getLastRowSpecial(range) {
var rowNum = 0;
var blank = false;
for (var row = 0; row < range.length; row++)
if (range[row][0] === "" && !blank) {
rowNum = row;
blank = true;
} else if (range[row][0] !== "") {
blank = false;
};
return rowNum;
};
var blankRow = getLastRowSpecial(columnToCheck) + 1;
var ranges1 = ["C26", "C27", "C11", "C12", "C21", "C22", "C23", "C24", "C20", "C6", "C28", "C7", "C16", "C8", "C9", "C10", "C14", "C13", "C17", "C19", "C18", "C15"];
var values = Sheets.Spreadsheets.Values.batchGet(myGoogleSheet.getId(), { ranges: ranges1.map(e => `'Interface Boletagem'!${e}`) }).valueRanges.map(({ values }) => values[0][0]);
datasheet.getRange(blankRow, 1, 1, values.length).setValues([values]);
ui.alert('Boletado');
shUserForm.getRange(6, 3, 14).clear().setBackground('#BEBEBE');
}
Reference:
Method: spreadsheets.values.batchGet
I'm trying to build a script that can automatically send email when a new row is updated. I only want to trigger the new updated rows and mark 'sent' after sending them out.
Here's the script that's currently working well. I can run it with a click:
function sendMail()
{
var name = 0;
var request = 1;
var id = 2;
var select = 3;
var time = 4;
var email = 5;
var status = 6;
var error = 7;
var emailTemp = HtmlService.createTemplateFromFile("email");
var ws = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Email list");
var data = ws.getRange("A2:I" + ws.getLastRow()).getValues();
data = data.filter(function(r){ return r[8] == true });
data.forEach(function(row)
{
emailTemp.fn = row[name];
emailTemp.req = row[request];
emailTemp.id = row[id];
emailTemp.erm = row[error];
emailTemp.ta = row[select];
emailTemp.time = row[time];
var htmlMessage = emailTemp.evaluate().getContent();
GmailApp.sendEmail(row[email],
"Failure message",
"Please submit again.",
{name: "My name", htmlBody: htmlMessage}
);
});
}
I have studied this query but I still have no idea how it works.
Please share some relevant source or some solution, thank you!
Although I'm not sure about mark 'sent' after sending them out., if "sent" is put to the column "J", from I assume it's filled in another column, like col8 or col 9. of your reply, I guessed that you wanted to put "sent" to the column "J" because the columns 8 and 9 (H and I) have already been used in your script. If my understanding is correct, how about the following modification?
Modified script:
Please copy and paste the following script to the script editor of Google Spreadsheet and save the script. And please install OnEdit trigger to the function sendMail. By this, when the cell is edited, the script is run.
function sendMail() {
var ws = SpreadsheetApp.getActiveSheet();
if (ws.getSheetName() != "Email list") return;
var name = 0;
var request = 1;
var id = 2;
var select = 3;
var time = 4;
var email = 5;
var status = 6;
var error = 7;
var emailTemp = {};
var emailTemp = HtmlService.createTemplateFromFile("email");
var data = ws.getRange("A2:J" + ws.getLastRow()).getValues();
var ranges = data.map(function (row, i) {
if (row[8] == true && row[9] != "sent") {
emailTemp.fn = row[name];
emailTemp.req = row[request];
emailTemp.id = row[id];
emailTemp.erm = row[error];
emailTemp.ta = row[select];
emailTemp.time = row[time];
var htmlMessage = emailTemp.evaluate().getContent();
GmailApp.sendEmail(row[email],
"Failure message",
"Please submit again.",
{ name: "My name", htmlBody: htmlMessage }
);
return "J" + (i + 2);
}
return "";
}).filter(String);
ws.getRangeList(ranges).setValue("sent");
}
In this case, when the active sheet is "Email list", the script is run. And, "sent" is put to the column "J".
Note:
I think that the event object of OnEdit can be used. But from your question, I thought that you might want to directly run the script with the script editor. So I didn't use the event object.
It seems that the columns 8 and 9 (H and I ) are used in your script like emailTemp.erm = row[error]; and data = data.filter(function(r){ return r[8] == true });. So I put "sent" to the column "J". Please be careful this.
Here is an example of the sheet I am trying to make this work for: https://docs.google.com/spreadsheets/d/1M79ki9QVRkfkwy1uWyNAVddeyPpcvqDppi3Et-b-cLw/edit?usp=sharing
The goal is that an email is sent when column I is greater than 2 and column K is null. Column I is a count formula based on columns C-H, which are manually filled in.
Here is the script I have, but it doesn't seem to be working:
function sendEmail() {
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheetByName("Workable");
var listing_id = sheet.getRange("B:B").getValues();
var flag_count = sheet.getRange("I:I").getValues();
var action_type = sheet.getRange("K:K").getValues();
var subject = 'New Listing Flagged';
var message = 'Listing' + listing_id + 'has been flagged. Please resolve ASAP in the QA Google Sheet. Thank you!';
var email_address = 'allyson#hipcamp.com';
if (flag_count > 2 && action_type == ""){MailApp.sendEmail(email_address, subject, message)}
}
What do I need to change to make it work?
I got your latest code in the sample sheet. Since you've decided to use onEdit trigger, you need to use the installable onEdit trigger because you are using MailApp.sendEmail() service which requires authorization.
Pre-requisite (installable trigger):
Sample Code:
function sendNotification1(e) {
Logger.log(JSON.stringify(e));
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var row = e.range.getRow();
var col = e.range.getColumn();
var startRow = 2;
var startCol = 3; //Column C
var endCol = 8; //Column H
if(sheet.getName() == "Workable"
&& col >= startCol
&& col <= endCol
&& row >= startRow
&& sheet.getRange(row,9).getValue() > 2 //flag_count column > 2
&& sheet.getRange(row,11).getValue() == "" //action column null
)
{
var campground_id = sheet.getRange(row,2).getValue();
var email = 'your#email.com';
var subject = "New Listing Flagged for Fraud";
var body = 'Campground ' + campground_id + ' has been flagged for fraud. Please resolve ASAP in the QA Google Sheet. Thank you!';
MailApp.sendEmail(email, subject, body);
}
}
What it does?
Your column I value depends on the value provided in column C-H. Hence your trigger should be the change in values done in column C-H (column index 3-8). I include an additional condition to check the current active sheet to verify that the modified cells are in sheet Workable. Check the value in column I if greater than 2. Lastly, check if column K is null/empty
Send the email
Output:
(Update)
Checkbox column included that will act as a checker button to trigger the email notification.
Sample Code:
function sendNotification(e) {
Logger.log(JSON.stringify(e));
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var row = e.range.getRow();
var col = e.range.getColumn();
var startRow = 2;
if(sheet.getName() == "Workable"
&& col == 9
&& row >= startRow
&& sheet.getRange(row,9).isChecked()
&& sheet.getRange(row,10).getValue() > 2 //flag_count column > 2
&& sheet.getRange(row,12).getValue() == "" //action column null
)
{
var campground_id = sheet.getRange(row,2).getValue();
var email = 'your#email.com';
var subject = "New Listing Flagged for Fraud";
var body = 'Campground ' + campground_id + ' has been flagged for fraud. Please resolve ASAP in the QA Google Sheet. Thank you!';
MailApp.sendEmail(email, subject, body);
}
}
Sample Sheet:
I don't work with Google Sheets very often and mainly deal with Google Form's script editor. We have created a database from various forms that fill into one spreadsheet and I would like to send email notifications to specific managers based on the recent row update, which would update from a form submission. Here is what I was trying to get it to do:
if cell in Column P matches to "FALSE":
send email
set the recipient field as "director1#gmail.com" if cell in Column J matches to the word "Building 1"
set the CC field as "manager1#gmail.com" if the cell in Column I matches to the word "Department 1"
if Column P matches to "TRUE", then it doesn't have to do anything
function triggerOnEdit(e)
{
alertManagers(e);
}
function checkClearance(e)
{
var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
var sheet = spreadsheet.getSheetByName("Calculations");
var value = sheet.getRange("P:P").getValue();
var range = sheet.getRange(1, 1, sheet.getLastRow(), 1); //understands spreadsheet
if(range.getColumn() <= 16 &&
range.getLastColumn() >=16 )
{
var edited_row = range.getRow();
var approval = SpreadsheetApp.getActiveSheet().getRange(edited_row,16).getValue();
if(approval == 'FALSE')
{
return edited_row;
}
}
return 0;
}
function alertManagers(e)
{
var clearance_row = checkClearance(e);
if(clearance_row <= 0)
{
return;
}
sendEmailByRow(clearance_row);
}
function sendEmailByRow(row)
{
var values = SpreadsheetApp.getActiveSheet().getRange(row,1,row,16).getValues();
var row_values = values[0];
var mail = composeAlertEmail(row_values);
var manageremail='test#gmail.com';
//Uncomment this line for testing
//SpreadsheetApp.getUi().alert(" subject is "+mail.subject+"\n message "+mail.message);
MailApp.sendEmail(manageremail,mail.subject,mail.message);
}
function composeAlertEmail(row_values)
{
var name = row_values[6];
var email = "test#gmail.com";
var message = "Good day, \n The following employee does not have clearance to enter the building: "+name+
" email "+email;
var subject = "Employee Not Cleared: "+name+" "
return({message:message,subject:subject});
}
Does this seem possible? I know I am probably far off from a solution, but thanks if anyone can help in advance!
Solution:
Here is what you are looking for:
function triggerOnEdit(e) {
sendEmails(e)
}
function sendEmails(e){
const row = e.range.getRow();
const col = e.range.getColumn();
const as = e.source.getActiveSheet();
const subject = "This is the subject of the email";
const body = "This is the body of the email";
const to = "director1#gmail.com";
const cc = "manager1#gmail.com";
if(as.getName() == "Calculations" && col == 16 && as.getRange(row,col).getDisplayValue() == "FALSE") {
if (as.getRange(row,10).getValue()=="Building 1"){
if(as.getRange(row,9).getValue()=="Department 1"){
MailApp.sendEmail({to:to ,subject: subject,body:body,cc:cc});
}
else {
MailApp.sendEmail({to: to,subject: subject,body:body});
}
}
}
}
I assume that if column J does not match Building 1 which means there is no recipient, the email won't be sent.
Don't forget to add triggerOnEdit(e) to the current project's trigger:
My spreadsheet is composed of a main sheet that is populated using a form plus several other sheets for the people who work with the responses submitted through the form. A script delegates the form responses to these other sheets depending on the type of item described in the response.
The problem is, when Person A deletes an item from their respective sheet, it doesn't delete in the main sheet.
My idea is that when you type a set password into the corresponding cell in row 'Q' in Person A's sheet, it matches the item by timestamp to the original form submission and deletes both the version of the item in Person A's sheet as well as the main sheet. However, I can't figure out what to set the range to to get it to point to the row in the array. Everything I have tried has sent back "undefined" in the debugger and won't delete anything. I think the problem is that I don't know how to get the row from the array that I have made. See my code below:
function onEdit() {//copies edited items from individual selector sheets back onto main spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
var actSheet = ss.getActiveSheet();
var responseSheet = ss.getSheetByName("Item Request");
var actCell = actSheet.getActiveCell();
var actRow = actCell.getRow();
var actVal = actCell.getValue();
var actLoc = actCell.getA1Notation();
var last = actSheet.getLastRow();
var respLast = responseSheet.getLastRow();
var dataA = responseSheet.getRange(1, 1, respLast, 1).getValues(); //compiles an array of data found in column A through last row in response sheet
var tstamp1 = actSheet.getRange(actCell.getRow(), 1);
var tsVal1 = tstamp1.getValue();
var colEdit = actCell.getColumn();
//===========THIS IS WHERE I'M STUCK=======================
if ((actVal == "p#ssword") && (colEdit == 17)) {
for (i = 1; i < dataA.length; i++) {
if (dataA[i][0].toString == tsVal1.toString()) {
responseSheet.deleteRow(i + 1);
actSheet.deleteRow(actRow);
break;
}
}
}
else if (colEdit == 15) { //checks the array to see if the edit was made to the "O" column
for (i = 1; i < dataA.length; i++) {//checking for timestamp match and copies entry
if (dataA[i][0].toString() == tsVal1.toString()) {
var toEdit = responseSheet.getRange(i + 1, 16);
toEdit.setValue(actVal);
}
}
}
else if (colEdit == 16) { // checks the array to see if the edit was made in the "P" column
for (i = 1; i < dataA.length; i++) {//checking for timestamp match and copies entry
if (dataA[i][0].toString() == tsVal1.toString()) {
var toEdit = responseSheet.getRange(i + 1, 17);
toEdit.setValue(actVal);
}
}
}
else {return;}
}//end onEdit
I don't believe these are proper commands delRow.deleteRow();actCell.deleteRow(); Take a look at the documentation;
Okay I rewrote that function for you a bit but I'm stilling wondering about a couple of lines.
function onEdit(e)
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var actSheet = ss.getActiveSheet();
var responseSheet = ss.getSheetByName("Item Request");
var actCell = actSheet.getActiveCell();
var actRow = actCell.getRow();
var actVal = actCell.getValue();
var colEdit = actCell.getColumn();
var respLast = responseSheet.getLastRow();
var dataA = responseSheet.getRange(1, 1, respLast, 1).getValues();
var tstamp1 = actSheet.getRange(actRow, 1);
var tsVal1 = tstamp1.getValue();
for(var i=0;i<dataA.length;i++)
{
if(new Date(dataA[i][0]).valueOf()==new Date(tsVal1).valueOf())
{
if (actVal=="p#ssword" && colEdit==17)
{
responseSheet.deleteRow(i + 1);
actSheet.deleteRow(actRow);
}
else if(colEdit==15)
{
var toEdit = responseSheet.getRange(i + 1, 16);//?
toEdit.setValue(actVal);//?
}
else if (colEdit == 16)
{
var toEdit = responseSheet.getRange(i + 1, 17);//?
toEdit.setValue(actVal);//?
}
}
}
}
Can you explain the function of the lines with question marked comments?