Google Sheets - Sending email based on specific sheet in a spreadsheet - google-apps-script

New to Google Scripts so I'm bumping my head on this entry level code. I want to send an email based on a specific sheet in a spreadsheet. The tab or sheet is named 'Test 2'. Currently this is my code.
/* Sends emails with data from the current spreadsheet.*/
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSpreadsheet();
var startRow = 2; // First row of data to process
var numRows = 2; // Number of rows to process
var dataRange = getRange(startRow, 1, numRows, 2); // Fetch the range of cells A2:B6
var data = dataRange.getValues(); // Fetch values for each row in the Range.
for (var i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = 'THIS IS A TEST';
MailApp.sendEmail(emailAddress, subject, message);
}
}
And right now it's throwing this error.
ReferenceError: "getRange" is not defined. (line 8, file "Code")
How can I get it to run while referencing that sheet 'Test 2'?
Thanks!

You want to avoid the error of "getRange" is not defined..
You want to retrieve the values from the cell "A2:B6" of the sheet Test 2.
If my understanding is correct, how about the following modification?
From:
var dataRange = getRange(startRow, 1, numRows, 2);
To:
var dataRange = sheet.getSheetByName("Test 2").getRange("A2:B6");
Note:
In this case, at first, retrieve the sheet object of Test 2 and use the method of getRange for the sheet object.
I thought that a1Notation might be suitable for your situation.
Reference:
getSheetByName()
getRange(a1Notation)
If I misunderstood your question and this was not the direction you want, I apologize.

Related

Google sheet SendEmail Script send a message to the same email address multiple times/ It hasn't happened untill today. Any way To solve it?

Stack overflowers!
I have a problem with my Sendemail Script, which is sending the same message for 8 times (really annoying, isn't it?) to each mail address. (It has been working fine until today though, I send remainders to five people daily; and my google sheet has two columns, one is for email address and the other is the message)
My code looks like this:
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 5; // Number of rows to process
// Fetch the range of cells A2:B6
var dataRange = sheet.getRange(startRow, 1, numRows, 5);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i in data) {
var row = data[I];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = 'ATTENTION!!!!!!';
MailApp.sendEmail(emailAddress, subject, message);
}
}
How can I solve this annoying problem? (I am not a developer; I am just a learner who can use internet sources very well; So, I don't understand scripts much and still can edit or change it a bit.)
There is currently a bug with time-driven triggers
As a consequence, the trigger might fire multiple times - more frequent than you specify.
You can "star" the issue on Google's Issue Tracker to indicate that you are also concerned.
In the meantime, as a workaround:
Use Script Properties to save the last execution time
Implement an if statement at the beginning of your code that executes the rest of the code only if the last execution time (retrieved from the script properties) is not less than the specified interval
Sample:
function sendEmails() {
if(!PropertiesService.getScriptProperties().getProperty("lastExecution")){
PropertiesService.getScriptProperties().setProperty("lastExecution", new Date().getTime());
}
var lastExecution = PropertiesService.getScriptProperties().getProperty("lastExecution");
var now = new Date().getTime();
var oneDay = 1000*3600*24;
if(now-lastExecution >= oneDay){
//here the rest of you code
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 5; // Number of rows to process
// Fetch the range of cells A2:B6
var dataRange = sheet.getRange(startRow, 1, numRows, 5);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i in data) {
var row = data[I];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = 'ATTENTION!!!!!!';
MailApp.sendEmail(emailAddress, subject, message);
PropertiesService.getScriptProperties().setProperty("lastExecution", now);
}
}
}

google sheets script wont get value for subject

I am trying to make an auto emailer with the google sheets script tool and I took this code directly from google and did some very minor adjustments so it will add subject and so i can better understand it...or so i thought, it sends emails fine but evert test email i get does not have a subject.
sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // Starts at row 2, row 1 has all the titles
var numRows = 2; // Allows the HORIZONTAL rows to process
var dataRange = sheet.getRange(startRow, 1, numRows, 2); // Set range to process
var data = dataRange.getValues(); //Assign values to the range
for (var i in data) {
var row = data[i];
var emailAddress = row[0]; // First column (email address)
var message = row[1]; // Second column (message)
var subject = row[2]; // Third column (subject)
MailApp.sendEmail(emailAddress, subject, message);
}
}
furthermore if there is any other way for me to do this cleaner then I am open for more advice and tips. thank you.
Issue with your code:
In your script, sheet.getRange(startRow, 1, numRows, 2) is used as the range for retrieving the values. In this case, the columns "A" and "B" are retrieved.
Solution
The subject is put in the column "C", please modify to sheet.getRange(startRow, 1, numRows, 3). By this, var subject = row[2] has the value of the column "C".
Reference
getRange(row,column,numrows,numcolumns)
– Tanaike

Attaching Google Sheet to emails from Gmail automatically using G Script

I found a G Script that works for sending an email to hundreds of addresses, based on an excel file with the name (which I can convert into Sheets if necessary).
I want to be able to add an attachment (which is currently an excel file, but can easily be converted into Sheets) to each email that is sent. The attachment is the same for each email.
The below script works for sending the emails, but I can't find the right way to add an attachment to each email (Note: line 17 is where I'm getting the error code).
I've tried a few different versions based on other similar strings on this site - but I can't get it to work with my situation, or maybe I don't understand how to structure the syntax accordingly.
/**
* Sends emails with data from the current spreadsheet.
*/
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 1; // Number of rows to process
// Fetch the range of cells A2:B2
var dataRange = sheet.getRange(startRow, 1, numRows, 1);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = 'Sending emails from a Spreadsheet'
var file = Drive.Files.get('test123/xlsx');
MailApp.sendEmail(emailAddress, subject, message, {attachments:
[file]});
}
}
ReferenceError: "Drive" is not defined. (line 17, file "Code")
"Drive" is the Advanced Drive API.In order to use the Drive advanced api you need to enable that api. But you really don't need the advanced api here.
Is your file in drive?
If so try this instead:
var file = DriveApp.getFileById("XXXXXXXXXXX");
the "xxx" should be the drive id.
According to the reference documentation, it looks like the class you're looking for is DriveApp.
/**
* Sends emails with data from the current spreadsheet.
*/
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 1; // Number of rows to process
// Fetch the range of cells A2:B2
var dataRange = sheet.getRange(startRow, 1, numRows, 1);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (i in data) {
var row = data[i];
var emailAddress = row[0]; // First column
var message = row[1]; // Second column
var subject = 'Sending emails from a Spreadsheet';
var file = DriveApp.getFileById('test123/xlsx');
MailApp.sendEmail(emailAddress, subject, message, {attachments:
[file]});
}
}

variables seem undefined but I can't find it

script failing with Invalid email: undefined (line 29, file "newCode")
Have worked through some errors but am stuck on this.
Besides the error message I found a debugger option and ran that.
It didn't make a lot of sense but this line seem to match the complaint.
"emailAddress undefined"
I feel like it might have to do with what I've done here:
var emailAddress = row[3]; // columnD
All I think I did in the borrowed code was change which column I want to pull the info from. In this case an email address. As far as I know Column D in Google Sheets is referenced as "3" ColA=0, ColB=1...ColD=3.
I can't hard code the email address as it will vary one row to the next.
Can someone advise how this is in error?
function Initialize() {
var triggers = ScriptApp.getProjectTriggers();
for(var i in triggers) {
ScriptApp.deleteTrigger(triggers[i]);
}
ScriptApp.newTrigger("SndMail()")
.forSpreadsheet(SpreadsheetApp.getActiveSpreadsheet())
.onFormSubmit()
.create();
}
// Write a value to column G for rows where an email sent successfully and sends non-duplicate emails with data from the current spreadsheet.
function SndMail() {
var EMAIL_SENT = 'Sent';
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = 75; // Number of rows to process.
// Fetch the range of cells A2:G76
var dataRange = sheet.getRange(startRow, 2, numRows);
// 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[3]; // columnD
var message = 'Please create a Logistics Case and log the CAS# for: <br/> row[4 + 5]'; // columnE
var mailout = row[6]; // columnG
if (mailout != EMAIL_SENT) { // Prevents sending duplicates
var subject = 'Logistics Claim case request';
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 3).setValue(Sent);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
What should be happening is that when a google form is submitted the sheet is updated and a script runs to email the intended recipient (email addy in Column D) and subsequently put the text "Sent" in Column G. Which is then filters subsequent function runs, avoiding duplicate email sends.
How about this modification?
Modification point:
When value is retrieved from sheet.getRange(startRow, 2, numRows), only column "B" is retrieved.
By this, var emailAddress = row[3] becomes undefined.
I think that the reason of your issue is this. In order to avoid the error, how about modifying as follows?
Modified script:
From:
var dataRange = sheet.getRange(startRow, 2, numRows);
To:
var dataRange = sheet.getRange(startRow, 2, numRows, sheet.getLastColumn());
or
var dataRange = sheet.getRange(startRow, 2, numRows, 7); // A2:G76 ?
Reference:
getRange(row, column, numRows, numColumns)
If I misunderstood your question, I apologize.

Copy Row and Delete

I have 2 sheets - 'Form Responses 1' and 'Students'.
When I run the function below, it copies all data from 'Form Responses 1' to 'Students' where I'll need to massage the data further in the second sheet. After I copied, I want that particular row to be deleted from 'Form Responses 1'. The next round when I run the function again (when there is new data in 'Form Responses 1'), it will append to 'Students' accordingly.
Would very much appreciate if you could advise how can I amend my codes below, thanks!
function Copy()
{
var sss = SpreadsheetApp.openById('sheet ID'); //replace with source ID
var ss = sss.getSheetByName('Form Responses 1'); //replace with source Sheet tab name
var range = ss.getRange('A:V'); //assign the range you want to copy
var data = range.getValues();
var numRows = range.getNumRows();
var getRow = range.getRow();
var tss = SpreadsheetApp.openById('sheet ID'); //replace with destination ID
var ts = tss.getSheetByName('Students');
ts.getRange(1, 1, data.length, data[0].length).setValues(data);
/*delete function is missing*/
}
The following bit of code should achieve the desire result, otherwise it is a good place to start. The code is pretty simple, so I put all the explanations in the comments of the code.
To use this code you can create a Stand alone script. (Does not need to be bound to a spreadsheet.) Copy Primary and Secondary code into two seperate tabs. (See the attached picture.) Once you have changed the IDs in the two scripts, run the primary script and you should see the desired result. (Be aware the all data in the form responses will be cleared.)
Hope this helps, and feel free to ask if you are not sure. Just note at this point I will be directing you to the documentation instead of trying to explain how certain methods/calls work:
Primary Code
function copy_Delete(){
var ss, sheet;
var lastRow, lastColumn;
var responseData;
//Get Spreadsheet and Sheet name for Form Responses Sheet
ss = SpreadsheetApp.openById("YOUR_ID_HERE");
sheet = ss.getSheetByName("Form Responses 1");
//Gets a numerical value representing the last row and last column where data is entered.
lastRow = sheet.getLastRow();
lastColumn = sheet.getLastColumn();
//Get all the data in the From Responses Sheet and put it all in an array.
responseData = sheet.getRange(2, 1, lastRow -1, lastColumn).getValues();
//Call the destination function and pass the array to it. Then clear form responses of all data.
destination(responseData);
sheet.clear();
}
Secondary Code
function destination(responseData){
var ss, sheet, form;
var numRows, numColumns, lastRow;
//Get Spreadsheet and Sheet name for your destination sheet
ss = SpreadsheetApp.openById("YOUR ID HERE");
sheet = ss.getSheetByName("Destination Sheet");
//Get the dimensions of the array and the last row of the spreadsheet.
numRows = responseData.length;
numColumns = responseData[0].length;
lastRow = sheet.getLastRow();
//Using the dimensions above,we push our array from the previous function into our new sheet.
sheet.getRange(lastRow +1, 1, numRows, numColumns).setValues(responseData);
//Get form and delete all responses.
form = FormApp.openById('YOUR_FORM_ID_HERE');
form.deleteAllResponses();
}
Attached example