I started an email list on google sheets for some guys in my area to sign up for basketball twice a week. I want to send a group email to the entire list twice a week. The email will not send because I get the following error message:
3/14/17 10:53 AM emailTuesday Limit Exceeded: Email Recipients Per Message. (line 34, file "Code") time-based 3/14/17 10:53 AM
There are 75 people on the list. In all my research I've found that even the lowest level accounts can send 100 emails per day. Other than this list, I don't send many emails so I know I'm not exceeding that limit. In fact, I have been manually sending the email in the meanwhile since it is not currently working. My script is below:
function emailWednesday(){
var emaillistsheet = SpreadsheetApp.getActive().getSheetByName('FridayEmailList');
var startRow = 2; // First row of data to process
var numRows = 90; // Number of rows to process
var dataRange = emaillistsheet.getRange(startRow, 1, numRows, 1)
// Fetch values for each row in the Range.
var data = dataRange.getValues();
var emailAddress = data; // First column
var message = "message";
var subject = "subject";
MailApp.sendEmail(emailAddress, subject, message);
}
Related
I have a script that looks into values in column G and if the correspondent cell in column A is empty, sends me an email.
--- WHAT WORKS --
It works ok for static values: it sends one email per each not empty cell in column G for which there is no value in column A
--- WHAT DOESN'T WORK --
It sends several emails for what I assume it's every Column G cell (empty or not) when the column A values are fetched from another tab. That way it's like all G and A cells have data, so I get multiple unwanted emails.
This is the script code:
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet to send emails');
const data = sh.getRange('A2:G'+sh.getLastRow()).getValues();
data.forEach(r=>{
let overdueValue = r[0];
if (overdueValue === ""){
let name = r[6];
let message = 'Text ' + name;
let subject = 'TEXT.'
MailApp.sendEmail('myemail#gmail.com', subject, message);
}
});
}
And this is the link to the test sheet:
https://docs.google.com/spreadsheets/d/1OKQlm0PjEjDB7PXvt34Og2fa4vPZWnvLazTEawEtOXg/edit?usp=sharing
In this test case, I "should" only get one email, related to ID 55555. With the script as is, I get one related to 55555 and several others "undefined".
To avoid e-mail spam, I didn't add the script to that sheet but it shows the "Vlookup" idea.
Can anyone give me a hand, please?
Thank you in advance
Issue:
The issue with your original script is that the sh.getLastRow returns 1000 (it also processes those rows that doesn't have contents, result to undefined)
Fix 1: Get specific last row of column G:
const gValues = sh.getRange('G1:G').getValues();
const gLastRow = gValues.filter(String).length;
or
Fix 2: Filter data
const data = sh.getRange('A2:G' + sh.getLastRow()).getValues().filter(r => r[6]);
Note:
As Kris mentioned in the comments, there is a specific case where getting the last row above will fail (same with getNextDataCell). This will not properly get the last row WHEN there are blank rows in between the first and last row of the column. If you have this kind of data, then use the 2nd method which is filtering the data.
If your data in column G does not have blank cells in between the first and last row, then any method should work.
I checked your test sheet, and sh.getLastRow() is 1000.
OPTION 1
If column G won't have empty cells between filled ones, then you can do this:
const ss = SpreadsheetApp.getActive();
const sheet = ss.getSheetByName("Sheet to send emails");
// get the first cell in column G
var gHeader = sheet.getRange(1, 7);
// equivelent of using CTRL + down arrow to find the last da
var lastRow = gcell.getNextDataCell(SpreadsheetApp.Direction.DOWN).getRow();
const data = sheet.getRange(2, 1, lastRow, 7).getValues();
OPTION 2
Add another condition to your code - like this:
data.forEach(r=>{
let overdueValue = r[0];
let name = r[6]
// check if the value in col A is blankd and col G is not blank
if (overdueValue === "" && name !== ""){
let message = 'Text ' + name;
let subject = 'TEXT.'
MailApp.sendEmail('myemail#gmail.com', subject, message);
}
});
And to speed it up, use a named range to limit how many rows it has to iterate through:
const ss = SpreadsheetApp.getActive();
const data = ss.getRangeByName("Your_NamedRange_Here").getValues();
I am trying to create a script that sends me an email of the contents of the last cell in a column.
GOAL: Last edited cell in a column to be emailed with the cell contents
For example, I have a sheet that on column C contains values 1,2,3,4, and 5 - with cell C1 containing 1, cell C2 containing 2, etc.
In working with the excel, a new number will be added on the same column, and my goal is to have the latest added cell to be delivered to me in an email - such as whenever C6 is filled and we get the value "6" there, I would recieve an email with the BODY being just "6".
This is what I've been working with but have no had any success in so far.
Thank you for your help!
/**
* Sends emails with data from the current spreadsheet.
*/
function sendEmails() {
var sheet = SpreadsheetApp.getActiveSheet();
var lastRow = sheet.getLastRow();
var startRow = 3; // First row of data to process
var numRows = 1; // Number of rows to process
var dataRange = sheet.getRange(lastRow, 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 = "me#gmail.com";
var message = row[0];
var subject = 'Sending emails from a Spreadsheet';
MailApp.sendEmail(emailAddress, subject, message);
}
}
message = row[0] doesn't make any sense.
you've defined row as equal to data[i] so row is not an array and the [] is not applicable..... try using row instead of message in the email call and eliminating the var message = row[0] stuff
I've searched everywhere on the web and on this site as well. What I want to do is relatively simple, however I don't know enough about javascript to write it myself but I am learning.
I have a google sheet with email addresses as well as data in 5 columns. Let's say there are 3 email addresses total. Now say there are 3 rows with the same email address and each row has new/different data than the previous row. I want to send JUST 1 email to that address with the 3 rows / 5 columns of data. There also may be an email address but with no data in the rows/columns. Obviously nothing should be sent from that row. Then there's the second email address. Repeat but send to the new email address. Next email, etc.
Here's the sheet to give you a clearer picture. I would like to keep the look/color of the table of column B through Column F in each email.
The following script had me most of the way there (sans the look/color of the table), however when I tried using it a few days ago it was sending a new email for each row of data instead of just one email for several rows of data...but it previously was working! (again sans the look/color of my sheet, it was simple text)
function sendEmails() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
ss.setActiveSheet(ss.getSheetByName("sheet1"));
var sheet = SpreadsheetApp.getActiveSheet();
var dataRange = sheet.getRange("A2:m8");
var data = dataRange.getValues();
// Modified
var temp = [];
var emailAddress, data1, data2, data3, data4, data5;
for (var i in data) {
[emailAddress, data1, data2, data3, data4, data5] = data[i];
var message = '\n\n' + data1 + ' ' + data2 + ' ' + data3 + ' ' + data4 + ' ' + data5;
if (emailAddress || !data1) {
if (temp.length > 0) {
MailApp.sendEmail(temp[0], "Subject", temp.slice(1,temp.length).join("\n"));
var temp = [];
}
temp.push(emailAddress, message);
if (!dimension) break;
} else {
temp.push(message);
}
}
}
The format of the body of the email should look like the following, but again, I also want it to retain the look/feel/color from the sheet:
Once that's working, I would like my email signature from Gmail included in the email. I'm not sure if I can get it exactly as is in my Gmail account, or just simple text via javascript.
I have this line but that's simple text. Any way to get my logo/formatting/etc. to match my Gmail or outlook account?
var signature = "\n---\nsample signature";
Your help is much appreciated. Thank you.
I'm a complete noob.
I'd like to forward labelled emails on the 1st of every month to another email address. Using Gmail's filters, the label "forwardthis" get applied to my invoices and statements I received during the month. On the 1st of every month, I'd like Google scrips to forward all new emails with the "forwardthis" label to another email address, including attachments.
The script I found doesn't work as I hoped. Not sure what the interval options below are for, but I need to run my script only once a month, on the 1st.
function autoForward() {
var label = 'forwardthis';
var recipient = 'elvis#gmail.com';
var interval = 5; // if the script runs every 5 minutes; change otherwise
var date = new Date();
var timeFrom = Math.floor(date.valueOf()/1000) - 60 * interval;
var threads = GmailApp.search('label:' + label + ' after:' + timeFrom);
for (var i = 0; i < threads.length; i++) {
threads[i].getMessages()[0].forward(recipient); // only the 1st message
}
}
Hope my question is clear. I'll greatly appreciate some guidance, thanks.
Sends labeled emails created after the last time the script was run
Evidently the script was meant to run every 5 minutes so rather that keeping tracked of emailed labels already sent the script just takes the labels created after the current time minus the interval or in other words the labeled emails received since the last time the script was run.
Since you want to run the script on the first of every month you will have to figure how to get the time for the 1st of last month and put that value into the timefrom variable.
function autoForward() {
var label = 'forwardthis';
var recipient = 'elvis#gmail.com';
var interval = 5; // if the script runs every 5 minutes; change otherwise
var date = new Date();
var timeFrom = Math.floor(date.valueOf()/1000) - 60 * interval;//This subtracts five minutes from the current time
var threads = GmailApp.search('label:' + label + ' after:' + timeFrom);//Emails with the correct label and created since 5 minutes ago are sent
for (var i = 0; i < threads.length; i++) {
threads[i].getMessages()[0].forward(recipient); // only the 1st message
}
}
Noob or not, you can figure this out. Most of what you need is right here. Or possibly here.
You can use triggers to run your script once a month. You can read about triggers here.
I have found ways to add the numbers of multiple input fields together and output the result. However I am trying to find a way to add numbers within one field, if possible. I basically want it to work as if it was an excel cell and add up numbers using a + in between each one.
So as the user enters =125+11+110 it automatically is adding those numbers to and displaying the total next to the box.
You can split the string:
var expression = "125+11+110";
var operands = expression.split("+");
var sum = 0;
for (var i = 0; i < operands.length; i++) {
sum += parseInt(operands[i]); // use parseFloat if you use decimals as well.
}
But the above example will not know hot to do multiple types of operations in single text box. For example, 100+76-45 will give you incorrect answer.
You can also use eval, but know that it can be harmful if you used it in a wrong way.
var expression = "125+11+110";
var sum = eval(expression);
If you use eval:
do not store the strings user submitted in the database without sanitation.
do not send back the strings user submitted to the browser as JavaScript.
to be safe, just do not even send the user's strings to server at all.
This is the dirty method. It splits the input between the plus signs and adds up the values in the array:
var userinput = "125+11+110";
var userinputarray = userinput.split("+");
var totalamount = 0;
$(userinputarray).each(function(key,value){
totalamount += parseFloat(value);
})
It does not handle subtraction. However you can do a regex match instead:
var userinput = "125+11+110";
var userinputarray = userinput.match(/(\+|\-){0,1}[0-9.]{1,}/g);
var totalamount = 0;
$(userinputarray).each(function(key,value){
totalamount += parseFloat(value);
});
Parsefloat will remove the + symbol, while still using the negative sign.
var data = $('#inputfeildID').text();
var arr = data.split('+');
var total = 0;
for(i=0; i < arr.length ; i ++){
total += arr[i];
}
console.log( total );
When user click enter or submit , first get the value or text in the input field & then split it from + , then add the array elements . you will get the total value of the input box ..
if you want to add those number automatically when user is typing , you have to use jQuery keyup function & when user press + , then add the next number to previous one
You can put a keyup listener on the text box. Then in the code fired by the listener, if "myinput" is the id of your input field:
var exp = document.getElementById('myinput').value;
var result = eval(exp);
"result" will be the value of the expression. You should also really check "exp" to see that it is a valid entry, because the user could put any kind of garbage into the input field, and there could also be security issues.
You should use eval. Like so...
var input = "125+11+110";
var answer = eval(input);
http://www.w3schools.com/jsref/jsref_eval.asp