I have a Grid panel and RowEditing Plugin. I search how to use events when i click on Update Button.
I can display alert() but i don't know how to retrieve updates datas ?!!
${prefix}grid.on('validateedit',onEdit, this);
function onEdit(e) {
alert('UPDATE');
};
I have just one line on my Gridpanel. I need to retrieve all data to updating it :)!
Thanks :)
In your onEdit function, you receive the edit object (e), and you can access everything you need to from here.
For example, if I want to access the store... I can do so from within the onEdit function like
var store = e.grid.store;
Related
I have a .tsv file from a tool and I have to import it the Google Sheet (nearly) real-time for reports. This is my code for importing:
function importBigTSV(url) {return Utilities.parseCsv(UrlFetchApp.fetch(url).getContentText(),'\t');}
It worked till some days ago when Error messages keep saying "Exceeded maximum execution time (line 0)."
Could anyone help? Thank you a lot!
Issue:
As #TheMaster said, custom functions have a hard limit of 30 seconds, which your function is most probably reaching. Regular Apps Script executions have a much more generous time limit (6 or 30 minutes, depending on your account), so you should modify your function accordingly.
Differences between functions:
In order to transform your function, you have to take into account these basic differences:
You cannot pass parameters to a function called by a Menu or a button. Because of this, you have to find another way to specify the URL to fetch.
Values returned by a regular function don't get automatically written to the sheet. You have to use a writing method (like setValues, or appendRow) to do that.
A non-custom function is not called in any particular cell, so you have to specify where do you want to write the values to.
Since, from what I understand, you are always fetching the same URL, you can specify that URL just by hardcoding it into your function.
Solution:
The function below, for example, will write the parsed output to the range that is currently selected (at the moment of triggering the function). You could as well provide a default range to write the output to, using getRange:
function importBigTSV() {
var url = "{url-to-fetch}";
var range = SpreadsheetApp.getActiveRange();
try {
var output = Utilities.parseCsv(UrlFetchApp.fetch(url).getContentText(),'\t');
var outputRange = range.offset(0, 0, output.length, output[0].length);
outputRange.setValues(output);
} catch(err) {
console.log(err);
}
}
If the URL can change, I'd suggest you to have a list of URLs to fetch, and, before triggering the function, select the desired URL, and use getActiveRange in order to get this URL.
Attaching function to Menu:
In any case, once you have written your function, you have to attach this function somehow, so that it can be trigged from the sheet itself. You can either create a custom menu, or insert and image or drawing, and attach the script to it. The referenced links provide clear and concise steps to achieve this.
Reference:
Custom Functions > Return values
Custom Menus in G Suite
I have written a custom google apps script function that is being called by a google sheet. In this function an API is called and the result of this API is being returned so that it gets displayed in the calling cell of the google sheet.
My problem now is that the sheet calls this function everytime I open the document and there are over 80.000 cells with this function.
Is it possible to save the returned value to the cell and don't call the custom function again when an value has been returned? I want the function being called only once per cell, even if I close the document and reopen it. The returned value should be saved until something else is being written into to cell. That would make my sheets document much more usable than the current state.
From the question
Is it possible to save the returned value to the cell and don't call the custom function again when an value has been returned? I want the function being called only once per cell, even if I close the document and reopen it. The returned value should be saved until something else is being written into to cell. That would make my sheets document much more usable than the current state.
By solely using the custom function it's not possible. There isn't a straight forward solution is to achieve this, in order to keep things simple you should look for another way to implement what is being done by the custom funtion.
One option is to use a trigger (including a custom menu / a function assined to a drawing) to check if the cell that should have the value returned by the custom function is empty and in such case fill it with the corresponding value. The best trigger to use will depend on your spreadsheet workflow.
As specified by Ruben this is not possible, with a custom function.
In my particular case I have resorted to using an Apps Script function that is triggered by an edit event of the spreadsheet and verifies if the event is in the column where the function that I want to execute only once should be, later replacement its content with the result of calling the API.
function freezeValue(e) {
var rangeEvent = e.range;
var col = rangeEvent.getColumnIndex();
if (col === 2) { #Verify column of event
var value = rangeEvent.getValue();
/*Call your api*/
result_api = CALL_API(value)
rangeEvent.setValue(result_api);
}
}
Keep in mind that this implementation only works when each of the cells is edited one by one. To do the same with a row or a complete array of elements, you must go through each of the cells and follow the same procedure.
I am currently trying to call a function with an argument in Google app's newTrigger() function.
I have a function called writeToSheet(sheet). Where as I enter the sheet name into the argument and the custom output is written to said sheet. It all works fine, but I would like to pass this into a time driven trigger with different sheets being written to at different times.
So far, entering ScriptApp.newTrigger('writeToSheet("Production Sheet")') within Google's trigger building example doesn't work. How would you go about solving this problem?
So far, I have had to create a function that executes what I need.
function prodSheetUpdate() {
writeToSheets("Production Sheet");
}
Then pass that function in my trigger.
ScriptApp.newTrigger("ProdSheetUpdate")
...
...
It doesn't seem like you can pass an argument in a trigger. If anybody knows otherwise, I am still curious!
you must pass a string to newTrigger
ScriptApp.newTrigger('writeToSheet('+'Production Sheet'+')')
or
var mystring
ScriptApp.newTrigger('writeToSheet('+mystring+')')
I have a script creating buttons in a table.
Each button is assigned to the same callback server function.
My question is how do I know which of these buttons triggered the server call?
Also is there a way of outputting a msgbox from the server script? When I try browser.msgBox, it gives an error saying that msgbox can't be used in this context.
var clientDel = app.createServerHandler("delStudent").addCallbackElement(grid);
table.setWidget(t, 4, app.createButton("Delete", clientDel).setId("del1"));
function delStudent(e){
var app = UiApp.getActiveApplication();
e.
return app;
}
Thanks,
C Singh.
simply e.parameter.source will return the ID of the widget that originates the handler function
You can use a label or a textBox that you create in your UI and set invisible. Then at any moment you can use getElementById(label_ID').setVisible(true) and put any text in it.
If you want it to appear at a specific position above all other widgets you can do that quite simply using setStyleAttributes, see this other post(server version) for further info and practical example
I have a Google spreadsheet with an onEdit() trigger to create a second time based trigger.
Simply: when the status column is edited to 'Approved' a trigger is created to send a feedback email on a supplied project completion date.
var oneTimeOnly = ScriptApp.newTrigger("emailFeedback").timeBased().at(endDate).create();
I wish to pass a variable to the second trigger. I could create Project Property or add a column in the spreadsheet. However it would be simpler to pass the variable when creating the trigger.
When I insert any additional characters inside the newTrigger quotes this causes the entire contents of the function to be stored in the trigger (which subsequently fails).
var oneTimeOnly = ScriptApp.newTrigger("emailFeedback<strong>(regEmail)</strong>").timeBased().at(endDate).create();
.
Is there a way to store a variable inside the trigger?
Using ScriptDB and new Function(), I was able to create a method for creating dynamic trigger functions.
The gist of the solution is to store the code you want to trigger is the db with the parameters you want to pass:
"myFunction('Hello world')"
Then, when the script starts, as a global variable, you attach newly created functions from your ScriptDB. (I've done this dynamically in my link below.)
globalFunctions.callThisOne = new Function("e", "myFunction("Hello world"));
Finally, when you create your trigger, you created it using the globally accessible function as such:
ScriptApp.newTrigger("globalFunctions.callThisOne").timeBased().everyDay(1).create();
I have written up a short post about this and posted the source. Hopefully it's useful.
You can read more about it here: http://goo.gl/wbUqH6
Or see the code here: http://goo.gl/zjUiYe
Sorry, there is not a way to do this.
As I understand correctly, the question was how to pass data to a time triggered function in a google script project. Eoin described a situation, but you may facing to many.
A classic situation when your script proccesses a complex spreadsheet that may run for long minutes. As you may probably know each script has about 6 minutes runtime limit. This situation you should break your script smaller logical partitions and at the end of each one can create a new trigger for the next part. Okay, but the next part must know about some data of the current running script's variables. Because no way to pass these data via newTrigger() you can create a snapshot and put into the script property context in a serialized way.
An easy way to do by ScriptProperties.setProperty().
Use ScriptProperties.setProperty() to store serialized parameters that can be accessed by trigger method.
#user2166613 is right, but a bit short. Here is how to do it.
I show an example that uses an after() trigger. This is a really interesting use case, as it allows to decouple time consuming tasks from e.g. web app calls, so the calls return control immediately and the processing is done in the background.
In my example I adapt the column widths of a sheet in a function that this run delayed.
// call this function to set a time based trigger and transfer parameters
function setTimeTrigger_AdaptColumnWidths() {
var ssId = SpreadsheetApp.getActiveSpreadsheet().getId();
var wsId = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getSheetId();
var scriptProperties = PropertiesService.getScriptProperties();
scriptProperties.setProperty('spreadsheetId', ssId);
scriptProperties.setProperty('worksheetId', wsId);
// Delay 10 secs, but real execution time may vary up to 15 min!
ScriptApp.newTrigger('adaptColumnWidths').timeBased().after(10000).create();
}
// this function is called by the trigger
function adaptColumnWidths() {
var scriptProperties = PropertiesService.getScriptProperties();
ssId = scriptProperties.getProperty('spreadsheetId');
wsId = scriptProperties.getProperty('worksheetId');
// getSheetById() is a custom function – see below – not yet in Spreadsheet Class!
sheet = getSheetById(SpreadsheetApp.openById(ssId), wsId);
// now do what we want to do in the timeBased trigger
for (var i = 1; i <= sheet.getLastColumn(); i++){
sheet.autoResizeColumn(i);
}
}
// -----
// custom function – hopefully this will become a method of Spreadsheet Class any time soon
function getSheetById(ss, wsId) {
var sheets = ss.getSheets();
for (var i=0; i<sheets.length; i++) {
if (sheets[i].getSheetId() == wsId) return sheets[i];
}
}
Please be aware that your are storing in a dataspace here that is common to all your function calls. So multiple calls in a short time can overwrite each others parameters.
In my use case this is not a problem as the spreadsheet and the worksheet will not change. But do NOT try to transfer data that can change from call to call.
The real moment of execution can vary up to 15 minutes (no matter what exact time you ask for), so there is plenty of room for multiple function calls to interfere with each other!!!