Trigger function when adding a row in an other spreadsheet - google-apps-script

I have a problem with triggers in Google App Script. I have a spreadsheet holding my users and other stuff (appSheet), and I have a second spreadsheet that holds all the data (dataSheet).
I also built a script that imports some data from "appSheet" to "dataSheet", and it works pretty well. The problem is I need it to execute automatically when a new row (user) is added in the app sheet. The built-in triggers in Google App Script doesn't allow me to set that kind of trigger.
I set this importing function in the dataSheet, maybe should I set it in the appSheet ? It may seem super easy but I'm a newbie to this :)
Has someone an insight on how to automatically trigger that function ?
Thanks a lot !

Thanks guys for your answers !
I found a very simple way to achieve this.
Instead of setting the script on the dataSheet and having the need of an "onEdit" trigger, I put the script in the appSheet and did little modifications.
The script is as followed :
function exportData() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var values = ss.getSheetByName('mySourceSheet').getRange('A2:B').getValues();
var dataSheet = SpreadsheetApp.openById("myDestinationSpreadsheet");
var targetSheet = dataSheet.getSheetByName("myDestinationSheet");
targetSheet.getRange(2,1,values.length,values[0].length).setValues(values);
}
The "2" in the "targetSheet.getRange" meaning I want it to begin in row 2.
Everything runs perfectly now with the built-in triggers in Apps Script.

Related

Google sheets macro only working when I manually trigger it

I have a spreadsheet that is connected a Hubspot workflow. When a deal is closed in our CRM, Hubspot creates a new row on the sheet with 3 pieces of data from the deal. Due to Hubspot's recommended best practices for working with Google Sheets integration, I have another sheet where I reference data from the sheet that receives the data. The problem arose when I realized that the reference sheet would not automatically refresh when new data was written to the synced sheet. So, I created a macro that copies the formula down using the fill handle every 5 minutes. This rescans the synced sheet and writes any new data to the reference sheet. This morning I woke up and there was some new data that should have been copied over to the reference sheet -- however it wasn't. I checked that the macro is running every 5 minutes, and it is. For the hell of it, I went to the menu and manually ran the macro and, to my surprise, it actually worked! I want this to be fully automated though and don't want to have to manually run a macro everytime I want the data to get copied over.
Data gets synced here
Data is referenced here
Macro Code:
/** #OnlyCurrentDoc */
function RefreshData() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('A75').activate();
spreadsheet.getActiveRange().autoFill(spreadsheet.getRange('A75:A223'), SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);
spreadsheet.getRange('B75').activate();
spreadsheet.getActiveRange().autoFill(spreadsheet.getRange('B75:B234'), SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);
spreadsheet.getRange('C75').activate();
spreadsheet.getActiveRange().autoFill(spreadsheet.getRange('C75:C232'), SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);
spreadsheet.getRange('C75:C232').activate();
};
The problem is that your macro, doesn't work in the time-driven triggers context. The following "macro" is able to be called by a time-driven trigger:
function RefreshDataByTimeDrivenTrigger() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('A75:A223')
.setValue(spreadsheet.getRange('A75').getValue());
spreadsheet.getRange('B75:B234')
.setValue(spreadsheet.getRange('B75').getValue());
spreadsheet.getRange('C75:C232')
.setValue(spreadsheet.getRange('C75').getValue());
};
Note:
/** #OnlyCurrentDoc */ was not included in the above code because it applies to the whole project.
I'm intentional using setValue instead of setValues as the same value should be added to all the cells from the specified range.
There are some methods that only works in certain contexts, i.e. SpreadsheetApp.getUi() works then called from a custom menu, but doesn't work when called from a time-driven trigger. The same happens with Range.activate(). Unfortunately the macro recorder adds a lot of Range.activate() and Spreadsheet.getActiveRange() methods and it's not smart enough yet to optimize the recorded user actions by itself, so, in order to make your macro to work when it's called by a time-driven trigger you have to adapt your code:
Remove statements like spreadsheet.getRange('A75').activate();.
Modify statements like spreadsheet.getActiveRange() to use statements like spreadsheet.getRange('A75').
If you are also interested in making your "macro" faster, you might also would like to replace patterns like
spreadsheet.getRange('A75').activate();
spreadsheet.getActiveRange().autoFill(spreadsheet.getRange('A75:A223'), SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);
by equivalent code that make fewer calls to Google Apps Script methods.
Related
Google sheets macro won't run on trigger
Try it this way:
function RefreshData() {
var ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("SheetName");
sh.getRange('A75').autoFill(sh.getRange('A75:A223'), SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);
sh.getRange('B75').autoFill(sh.getRange('B75:B234'), SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);
sh.getRange('C75').autoFill(sh.getRange('C75:C232'), SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);
}

On cell selection

I am learning to use google app script. I have written code to get row number in which so far I succeeded but can't find a way to assign it to a cell or row change event trigger. Can someone help me figure out how to do this?
My code is as follows :
function onChange(event) {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var currentCell = sheet.getCurrentCell();
sheet.getRange("B1").setValue(currentCell.getRow());
}
There are no "onSelect" trigger on Google Apps Script but you could use the poll technique. Basically, you will have to use a sidebar to hold client-side code that will check for the selected cell every determined time. For code examples checkout the following Q/A
How do I make a Sidebar display values from cells?
How to detect user changing sheet?
Have you installed the trigger? onChange triggers need to be explicitly hooked up because they're considered installable triggers (opposed to simple triggers, which just require saving the .gs file).
You can manage your triggers from the Menu in your Apps Script Editor:

Setting a trigger on a programmatically created Google spreadsheet

I am building a Google sheets platform where I make a new spreadsheet for a new user by copying a template spreadsheet. Because of a potential large amount of users, I need to be able to do this programmatically.
Part of the template is an onEdit trigger. So far I have not found a way to copy this trigger to the new spreadsheet. I have tried by using ScriptApp.newTrigger as shown below:
var newss = playertemplate.copy(playerid + '. ' + playername).getId()
var newsheet = SpreadsheetApp.openById(newss).getSheetByName('Sheet1')
var newfile = DriveApp.getFileById(newss)
newfile.setSharing(DriveApp.Access.ANYONE_WITH_LINK, DriveApp.Permission.EDIT)
ScriptApp.newTrigger("submitBets").forSpreadsheet(newss).onEdit().create()
But the result is that the new trigger is created both on the "master" spreadsheet from which the above script is run, and on the new spreadsheet. I have found that this works for up to 20 new users, after which I run into the limit of the number of bound triggers on the master spreadsheet. When I remove the trigger on the master spreadsheet, it is removed on the new one as well.
I have found some old similar questions but none of them were solved, so I'm hoping a solution was developed in the past few years or someone found a workaround in the meantime.

Google Script - onEdit(e) not triggering

I have a google sheet with some script running behind it. I've had to separate some of the tabs out to individual workbooks, and have been updating the script accordingly. One of the functions I had was an onEdit(e) trigger, that was no longer running in the new workbook. As part of my testing, I've simplified it to just:
function onEdit(e) {
Logger.log("TEST");
}
No matter the changes I make in the sheet this is attached to, the Logger.log never writes.
I've done some research, especially into the simple trigger restrictions, and one of those relates to openByURL, which I am using elsewhere in the script.
var otherBook = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/etcetc/edit');
Even though the onEdit(e) doesn't directly relate, is the presence of the openByUrl within the script what is preventing the onEdit(e) from running? If so, are there ways to get around that, so that I can trigger actions based on an edit, but also be able to pull data from an alternate workbook?
I inserted the following into a new script and the onEdit(e) worked without an issue. To call functions from onEdit that are restricted for simple triggers, install the trigger instead and set it to fire on spreadsheet edit.
function onEdit(e) {
Logger.log("TEST2");
}
function test() {
var otherBook = SpreadsheetApp.openByUrl('https://docs.google.com/spreadsheets/d/etcetc/edit');
}
Regarding the Logger, can you try:
Logger.log(["TEST"]); instead of Logger.log("TEST");
Your login line does not work for me either but works with the brackets.

How to create time based triggers in Multiple Google Sheets

I would like to install a time based trigger on multiple Google Sheets using Google Apps Scripts and can't figure out how to do so. I know these can be added through the UI but I was hoping to find a programmatic way to do this. I have tried this code:
function initializeTrigger(sheetID){
var sheet = SpreadsheetApp.openById(sheetID);
ScriptApp.newTrigger('myLibrary.myFunction')
.forSpreadsheet(sheet)
.timeBased()
.atHour(9)
.everyDays(1)
.create();
}
function installMultipleTriggers(){
var sheetList = [sheetID1, sheetID2, sheetID3];
for (var i = 0; i < sheetList.length; i++)
{
initializeTrigger(sheetList[i]);
}
}
But when I run this I receive the error:
TypeError: Cannot find function timeBased in object SpreadsheetTriggerBuilder.
Which makes sense I guess, because according to the documentation, the SpreadsheetTriggerBuilder class doesn't have a method named timeBased()... Does anyone know how to add time-based triggers to multiple Google Sheets?
A time based trigger is independent of a sheet based trigger. Sheet based triggers respond to events that occur on the sheet, for example if you edit a cell.
I would eliminate the forSpreadsheet call in your code snippet, that should resolve your issue.
Create Spreadsheet Triggers Programatically
So I guess the issue here is that you wish to tie the triggers to a spreadsheet. I believe that only way to do that is to create the triggers from a project that is contained by the spreadsheet and you can just use ClockTriggerBuilder.