Why isn't my time based trigger working properly? - google-apps-script

I recorded a simple google sheets macro ( relative reference ) by copying info within a cell and pasting it into the cell below. It works fine when a manually run the macro but when I added a time based trigger ( every minute ) it only runs on the cell "A1" and not the selected cell e.g. B2.
I need the time based trigger so that it works for the selected cell instead.
function copy1() {
var spreadsheet = SpreadsheetApp.getActive();
var sheet= SpreadsheetApp.getActiveSheet()
spreadsheet.getCurrentCell().offset(1, 0).activate();
spreadsheet.getCurrentCell().offset(-1, 0).copyTo(spreadsheet.getActiveRange(), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
};

Seems like when it automatically runs, the initial cell is A1. You can overwrite that by saying offset(2,2) on line 4 of your code. Then it should always use that cell. Remember that if you create a relative reference that the currently selected cell will not necessarily be selected when the trigger is running.

UPDATE: The time-driven trigger cannot retrieve the current cell
Why?
Because a time-driven trigger runs even if the spreadsheet is closed - in this case there is no current cell, but by default Google Sheets always resets the current cell to A1 when you reopen the spreadsheet - this is the one the tie-driven trigger retrieves.
Good news: Recently a new trigger has been introduced - onSelectionChange(e)
This trigger fires every time you change the selection.
So for example if you click away from A1 to B2 - B2 will be detected as the new selected cell with the event object e.range.
Sample:
function onSelectionChange(e) {
var cell = e.range;
cell.copyTo(cell.offset(1, 0), SpreadsheetApp.CopyPasteType.PASTE_NORMAL, false);
}

Related

How to determine which row has changed/updated on Google Sheets Script Editor

For my google sheets, each row gets populated at random, but when it does get populated, I want a function to run. Each time something gets populated, it's the next row (it's not a cell or a random row).
I have the onChange trigger running right now. It is set to "run FunctionA from Spreadsheet on change". In that function, how do I grab the row that has been specifically changed/updated? What is the function/method I would use to manipulate whatever that row is?
I searched around but couldn't find an appropriate answer.
You should use the onEdit spreadsheet event. (https://developers.google.com/apps-script/guides/triggers/events)
You can call it this way :
function onEdit(e){
//Access the range with your parameter e.
var range = e.range;
var row = range.getRow();
var column = range.getColumn();
//do whatever you need with that range
}
It will automatically run when there is an edit on a cell of the spreadsheet.

Trigger that fires when a new cell selection is made

Have successfully implemented OnEdit/OnChange triggers. However, these require an actual change to a cell.
It does not look like there is an analogous OnSelectionChanged trigger that fires when a new cell selection is made.
Any thoughts on how one might implement?
Good news. There is a new Simple Trigger, check this release note:
A new simple trigger, onSelectionChange(e), has been added for
Google Sheets. The onSelectionChange(e) trigger runs automatically
when a user changes the selection in a spreadsheet.
The following code illustrates how to use this trigger:
function onSelectionChange(e) {
var range = e.range;
if(range.getNumRows() === 1 && range.getNumColumns() === 1) {
SpreadsheetApp.getActiveSheet().clearFormats();
range.setFontColor("red").setFontWeight("bold")
}
}
If you add this function in your sheet bounded script the selected cell will always be highlighted as bold red. Please, note that this is just an example. The clearFormats() call will clear the format of all cells in the active sheet, so take care with it.

Trigger a script when a formula changes a cell value

I'm using a Google script then sends out an email when a certain column in a Google sheet is changed. The information in the cell is either inputted manually, or completes using a formula based on information in other cells.
The script works fine when information is manually entered, but not when the formula runs. I've read up on it and realise that a formula calculation doesn't count as an edit, so how do I get the script to run?
It's currently set up to trigger from the spreadsheet when there's an edit.
Below is the part of my script that covers the column/cell in question.
function sendEmail() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var row = sheet.getActiveRange().getRow();
var cellvalue = ss.getActiveCell().getValue().toString();
if(sheet.getActiveRange().getColumn() == 12)
There's a lot more included in the script so I haven't copied everything onto here. Many thanks in advance.
There is no trigger that can run when a formula changes.
Try figure out, what conditions is your formula depends on:
if it is another cell, entered manually, then use those cell to trigger it's changes with onEdit
if the formula imports data from external source, use random or time functions, you'd better use onTime trigger.
if the formula uses importrange then go to the range you import and see the original range, return to step 1 → 2...

Running scripts resetting active cell

I'm fairly new to Google Scripts, and I'd like to use onEdit to trigger a function whenever a cell is edited. While I've got it working, it resets the active cell to A1 when it runs, so if someone tries to enter more than one value at a time, e.g. cells C4, D4, E4) - while they are entering a value into E4 the selection will reset to A1.
Cheers
Edit: Here's a spreadsheet showing the problem.
On further inspection, it looks like running any script (I also have a delete row function and an insert row function) will reset active cell to A1. This may not be the technical term, but if you have for example D4 selected, then running a script will change selection to A1
In your code, you're resetting the active sheet, which reloads the page when the script is triggered.
Here's your current code:
// Get the active workbook
var ss = SpreadsheetApp.getActiveSpreadsheet();
// Get the first sheet in the workbook
var sheet = ss.getSheets()[0];
// Reload that first sheet
SpreadsheetApp.setActiveSheet(ss.getSheets()[0]);
Remove the third line where .setActiveSheet() is called and the problem will go away.

How to create a time based trigger for a google spread sheet created with apps script

I wonder if there is a way to create a time based trigger fir a google spread sheet created with google apps script.I googled a lot and no luck.what i am exactly looking for is,i created a google spread sheet and took the id of that spread sheet like this
var spreadSheet = SpreadsheetApp.create('Google Contacts');
var id = spreadSheet.getId();
PropertiesService.getScriptProperties().setProperty('ssId', id);
and then i was trying to create a trigger for this spread sheet like this
ScriptApp.newTrigger("myTrigger").timeBased().everyMinutes(1).create();
and myTrigger is this
function myTrigger(e) {
var range = e.range;
range.setNote('Last modified: ' + new Date());
}
I want to run this trigger ,ie,this time based trigger on my spread sheet created with the previous method.And now i don't find a way for this.
What i am looking for is, i want to run this time based trigger on the spread sheet with this id
var id = PropertiesService.getScriptProperties().getProperty('ssId');
I was able to create this trigger for this spread sheet with the code ScriptApp.newTrigger('myTrigger').forSpreadsheet(id).onEdit().create(); but this is not triggering on a time based ,rather than it is triigering on editof the above spread sheet.
Thanks.
The issue here is your trigger function myTrigger is coded to expect an onEdit event rather than an time based trigger event, as a result the script simply crashes when your time-based trigger calls it.
You can probably see details of this failure in the Execution Transcript of your Script Editor.
The reason is the reference to e.range, with an OnEdit trigger e.range is the edited range, but on a time-based trigger e.range is undefined. This is because the time-based trigger has nothing to do with any given range of cells.
Since your goal seems to be to set a note saying when a given range was last modified, I don't think you can easily achieve your final goal with a time-based trigger, why not simply use the onEdit trigger?
If you want to interact with the spreadsheet from your time based trigger, you will need to open the spreadsheet and get the range, then take your actions.
function myTrigger(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var range = ss.getRange("A1:B1");
range.setNote('...')
You can see the different properties of event vs time-driven triggers listed in the tables here: https://developers.google.com/apps-script/guides/triggers/events#google_sheets_events