How do I find a cell value based on if statements? - google-apps-script

I am building a badge sending program using Google sheets and everything is going great so far. There is a control page that once marked yes and the script runs, sends an email to the email listed and inserts information from that page, including the recipients name. I want to be able to find the name of the person I'm sending a badge email to, use that name to activate a sheet, and then date stamp a certain cell on that sheet. I'm having trouble finding the name value.
The email and date stamp is working on the control page, but I'm having trouble figuring out the logic to determine the name value to open each person's individual page. The Logger just shows all the names in the range and I only want the names to show that are receiving emails/badges.
function sendEmails3() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Badge Issuing Central")
var startRow = 2; // First row of data to process
// Fetch the range of cells
var dataRange = sheet.getRange(startRow, 1, sheet.getLastRow()-1, 7);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
data.forEach(function(row,i) {
var name = row[0]; // First column
var badge = row[1]; // Second column
var recomendations = row[2]//third column
var awarded = row [3] // fourth column
var email = row [4] // fifth column
var dateEmailed = row [5] // 6th column
var emailSent = row[6]; // Seventh column
if (emailSent != EMAIL_SENT && awarded == 'Yes') { // Prevents sending duplicates
var body = 'Hi ' + name + '<br><br>' +
'Congratulations! You have recieved a badge!<br><br>' +
'Your teammates think you are doing great lately.<br><br>' +
'You were nominated at least twice by those around you, and you are being awarded:<br><br>' +
"<em>" + badge + '<br><br>' +
"Make sure you check out your Badge Pathway to see how you're doing!<br><br>" +
'Thanks, <br>' +
"Jordan, Mark, and Jarrod";
var subject = 'Congratulations! You have earned a badge!';
GmailApp.sendEmail(email, subject, "", { htmlBody: body } );
sheet.getRange(startRow + i, 7).setValue(EMAIL_SENT);
sheet.getRange(startRow + i, 6).setValue(d);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
if (emailSent != EMAIL_SENT && awarded == 'Yes') {
var nameTab = sheet.getRange(2,1,sheet.getLastRow()-1,1).getValues();
Logger.log(nameTab);}
});}

Try this:
function sendEmails3() {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName("Badge Issuing Central")
var data=sh.getRange(2, 1, sh.getLastRow()-1, 7).getValues();
for(var i=0;i<data.length;i++) {
var name=data[i][0]; // First column
var badge=data[i][1]; // Second column
var recomendations=data[i][2]//third column
var awarded=data[i][3] // fourth column
var email=data[i][4] // fifth column
var dateEmailed=data[i][5] // 6th column
var emailSent = data[i][6]; // Seventh column
if(emailSent != "EMAIL_SENT" && awarded=='Yes') {
var body=Utilities.formatString('Hi %s <br><br>Congratulations! You have recieved a badge!<br><br>Your teammates think you are doing great lately.<br><br>You were nominated at least twice by those around you, and you are being awarded:<br><br><em> %s<br><br>Make sure you check out your Badge Pathway to see how you\'re doing!<br><br>Thanks, <br>Jordan, Mark, and Jarrod', name,badge);
var subject = 'Congratulations! You have earned a badge!';
GmailApp.sendEmail(email, subject, "", { htmlBody: body } );
sh.getRange(i + 2, 7).setValue("EMAIL_SENT");
sh.getRange(i + 2, 6).setValue(Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MMddyyyy HH:mm:ss"));
}
}
}

Related

How to send email IF Cell Value Contains Certain Text?

I am having problems with a script that I wrote. It isn't throwing any errors however I am not receiving the emails. The goal of this script is to send an email if column G has value Y.
Column A = Organization Name
Column C= Days Aging
Column F= Email (where the email should be sent)
Column G= Status (where the Y will be)
function CheckPastDueAccounting() {
//Fetch Accounting Spreadsheet with past due accounts
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var lrow= ss.getLastRow();
for(var i=2;i<=lrow;i++);
var Status =ss.getRange(i,7);
var value = Status.getValue();
if (value == 'Y') {
var DaysAgingColumn = ss.getRange(i,3);
var DaysAging = DaysAgingColumn.getValue();
// Fetch Organization Name
var Organizations = ss.getRange(i,1);
var org = Organizations.getValue();
// Fetch the email address
var emailRange = ss.getRange(i,6);
var emailAddress = emailRange.getValue();
// Send Alert Email.
var message = 'Hi. Your account is past due ' + DaysAging + ' days.'; // Second column
var subject = 'Past Due Accounting Alert: ' + org;
GmailApp.sendEmail(emailAddress, subject, message);
}
}
Issue:
You should be enclosing the statements you want to run in loop between { }. Otherwise, the for loop is just incrementing the variable i and not running any of your desired code.
Moreover, after the for loop ends, the variable i is higher than the last row with content (lrow) which means that all calls to .getRange(i, columnIndex) refer to empty cells. Because of this, no email is sent, and no error is shown.
Solution:
function CheckPastDueAccounting() {
// Code before for loop starts
for(var i=2; i<=lrow; i++) {
// Code to run in loop (iterate through all rows with content)
}
// Code to run after for loop ends
}
Improving code:
Calling getRange(row, column) for individual cells, for each row in a for loop, is not the best way to iterate through rows with data.
It's much better to first (1) get all the values in the desired range, with getRange(row, column, numRows, numColumns) and getValues(), and then (2) iterate through the resulting 2D array, like this:
function CheckPastDueAccounting() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var lrow= ss.getLastRow();
var firstRow = 2;
var values = ss.getRange(firstRow, 1, lrow - firstRow + 1, 7).getValues();
for (var i = 0; i < values.length; i++) {
var row = values[i];
var value = row[6];
if (value == 'Y') {
var DaysAging = row[2];
var org = row[0]; // Fetch Organization Name
var emailAddress = row[5]; // Fetch the email address
var message = 'Hi. Your account is past due ' + DaysAging + ' days.';
var subject = 'Past Due Accounting Alert: ' + org;
GmailApp.sendEmail(emailAddress, subject, message); // Send Alert Email.
}
}
}
Reference:
for loop
getRange(row, column, numRows, numColumns)

How to get A2:A length using google scripts

I need to send an email from my sheets based on the first Column inputs (email ID's) and (which is dynamic row and gets updated based on the time). how can I return only A2:A length using the google script. Also, how can I do it in excel as well?
var formattedDate = Utilities.formatDate(new Date(), "GMT-6", "'Date: ' yyyy-MM-dd ' Time: ' HH:mm:ss ' CDT'");
var EMAIL_SENT = 'Email Success ! '+ "\n\n" + formattedDate;
/**
* Sends non-duplicate emails with data from the current spreadsheet.
*/function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Script (Beta)").activate();
var startRow = 2; // First row of data to process
var numRows = 120; // Number of rows to process
// Fetch the range of cells 'A' columns
var dataRange = sheet.getRange(startRow, 1, numRows, 3);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var emailSent = row[2]; // Third column
if (emailSent !== EMAIL_SENT) { // Prevents sending duplicates
var subject = '[Auto] The Process Has Not Yet Been Started';
if(emailSent =='')
break;
MailApp.sendEmail(emailAddress, subject, message, {htmlBody: message,
cc: 'abc#xyz.com',
bcc:'cde#xyz.com'});
sheet.getRange(startRow + i, 3).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
Logger.log(sendEmails2);
SpreadsheetApp.flush();
}}}
function A2A(col,sh,ss) {
var ss=ss || SpreadsheetApp.getActive();
var sh=sh || ss.getActiveSheet();
var col=col || 1;
return sh.getRange(2,col,sh.getLastRow()-1,1).getValues().filter(String).length;
}
To get the last row of the 'A' column you can get first all the values of the row:
var dataRange = sheet.getRange('A:A').getValues();
getValues() returns a two-dimensional array of values, indexed by row,
then by column
Since we have already set the column to be A we will need only one for to loop through the array:
var lastDataPosition = 0; // Create variable to set the last row of the column that has data
for (var i = 0; i < dataRange.length; ++i) {
if (dataRange[i] != '') { // Check if the array position has data
lastDataPosition = i + 1 // If the position has data in it -> assign that position to 'lastDataPosition' as the last one
}
}
*We add +1 to the array position since the first cell of the sheet is 1 and the first position of the array is 0
This is how you get the last row with data even if there are some blank cells in the middle.
For excel, I recommend you to create a new question with the proper tags.

"Invalid email: Email (line 24, file "Code")" when trying to send out a mass email

Please help, I have no coding experience and I want to send out a mass email but it keeps saying Invalid email: Email (line 24, file "Code") when I try running the function.
// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = 'EMAIL_SENT';
/**
* Sends non-duplicate emails with data from the current spreadsheet.
*/
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 1; // First row of data to process
var numRows = 1718; // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 3);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var name = row[0];
var emailAddress = row[1]; // First column
var message = 'Hello, '+ name + row[2]; // Second column
var emailSent = row[4]; // Third column
if (emailSent !== EMAIL_SENT) { // Prevents sending duplicates
var subject = 'Wanting To Represent Your School';
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 3).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is
interrupted
SpreadsheetApp.flush();
}
}
}
The problem is in line...
MailApp.sendEmail(emailAddress, subject, message);
At least that's what it's saying.
My goal with this code is to send a message to a bunch of colleges asking for merch in which I have a Google Sheet with the first column being the name of the school, the second being the email of the school and the third being the message to the school. I ran the function once and it sent the emails to two schools because I forgot to change the number of rows to process but now I do not want to run again. Please help, I would greatly appreciate it.
Try this:
function sendEmails2() {
var sheet=SpreadsheetApp.getActiveSheet();
var startRow=2;
var dataRange=sheet.getRange(startRow,1,sheet.getLastRow()-1,3);
var data = dataRange.getValues();
for (var i=0;i<data.length;i++) {
var row=data[i];
var name=row[0];//Column 1
var emailAddress=row[1]; //Column 2
var message='Hello, '+ name + row[2]; // Second column
var emailSent=row[2];//Column 3
if (emailSent !== "EMAIL_SENT") {
var subject = 'Wanting To Represent Your School';
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 3).setValue("EMAIL_SENT");
}
}
}

Updating different tab with a script from a pivot table????

I am new to coding scripts in google and come into a problem I can not work through and my script "mentor" is still not that experienced and can't figure it out either.
I am trying to update a different tab on my sheet from a pivot table when I use my script to send out bulked emails.
So the link below will bring you to the dummy sheet built off my real sheet. The 'PM' tab column L is what I am trying to update. It starts at 1 on all jobs. The emails are sent out by the Blue button on the next tab 'Follow up email' (this is just a pivot table so I can always adjust who is getting the emails easily). But I cant figure out how to have it update the 'PM' tab with the button at the same time as the emails go out.
Link to the open shared spreadsheet. Feel free to play around if you can help.
https://docs.google.com/spreadsheets/d/1_hipIj4suI2xMGUrZhMTBDvkQv9Y9O3JRNNQUpSeAP0/edit?usp=sharing
(only got the emails to send properly so far)
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var rows = sheet.getLastRow()
var dataRange = sheet.getRange(2, 1, rows-1, 7);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[1]; // Second column
var message = 'Hello, we have submitted this job ' + row[2] + ' days Ago. ' + row[4] + ' \n\n' + ' -' + row[5];
var subject = row[0]; // First column
MailApp.sendEmail(emailAddress, subject, message);
}
}
I need the button to send out emails on the 'Follow up email' tab and at the same time "email counter" (column L) would get 1 added to it on the 'PM' Tab. This way I can keep track of how many times that job was emailed from the sheet.
Try this code:
function sendEmails() {
var pmSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("PM");
var emailSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Follow up email");
var startRow = 2; // First row of data to process
var rows = emailSheet.getLastRow()
var dataRange = emailSheet.getRange(2, 1, rows-1, 7);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[1]; // Second column
var message = 'Hello, we have submitted this job ' + row[2] + ' days Ago. ' + row[4] + ' \n\n' + ' -' + row[5];
var subject = row[0]; // First column
MailApp.sendEmail(emailAddress, subject, message);
updatePM(pmSheet, emailAddress);
}
}
function updatePM(sheet, email){
var value;
var emails = sheet.getRange("G3:G" + sheet.getLastRow()).getValues();
for (var i = 0; i < emails.length; i++)
if (emails[i][0] == email){
value = sheet.getRange("K" + (i+3)).getValue() + 1
sheet.getRange("K" + (i+3)).setValue(value);
}
}
I changed the way you got the sheets just to be safe, then I just wrote a small function that gets called after the email is sent, which checks the list of emails in the PM sheet and then updates the value in the sent email column.

How to fetch the row number of a Google Spread Sheet via Google Apps Script?

I have a google script I am using and I was wanting to insert the current row I am working with into a value which will be re added into a formula I set back in the spreadsheet. I want to do this in case someone resubmits the same data, so they are emailed the changes. At the moment this script is just a proof of concept for me, so I can then go on and code the entire process.
The problem I am having with the script is with the value currentRow. It seems to get the value of the first pass and then does not change it, which is problematic when you have more than one entry to process.
I use the value currentRow in the variable RESEND_EMAIL, so it can generate a formula which looks to see if the two columns are alike (I am going to use the date time stamp and copy it in just the first time to column D (also known as var resend[4]).
This way I can set the script to run automatically and check if this column is set as "Yes", in which case it will send and email again and then change the a value (shown here as email address - but I will use the timestamp instead) so that the formula RESEND_EMAIL changes resend back to "No".
How do I always ger the correct row Number in the value currentRow?
// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = "EMAIL_SENT";
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 6)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var emailSent = row[2]; // Third column
var resend = row[4];
var extension = row [5];
var currentRow = sheet.getActiveRange().getRow();
var RESEND_EMAIL = "=IF(A"+ currentRow +"=D" + currentRow +",\"No\",\"Yes\")";
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = "Sending emails from a Spreadsheet";
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 3).setValue(EMAIL_SENT);
sheet.getRange(startRow + i, 5).setFormula(RESEND_EMAIL);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
if (resend == "Yes") { // Prevents sending duplicates
var subject = "Sending emails from a Spreadsheet";
message = message + " " + extension;
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 4).setValue(emailAddress);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
As shown in your code i variable value becomes the current row.
...
var currentRow = startRow + i;
...