ABOUT: Tutorial: Sending emails from a Spreadsheet - google-apps-script

Is it possible to get this script updated? In 2009 it may have worked, but it doesn't now.
Tutorial: Sending emails from a Spreadsheet -
Quick link to Google Developers Tutorial
I can't for the life of me get my own script to work. Having a problem incrementing the rows correctly when it checks before sending, which is either leaving me sending a dozen e-mails of a single row of data or if I try to implement a while loop, I've ended up sending myself over hundreds of e-mails and google then stops me from using the function any further until the next day.
My specific script question is HERE, except I don't think I worded it correctly because no one is replying.

It seems that you forgot a couple of things in your script :
1° : var dataRange = sheet.getRange(sRow,1,1,cols); // this gets only 1 row in your sheet so it is normal that the loop doesn't work (length=1).
I'd suggest to replace the height value by the last row value (see docs to get that value) to make the loop iterate through every rows.
2° when you use .setValue(EMAIL_SENT); the value of EMAIL_SENT is not defined in your code (it is defined outside the function in the tutorial).
I'd suggest to add a statement like this : var EMAIL_SENT="EMAIL_SENT" or, more simply use the string value in your 'setValue' statement like this : .setValue("EMAIL_SENT");

Related

How to change background color of a cell if it is edited after a specific duration?

I have a google spreadsheet which we use to feed inventory purchase and issue data. The only problem is my staff can manipulate purchased quantity, prices and other variables at a later date. I want that if they enter the data in a cell and try to edit it whenever after 12 hours of entering the data, the cell should get highlighted. If possible, the cell should not highlight if I edit the data.
A simple solution is to have a column when this data is entered (if the data is added with a google form, then you are already set to go on that front). At that point all you need is a onEdit triggered function that fetches that timestamp, does var curTime = new Date() and then check what is the difference between them, and if it's greater than 12 hours you do a e.range.setBackground('red') or whatever color you wish (remember that the function must have e defined like function checker(e)).
Having it ignore edits done by you is also simple, just have an a simple
var editUser = Session.getEffectiveUser().getEmail()
if (editUser == 'myEmail#gmail.com`)
return 1;
and it will stop the script if the session users email matches your own.
For future reference please also provide what code you have so far, as currently we don't know what research you have done so far, what worked and what did not. Remember — here you won't get someone to write the program for you, only solve issues you have with code you already have.

Copying values from Google sheet, add time stamp, prevent duplicates

I'm using Kimono to scrape a site that lists active development permits. For a one off data scrape it's fine, the problem is that there is no way of sorting new data. Every time Kimono scrapes it updates the entire array.
This is what the sheet currently looks like
https://docs.google.com/spreadsheets/d/1BH8ESAHQJrog6x8nRBOpgBN-nTN1_aDY7wr8W_YYet0/edit#gid=1865015934
The first sheet is automatically populated and overwritten by Kimono. It seems like the most logical way of making this work would be to copy the values to another sheet, adding a time stamp when this happens and then preventing duplicate values from being posted.
Following this thread is was able to muster this code
I've got the copying part down with the following:
function moveValuesOnly() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var source = ss.getRange('Building Permits!A1:D');
source.copyTo(ss.getRange('Sheet2!A1'), {contentsOnly: true});
source.clear();
}
What I am trying to figure out is how to prevent duplicates based on the URL value.
I know that it is right in front of me, but I'm drawing a blank on how to get this to work.
This Google documentation article on removing duplicates is very well written, so I won't duplicate it: https://developers.google.com/apps-script/articles/removing_duplicates
It has exactly what you need. Read the later part of the article where it talks about how to check duplicates not for the entire row, but specific columns in that row. Once you understand that, your problem is straightforward to solve. Just use 2 arrays, to hold the contents of the rows from the 2 sheets as in the example they've given. compare the first column value of the current row. if it matches, don't copy the row over.
note: this works only when you copy row-by-row into the target sheet, not the entire range as your'e doing right now. But that's unavoidable.

Google Sheets - setFormulaR1C1(formula) doesn't seem to work

I'm really scratching my head over this one. Everything seems to indicate I can use this structure, but Google Sheets doesn't recognize it, and if the function is supposed to parse it into A1 notation, it isn't.
Assume a spreadsheet with one row and two columns, and a number between 1 and 10 is in column 1.
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var theCell = sheet.getRange(1,2,1,1);
theCell.setFormulaR1C1('=IF(R[0]C[-1]>=10, "Hooray!", "Boo!")');
This successfully sets the cell's value to '=IF(R[0]C[-1]>=10, "Hooray!", "Boo!")', but this doesn't parse (#ERROR!). Manually entering something simple like '=R[0]C[-1]' doesn't work either. So I'm very confused. Does R1C1 notation even work?
I can't even get Google's own example to work.
Reference:
https://developers.google.com/apps-script/reference/spreadsheet/range#setFormulasR1C1(String)
Edit:
The fix was to change the comas in the formula to semi-colons. Thanks AdamJ.

How to write an onOpen triggered script without using Activate() methods

Good morning,
I am having an issue with a piece of script which will open the spreadsheet at the first available row after a data table. I am fairly new to this, but as I understand it from research, the onOpen trigger will not work for scripts featuring Activate() methods (which I assume are things like getActiveRange() and setActiveRange() etc.).
I'd really like for this to work, but I can only do it currently by placing a button at the top of the sheet which the user has to click to run the script. I'm at a loss as to how to write in a different way, and have spent ages googling but only get things which don't help me much at all. My code is as below, any help you can give in writing it without using Activate() methods would be very much appreciated. Thanks, MB
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getRange("A2");
var rowCount = range.getValue() + 3;
var newRange = ss.getRange("A" + rowCount);
SpreadsheetApp.setActiveRange(newRange); };
The value on line 4 refers to a value in a cell which is counting the number of rows in the dataset (I had issues trying to count this using script because there are other columns in the dataset which throw functions like getLastRow()).
As mentioned in issue 3928 there is no way (as of now, september 2014) to set a selection on a cell/range/sheet from a triggered function.
This issue was closed as "wont fix" but recently reopened - probably because a lot of people were very disappointed (to use a polite word) - so I suggest you star this issue to increase its visibility and its priority.
In the mean time I'm afraid there is not much we can do except continue to use old version spreadsheet in which this works without problem.
About what you said about counting the last row in a single column, this has been the subject of one of the most popular thread on this forum, look at the suggested solutions there (and also in other similar threads).

Google Apps Script in Spreadsheet storing decimal values instead of Integer in Project Properties

This is my first post. I tried searching via Google and this site but really couldn't find any info about typecasting or converting numerical values within GAS specifically in this scenario. So here the problem:
I have a very basic script attached to a Google Spreadsheet. The script simply keeps track of the last row that was populated, increments the value by one, so that the next row can be populated. I'm storing the "last row used" as a Project Property. For some reason, the script keeps writing the value back into Project Properties as a decimal value, which throws off the whole script since it seems I can't use a decimal value to reference a cell location.
Here is the code snippet:
function onEdit(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var value = ss.getSheetByName("Sheet1").getRange("D13").getValue().toString();
var last = ScriptProperties.getProperty("last");
var therowx = parseInt(ScriptProperties.getProperty("therow"));
Browser.msgBox("The last row is: " + therowx);
if( value != last ) {
ScriptProperties.setProperty("last", value);
ScriptProperties.setProperty("therow", therowx + 1);
}
}
Assuming that I've pre-set the Property to 1 before running the script, once this method fires, it sets it to 2.0 instead of just 2. I've tried wrapping the method call with the Number() and parseInt() functions but they don't seem to make a difference.
I'm open to suggestions, as I'm sure I'm doing something wrong but just not quite sure what.
It would appear that you are using a value from the spreadsheet with var value = ss.getSheetByName("Sheet1").getRange("D13").getValue().toString();
This is were you are getting the decimal as Google spreadsheets will default to one decimal place. You will need to highlight the column or cell and change the format to Number>Rounded to get rid of it.
I am sure i am missing some components of your full script here, however have you tried the "getLastRow" function? There are some scripts in the tutorials that use it and it is a tried tested and true method of finding the last row of the sheet.