variables seem undefined but I can't find it - google-apps-script

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.

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

Sending Email using google script

Can anyone help me with sending an email via google scripts?
Here the challenge I am facing is that the range of the first column (email) may go up to 1000 lists of the email addresses. Although, now it's working fine (for now) how can I make it a dynamic range of list to be fed over my email lists to the script.
Code:
// This constant is written in column C for rows for which an email
// has been sent successfully.
var EMAIL_SENT = 'Email Success!';
/**
* Sends non-duplicate emails with data from the current spreadsheet.
*/
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Script (Beta)");
var startRow = 2; // First row of data to process
var numRows = 3; // 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 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';
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();
}
}
}
Doc Link
In order to make your range dynamic, you could use Sheet.getLastRow(), which returns the position of the last row with content.
Assuming that function sendEmails2 is the one your using for this, you would just have to modify the variable numRows. You would have to change this line:
var numRows = 3; // Number of rows to process
To this one:
var numRows = sheet.getLastRow() - startRow + 1;
Reference:
Sheet.getLastRow()
I hope this is of any help.

How to get Google Drive PDF files with "name contains info in cell D1:D from Spreadsheet" and send them as emails to each contact in column A

Disclaimer: I am new to programming so please bear with me :)
I am trying to send emails with a PDF file attachment to different email contacts on a Google Spreadsheet. Each attachment has to be unique to each Name by looking up that file name on google drive. Can someone help with that extra bit of code?
The code I have is currently sending emails with a custom message and a file attachment, and marking each email as sent in column C once the script ends running. However, I would like to send a different PDF attachment to each and every email address, ideally by writing some code that gets the "Investor Name" in column D, looks up the file in Google Drive that contains that name, and attaches that file to the email to be sent out.
So, I need to get the PDF file by each name in each corresponding cell, and not as written below (I believe):
var file = DriveApp.getFilesByName('SHARE CERTIFICATE #60 - JOHN APPLE.pdf');
// 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 = 250; // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 250)
// 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 = "Sending emails from a Spreadsheet";
var file = DriveApp.getFilesByName('SHARE CERTIFICATE #60 - JOHN APPLE.pdf');
if (file.hasNext()) {
MailApp.sendEmail(emailAddress, subject, message, {
attachments: [file.next().getAs(MimeType.PDF)],
name: 'Custom email Team'
});
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 final result I expect is to:
- Send Emails to different email addresses with a message and subject
- Attach a PDF file with file name that correspond to the Name of each email recipient
Thanks a lot in advance, this will massively help! :)
Your code is missing a small detail. Basically, you should get the data from column D when using getRange:
var numRows = sheet.getLastRow() - startRow + 1; // Number of rows to process
var startCol = 1;
var numCols = 4; // Number of columns to process (should include column D)
// Fetch the range of cells A2:D
var dataRange = sheet.getRange(startRow, startCol, numRows, numCols);
Notice that the number of rows to be retrieved doesn't have to be hardcoded. If you use getLastRow you can get the index of the last row with content, and use that to get the desired range. This way you can get exactly the number of rows you want; not more, not less.
Then, inside the loop, retrieve the value in column D, like this:
var fileName = row[3]; // Fourth column
Finally, you retrieve the file from Drive like this:
var files = DriveApp.getFilesByName(fileName);
So the full modified code could be like:
// 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 = sheet.getLastRow() - startRow + 1; // Number of rows to process
var startCol = 1;
var numCols = 4; // Number of columns to process (should include column D)
// Fetch the range of cells A2:D
var dataRange = sheet.getRange(startRow, startCol, numRows, numCols);
// 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 fileName = row[3]; // Fourth column
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = "Sending emails from a Spreadsheet";
var files = DriveApp.getFilesByName(fileName);
if (files.hasNext()) {
var file = files.next();
MailApp.sendEmail(emailAddress, subject, message, {
attachments: [file], // No need to use getAs if your file is already a PDF
name: 'Custom email Team'
});
sheet.getRange(startRow + i, 3).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
}
I have made some additional small changes to that code (for example, changing the variable file to files and then defining var file = files.next()).
I hope this is of any help to you.
Something like this will work I think:
function sendEmails() {
var ss=SpreadsheetApp.getActive();
var sheet=ss.getActiveSheet();
var logsheet=ss.getSheetByName('logSheet');//added logsheet
if(!logsheet){ss.insertSheet('logSheet');}
var startRow=3;//added one row here to accomodate subject and pdfFldrId
var dataRange = sheet.getRange(startRow, 1, sheet.getLastRow()-startRow-1,sheet.getLastColumn())
var data = dataRange.getValues();
var subject= sheet.getRange("B2").getValue();
var pdfFldrId=sheet.getRange("C2").getValue();
for (var i=0;i<data.length;++i) {
var row=data[i];
var emailAddress=row[0];
var message=row[1];
var emailSent=row[2];
var pdfName=row[3];
var files=DriveApp.getFolderById(pdfFldrId).getFilesByName(pdfName);
var n=0;
while(files.hasNext()) {
var file=files.next();
n++;
}
if(n>1){
var ts=Utilities.formatDate(new Date(), Session.getScriptTimeZone(), "MM/dd/yyyy HH:mm:ss");
logsheet.append([ts,pdfName,'more than file with this name']);
continue;//breaks out of loop increment index and keep going
}
if(emailSent!="EMAIL_SENT") {
MailApp.sendEmail(emailAddress, subject, message, {attachments:[file]});
sheet.getRange(startRow + i, 3).setValue("EMAIL_SENT");
}
}
}
If you want to send a different image with the same email list just duplicate the sheet and change the pdfFldrId and the subject which are found in C2 and B2 and learn to keep the different images is different folders with the same filenames.

Executing the correct enteries and ignoring the wrong entries(sending email) from a google form by google app script

I have a google form which collects few details and an email-id, however if there is a wrong entry in the email, the script fails and does not execute the next row, it gets stuck there. Now i want the script to ignore the wrong entries and execute for the correct entries.I have my code below.
var EMAIL_SENT = "EMAIL_SENT";
function sendEmails2() {
var sheet = SpreadsheetApp.getActiveSheet();
var startRow = 2; // First row of data to process
var numRows = sheet.getLastRow(); // Number of rows to process
// Fetch the range of cells A2:B3
var dataRange = sheet.getRange(startRow, 5, 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 = "You have been registered for follwoing events:-";
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 7).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
For this you can add a if condition before this line of code
if(valid email address){
MailApp.sendEmail(emailAddress, subject, message);
}
else{continue;}
to verify if the email id has a valid value or not.
You can also check this approach.
Hope that helps!