Google Sheets Script - Not Recognizing Sheet - google-apps-script

I've a Google Sheet.
I went to Tools > Script Editor.
I want to send an email when there are new rows in the sheet.
Here is my script below.
When debugging the ss variable seems to be set but is null.
So when I get to getSheetByName it is also null.
I'm not sure why it isn't getting the sheet.
// 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 sendEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Pricing Changes');
var startRow = 2; // First row of data to process
var numRows = 0; // Number of rows to process
numrows = sheet.getLastRow();
// 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 vdate = row[0]; // First column
var vasin = row[1]; // Second column
var vcurrentprice = row[2]; // Third column
var vnewprice = row[3]; // Third column
var vremarks = row[4]; // Third column
var emailsent = row[5]; // Third column
var message = vdate & "-" & vasin & "-" & vcurrentprice & "-" & vnewprice & "-" & vremarks;
if (emailSent !== EMAIL_SENT) { // Prevents sending duplicates
var subject = 'Sending emails from a Spreadsheet';
MailApp.sendEmail(emailAddress, "New Price Changes", 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();
}
}
}
Note that I have set it up as a File as it was previously set up as "Code" but I thought perhaps that was the issue. (I'm not able to embed the image so hopefully stack will put the correct image link.)
App Script UI Screen Shot

Since you mentioned that both getActive() and getActiveSpreadsheet() returns a null. The last option you have to get the Spreadsheet object is to use either of the following:
1. openById(id)
Opens the spreadsheet with the given ID
A spreadsheet ID can be extracted from its URL. For example, the spreadsheet ID in the URL https://docs.google.com/spreadsheets/d/abc1234567/edit#gid=0 is "abc1234567".
2. openByUrl(url)
Opens the spreadsheet with the given URL. Throws a scripting exception if the URL does not exist or the user does not have permission to access it.

Related

Create and pop up a new email using data from spreadsheet

I have spreadsheet in `Google-drive' that contains information like below:
I need to add a button to each row (suppose that we have more data) and If I click it will pop up an html with a new email that contains info from that spreadsheet and that specific row.
Currently, I've created the following gs file in Apps Script the following script that creates a draft email. However, I want to create and view the new email in order to add more info to the message and then send it.
/**
* 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:B3
var dataRange = sheet.getRange(startRow, 1, numRows, 9);
// Fetch values for each row in the Range.
var data = dataRange.getValues();
for (var i in data) {
var row = data[i];
var emailAddress = row[7]; // First column
var message = row[8]; // Second column
var subject = row[1]+" " + row[6]+ " " + row[1];//'Sending emails from a Spreadsheet';
GmailApp.createDraft(emailAddress, subject, message);
}
}
I found a solution thanks to this solution.
I edited my gs file in Apps Script to have the following script:
/**
* Sends emails with data from the current spreadsheet.
*/
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var row = sheet.getActiveCell().getRow();
var column = 1;//= sheet.getActiveCell().getColumn();
var dataRange = sheet.getRange(row, 1, column, 10);
var data = dataRange.getValues();
var row = data[0];//[i];
var emailAddress = row[7]; // First column
var message = row[8]; // Second column
var subject = row[1]+" " + row[6]+ " " + row[2];//'Sending emails from a Spreadsheet';
GmailApp.createDraft(emailAddress, subject, message);
}
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu("Send email")
.addItem('Generate Draft Email', 'sendEmails')
.addToUi();
}
Now, in my menu in my spreadsheet I have Send Email tab like below:
When I go to a selected row, I click the submenu Generate Draft Email from Send Email and a new email is generated in my Gmail draft emails.

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.

I am trying to send Google Drive Attachments to different email addresses using a script but struggling to make it work

I am new to coding and wanted to automate sending emails with attachments. Basically what I would like to do is to send a message and Google Drive attachment to a specific email address in my spreadsheet. Each attachment (google drive link) is different for each email address and I have everything laid out on a spreadsheet.
The spreadsheet is composed of three sheets, and I want to get the info from the first sheet only (called Full Data). The structure of the columns is the following:
A1 Full Name
B1 First Name
C1 Last Name
D1 Email Address
E1 File attachment (google drive link)
F1 Date
G1 Status
H1 Message
I1 Email Sent?
I would like to send an email with a template starting with "Hello {Full Name}," and in the row below starts the message.
Here's the code I have for now:
// 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 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);
var data = dataRange.getValues();
for (var i = 0; i < data.length; ++i) {
var row = data[i];
var emailAddress = row[3]; // Third column
var message = row[7]; // Eigth column
var emailSent = row[8]; // Ninth column
if (emailSent !== EMAIL_SENT) { // Prevents sending duplicates
var subject = 'Sending emails from a Spreadsheet';
MailApp.sendEmail(emailAddress, subject, message);
sheet.getRange(startRow + i, 8).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
I realize that I have not set a variable for the attachment. The attachment should be taken from column E (corresponding to the row). For example, John Apple in A2 has attachment X in E2, while Mick Orange in A3 has attachment Y in E3, and so on... The range of data goes down till 130 rows but it would be great to have something that always gets the range until there is data (no matter the number of rows).
Does anyone have an idea on how to make this work?
Thanks a lot in advance!!
If I understand you correctly, your current question differs from your previous one in that:
The message body starts with "Hello {Full Name}".
You are not looking for files with the same name as in the sheet, but files that have a certain URL.
The columns to fetch the data from are not the same.
Taking all this into account, I reworked the solution I proposed in your previous question so that it does what you pretend now (read inline comments to see what the code is doing, step by step):
var EMAIL_SENT = "EMAIL_SENT";
function sendEmails2() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Full Data");
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 = 9; // 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[3];
var fullname = row[0];
var messageBody = row[7];
var message = "Hello ".concat(fullname, "\n", messageBody); // Creating message body
var emailSent = row[8];
var fileURL = row[4];
var fileId = fileURL.match(/[-\w]{25,}/); // Extracts file id from file url
if (emailSent != EMAIL_SENT) { // Prevents sending duplicates
var subject = "Sending emails from a Spreadsheet";
var file = DriveApp.getFileById(fileId);
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, 9).setValue(EMAIL_SENT);
// Make sure the cell is updated right away in case the script is interrupted
SpreadsheetApp.flush();
}
}
}
DriveApp does not have an getFileByUrl method, so to get the file, the code first extracts the file id from the url using regex and then calls getFileById.
Let me know if that works for you.

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]});
}
}

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;
...