Google Sheets Script: Combining onEdit with openById("OtherSheetsId") - google-apps-script

I am pretty bad at this but i did search around quite alot before posting here. I found some answers and I am now stuck at this part.
In short: We have 2 seperate google doc sheets. When a specific cell gets changed in Spreadsheet1, the script must change a specific cell's value in Spreadsheet2.
function onEdit(e) {
var mainsheet = SpreadsheetApp.getActive().getSheetByName('Main');
var changeit = sheet.getRange("A1").getValue();
var offsheet = SpreadsheetApp.openById("spreadsheet2s id").getSheetByName('Echo').getRange("A1");
if (changeit == 'true'){
offsheet.setValue('true');
}
It basically does not work, and in scripts, when I go to Run -> Executions Transcript it tells me Execution failed: You do not have permission to call SpreadsheetApp.openById.
When I try this for the same sheet it works fine.
It seems that an installable trigger would do the trick, but i have not been able to find anything on what exactly to do here, as in how to apply an installable trigger.
It is said by google info that this will allow a function to change info on another sheet. How would we make this only apply to the onEdit(e) function listed above?
And the biggest question is, how do we make this work / tie it all together? What I have done is just pasted this underneath (as if it was its own function).
I have played around with it in various ways (such as trying to add the openByID info in this and afew other silly things) and I think I missing something simple here.
function createSpreadsheetEditTrigger() {
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger('onEdit')
.forSpreadsheet(ss)
.onEdit()
.create();
}
Thank you in advance for your help.

Try this:
function ss1OnEdit(e){
if(e.range.getSheet().getName()!='Main') return;
SpreadsheetApp.openById("ss2id").getSheetByName("Echo").getRange(e.range.getA1Notation()).setValue(e.value);
}
//You can run this function all you want it will not create more than one trigger. But you must run it once to setup the first trigger.
function createSS1OnEditTrigger() {
var ss=SpreadsheetApp.getActive();
var trgs=ScriptApp.getProjectTriggers();
var found=false;
for(var i=0;i<trgs.length;i++) {
if(trgs[i].getHandlerFunction()=="ss1OnEdit") {
return;
}
}
if(!found) {
ScriptApp.newTrigger("ss1OnEdit").forSpreadsheet(ss.getId()).onEdit().create();
}
}

Related

Is there a way to use Google Apps Script to open a document at the last edit?

I have a Google Doc that's getting kind of long. I use it to collect pretty much all my thoughts on different projects, so I'd like it to open back up wherever I left off (not necessarily at the end). - I need it readily accessible on whatever device I'm on, that's why it's a Doc and not a Word file, even though I know how to write the macro there. -
After some digging, it looks like there's an edit trigger for sheets but not for docs, so I've been trying to get a time-based trigger instead as a best approximation of the most recent edit. I wrote the following in the doc's Code.gs, but it doesn't seem to work. Any suggestions?
function onOpen() {
deleteTrigger();
createTrigger();
DocumentApp.getActiveDocument().setCursor(PropertiesService.getDocumentProperties().getProperty('lastOpen'));
}
function createTrigger() {
ScriptApp.newTrigger('savePlace')
.timeBased()
.everyMinutes(1)
.create();
}
function savePlace() {
PropertiesService.getDocumentProperties().setProperty('lastOpen', DocumentApp.getActiveDocument().getCursor());
}
function deleteTrigger() {
// Loop over all triggers and delete them
var allTriggers = ScriptApp.getProjectTriggers();
for (var i = 0; i < allTriggers.length; i++) {
ScriptApp.deleteTrigger(allTriggers[i]);
}
}
(Also, do I have to specify a script property for lastOpen in the dialog box? And what's the best value to put in there if so. [I'm really, really new to this])
Try this:
Just save your bookmark when you leave. And the use gotoBookMark when you open up the document.
function saveBookMark() {
var doc=DocumentApp.getActiveDocument();
var cursor=doc.getCursor();
var bookmark=doc.addBookmark(cursor);
var ps=PropertiesService.getDocumentProperties();
ps.setProperty('bookmarkid', bookmark.getId());
}
function gotoBookMark() {
var doc=DocumentApp.getActiveDocument();
var bookmarkid=PropertiesService.getDocumentProperties().getProperty('bookmarkid');
var pos=doc.getBookmark(bookmarkid).getPosition();
doc.setCursor(pos);
}
This will remove all bookmarks:
function clearBookMarks() {
var doc=DocumentApp.getActiveDocument();
var bkmarks=doc.getBookmarks().forEach(function(bm){bm.remove();})
}
Here's the menu:
function menu() {
DocumentApp.getUi().createMenu('MyMenu')
.addItem('Save BookMark', 'saveBookMark')
.addItem('Goto Bookmark', 'gotoBookMark')
.addItem('Remove All Bookmarks', 'clearBookMarks')
.addToUi();
}
Class Bookmarks
I've never actually used this before but I imagine with a little extra effort one could post an excerpt from each bookmark and provide a checkbox to select them and then only delete the ones you don't want and also provide a button next to each one so you could return to that one whenever you wish.
This was the sample code that got me rolling:
// Insert a bookmark at the cursor position and log its ID.
var doc = DocumentApp.getActiveDocument();
var cursor = doc.getCursor();
var bookmark = doc.addBookmark(cursor);
Logger.log(bookmark.getId());
After that you can use code completion to figure out what methods are available and then refer to the manual when necessary. It's interest sometimes code completion is updated before the document and sometimes the documentation gets updated first so you sometimes have to willing to wing it on your a bit.
I used the Document Properties Service to save the last bookmark id and so when you open up the document it always goes to the last bookmark.
PropertiesService

Trouble triggering a macro when a specific cell has a specific value

I'm trying to trigger a google sheet macro / apps script to reformat a sheet when a specific value is entered into a specific cell. I have been working on it to get it to work but without success.
Here is my code;
function onEdit(e) {
var spreadsheet = SpreadsheetApp.getActive();
var sheet = SpreadsheetApp.getActiveSheet();
var cell = sheet.getRange('C2');
var cellContent = cell.getValue();
if(cellContent === 'Past campaigns - actual cashflows to date only') {
spreadsheet.getRange('7:12').activate();
spreadsheet.getActiveSheet().hideRows(spreadsheet.getActiveRange().getRow(), spreadsheet.getActiveRange().getNumRows());
spreadsheet.getRange('13:13').activate();
}
};
I'm new to macros and apps scripts. I have tried to implement all the suggestions from the following links without success;
How can I get a macro to automatically trigger when a cell reaches a certain value in a Google Sheet?
https://developers.google.com/apps-script/guides/triggers
https://developers.google.com/apps-script/guides/sheets
As #Cooper has said you cannot make a trigger based on a cell value. Only on user changes.
You could try to make the onEdit trigger to execute only inside an if statement. But that's already what you have done.
Try this:
function onEdit(e) {
e.source.toast('Entry');
const sh=e.range.getSheet();
if(sh.getName()!='Sheet Name')return;//you need to change this sheetname
const X=sh.getRange('C2').getValue();
if(X=='Past campaigns - actual cashflows to date only') {
e.source.toast('flag1');
sh.hideRows(e.range.rowStart,e.range.rowEnd-e.range.rowStart+1);
}
}
It's not necessary to use activate in most scripts and certainly in this one since it has to finish in 30 seconds. They use activate in macros because they are following you actions as you move around the screen. But in a script, generally to don't want to interact with the screen very much because it slows down the script and it doesn't really accomplish anything.
I'm currently using in a script that run when a Spreadsheet opens up because it has a lot rows in it and I want it to go down to the last row. So activate is useful because I don't have to scroll down to the last row every time I open the spreadsheet.
try it this way:
function onEdit(e) {
//e.source.toast('Entry');
var sh=e.range.getSheet();
if(sh.getName()!='Sheet Name')return;//you need to change this sheetnamee
var X=sh.getRange('C2').getValue();
if(X=='Past campaigns - actual cashflows to date only') {
//e.source.toast('flag1');
sh.hideRows(e.range.rowStart,e.range.rowEnd-e.range.rowStart+1);
}
}
I hope you're not trying to run this from the script editor because that's not going to work.

How can I get a macro to automatically trigger when a cell reaches a certain value in a Google Sheet?

What I need is for a macro I've recorded called SwitchHotSeat to trigger when the value of cell F3 goes above £1,000,000.00 0r 1000000 or the LEN of cell F3 goes over that length.
I can find guides for doing this in Excel, but not for Google Sheets. below is just the code for my macro.
function SwitchHotSeat() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('3:3').activate();
spreadsheet.getActiveSheet().deleteRows(spreadsheet.getActiveRange().getRow(), spreadsheet.getActiveRange().getNumRows());
spreadsheet.getActiveRangeList().setBackground('#ff0000')
.setFontColor('#ffffff');
};
The macro works fine. I just need a way of triggering it when that cell goes over the 1000000.
You could use simple or installable triggers. See
https://developers.google.com/apps-script/guides/triggers
https://developers.google.com/apps-script/guides/triggers/installable
Example of using onEdit simple trigger
function onEdit(e){
if(/* add here your conditions */) {
SwitchHotSeat();
}
}
NOTE: on edit and on change triggers are triggered only when an user edit the spreadsheet.
Just in case it helps anyone else with a similar issue, I discovered (by logging) that it was returning an object, rather than a number before, so the following code worked fine in the end.
function onFormSubmit(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var millionaire24 = ss.getSheetByName('Millionaire24.');
var cellValue = millionaire24.getRange(3,6,1,1).getValues();
Number(cellValue)
if(cellValue[0] >= 1000000)switchHotSeat();
}

Setting up a trigger when a Google Sheet gets updated by IFTTT

I'm using IFTTT to update my Google Sheets when I receive a SMS. Now, I would like to take a step ahead and write a Google Apps Script that would do different things with the data updated by IFTTT into my Google Sheet. I tried to achieve the same using the Google Apps Script's onEdit function, but that does not work.
I did a lot of search on multiple forums regarding this problem, and I learnt that onEdit works only when a "user" makes the changes to the Google Sheet and not when the changes are done over an API request (I believe IFTTT uses the same). I could not see even a single post with a working solution.
Any ideas? Thanks!
After a lot of Google search, I found below code to be working for me. It is inspired by this answer by Mogsdad.
function myOnEdit(e) {
if (!e) throw new Error( "Event object required. Test using test_onEdit()" );
// e.value is only available if a single cell was edited
if (e.hasOwnProperty("value")) {
var cells = [[e.value]];
}
else {
cells = e.range.getValues();
}
row = cells[cells.length - 1];
// Do anything with the row data here
}
function test_onEdit() {
var fakeEvent = {};
fakeEvent.authMode = ScriptApp.AuthMode.LIMITED;
fakeEvent.user = "hello#example.com";
fakeEvent.source = SpreadsheetApp.getActiveSpreadsheet();
fakeEvent.range = fakeEvent.source.getActiveSheet().getDataRange();
// e.value is only available if a single cell was edited
if (fakeEvent.range.getNumRows() === 1 && fakeEvent.range.getNumColumns() === 1) {
fakeEvent.value = fakeEvent.range.getValue();
}
onEdit(fakeEvent);
}
// Installable trigger to handle change or timed events
// Something may or may not have changed, but we won't know exactly what
function playCatchUp(e) {
// Build a fake event to pass to myOnEdit()
var fakeEvent = {};
fakeEvent.source = SpreadsheetApp.getActiveSpreadsheet();
fakeEvent.range = fakeEvent.source.getActiveSheet().getDataRange();
myOnEdit(fakeEvent);
}
Hope this helps someone in future. Do note that the functions playCatchUp and myOnEdit must be set as "change" and "edit" action triggers respectively in Google Apps Script.

Why doesn't the trigger work for the script running a function on my google spreadsheet?

So I'm using a script on my googledoc spreadsheet that goes through a column and counts a certain number of occurrences of specified formatting. (i.e. in my spreadsheet "=myFunction()")
The function works fine, but my problem is despite setting up a trigger to run the script "onEdit", it never does it. I have to open the script up and save it each time I want it to update on my spreadsheet.
I've been looking up for hours but no one seems to have my question. There are no errors sent by the notifications. The code (though I don't think it's terribly relevant) for my function is:
function CountIfNotStrikeThrough2()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var mysheet = ss.getActiveSheet();
var mydatarange = mysheet.getRange(1,1,390,1);
var numRows = mydatarange.getLastRow();
var rowindex = mydatarange.getRowIndex();
var columnindex = mydatarange.getColumnIndex();
var total =0;
for(i=rowindex;i<=numRows;i++)
{
if(mydatarange.offset(i-1, columnindex-1, 1, 1).isBlank() != true && mydatarange.offset(i-1, columnindex-1, 1, 1).getFontLine() != "line-through")
{
total++;
}
}
return total;
}
I know there's a thread here that has a comprehensive list of when the onEdit trigger doesn't activate. (here) For example, if you setup Data Validation and select an item from the list of values in the validation, it doesn't trigger the onEdit function.
Besides that, could you try a simple trigger instead of installable? This is to say, instead of explicitly associating CountIfNotStrikeThrough2() to the onEdit trigger, please try re-naming the function to "onEdit()" instead and see if that works. This creates an implicit or simple trigger. I've had trouble in the past with installable vs. simple triggers.
Also, please share the exact action you're performing to test the trigger.
Reference: https://developers.google.com/apps-script/understanding_triggers