Google Apps Script Execution Order - google-apps-script

Having trouble getting GAS to execute functions in the order I need. In this code:
function documentUpload(e) {
var app = UiApp.getActiveApplication();
app.getElementById('documentValue').setText('Uploaded');
app.getElementById('documentValueLabel').setStyleAttribute('color', 'black');
checkSubmit(e);
return app;
}
...it always runs checkSubmit before changing the text. Which is useless because one of the things that checkSubmit checks is whether documentValue has text.
I saw this post and tried adding LockService like so:
function documentUpload(e) {
var app = UiApp.getActiveApplication();
app.getElementById('documentValue').setText('Uploaded');
app.getElementById('documentValueLabel').setStyleAttribute('color', 'black');
var lock = LockService.getPrivateLock();
lock.waitLock(10000);
checkSubmit(e);
lock.releaseLock();
return app;
}
...but I'm not getting any different results. Same thing for Utilities.sleep().
Thanks in advance for any suggestions!

the UI is updated when you return app . That means that any function call from inside your function cannot see the changes you made to your UI from inside the same function.
You'll have to think differently, ie probably split your code in 2 functions to allow to return the app (in other words to update the UI) before calling the function that reads its content.
EDIT : when I look at your code it seems that the only thing you want to do before starting the download is to change a text value and a style attribute... if so you can use a clientHandler that will execute immediately (see this other recent post) maybe this can solve your problem... let us know if it does.

Related

Google Sheets with Google App Script: How to write a 'status' message to the cell before returning the final result?

I have a function that can take a while to return the output. Is there a way to have it print a message in the cell, before overwriting the message with the output a short time later? The function can take 30 seconds to run and it may be used in 20-30 cells, hence it would be nice to see which cell is still calculating and which is done.
function do_calc() {
print("Now doing the calculations...")
// ... (bunch of code here that does the calculations)
return output;
}
I tried to use setvalue() but it says I don't have permission to do that in a custom function.
UPDATE: added picture
screenshot
function myFunction() {
var sheet = SpreadsheetApp.getActiveSheet();
var active_range = sheet.getActiveRange();
sheet.getRange(active_range.getRowIndex(), 10).setValue('Running...');
Utilities.sleep(10000);
return 'Finished';
}
Issues:
Like I said in the comment you can't return twice because the first return statement will cancel out the code that comes after that.
Also set methods (like setValue) are not allowed in custom function as clearly stated in the official documentation.
Solution:
The solution would be to incorporate the built in google sheets formula IFERROR.
=iferror(myFunction(),"Running...")
where myFunction is:
function myFunction() {
try{
// some code that delays
Utilities.sleep(10000);
}
catch(e){
return e.message;
}
return 'Finished';
}
I added a try...catch to make sure you return the error messages that are related to the script. Otherwise, iferror will hide them.
Be careful!
A custom function call must return within 30 seconds. If this time is surpassed then the custom function will return the error:
Exceeded maximum execution time
which will not be shown because you have used iferror which will cover the error.

Logger.getLog() is not working: Google Apps Scripts

I wanted to view my log from the sheet front end, I tried following workaround but it seems getLog() function is not working.
// log adding function
function addLogs()
{
Logger.log("Adding my test log");
}
// log display function
function viewLog()
{
var logs = Logger.getLog(); // issue is here
Browser.msgBox(logs); // gives empty
var htmlOutput = HtmlService
.createHtmlOutput(logs)
.setSandboxMode(HtmlService.SandboxMode.IFRAME).setHeight(500);
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Sheet Log'); // gives empty
}
Try combining your functions together as a nested function. When you run the code, you have added to the log in one function, and called an empty log in the other.
You will either need to add to the log and call it in the same function or nest the functions together so that when you run the topmost function, it runs all processes.
Did you call the function addLogs() at all? It's not going to run on it's own and hence the log will be empty at the beginning. Correct behaviour.

Function in sheet has stopped working recently

I have a function which up until recently was working fine.
function DynamicImportRange(sheet_url, sheet_name, sheet_range) {
var values = SpreadsheetApp.openByUrl(sheet_url).getSheetByName(sheet_name).getRange(sheet_range).getValues();
return values
};
I reference the function in a cell and am now getting the error: "You do not have permission to perform that action." I have authorized the function in the script editor and as I said before it was working fine for a long while up until recently. Any idea what the problem might be?
That is working for me as well. However, if it is not working for you, try doing something like this:
function DynamicImportRange(sheet_id, sheet_name, sheet_range) {
var values = SpreadsheetApp.openById(sheet_id).getSheetByName(sheet_name).getRange(sheet_range).getValues();
return values;
};
The only change I made was that instead of passing sheet_url I'm passing sheet_id and it seems to be working perfectly well.

e.parameter undefined

Q: why is e.parameter.wfId undefined (in the log) after running the script below (as a web-app)
I call script with this URL
https://script.google.com/a/macros/gappspro.com/exec?service=my-webapp-key
without a parameter (&wfId=somecharacters)
function doGet(e) {
var app = UiApp.createApplication().setTitle('Workflow Builder');
var mainGrid = app.createGrid(2,1).setId('FILE_doGet_mainGrid');
app.add(mainGrid);
var wfId = '1234567890' // FILE.doGet.randomString();
mainGrid.setWidget(1,0, app.createTextBox().setValue(wfId).setId('wfId').setName('wfId'));
var handler = app.createServerHandler('func');
handler.addCallbackElement(mainGrid);
Logger.log(e.parameter.wfId);
return app;
}
function func(e) {
return x;
}
I am trying to implement the workflow script from chapter 8 of james ferreira’s book Enterprise Application Essentials and in the add Docs section i ran into the problem that e.parameter.wfId in line “var wfRowArray = FILE.ssOps.getWfRowFromSS(e.parameter.wfId), “ is undefined when running the script. (on page 134 in the book, not the PDF).
In the example above i brought the code back to the essence of what is causing the error,...for me.
e.parameter.wfId is only available in your func(e) function, not in the doGet. the variable e represents the elements of the callBackElement catch by the handler function.
If I have understood your question correctly, this is behaving as expected.
You say "h-ttps://script.google.com/a/macros/gappspro.com/exec?service=my-webapp-key without a parameter (&wfId=somecharacters)"
So, I believe you are not passing any URL parameters to the script URL and therefore you get them as undefined.
If you call your script with the URL parameters, say
h-ttps://script.google.com/a/macros/gappspro.com/exec?service=my-webapp&wfId=somecharacters
then you can expect to see e.parameter.wfld

google apps script - web app doesn't seem to do anything . .

I'm a Java developer but I did a small site for a non-profit group using Google Sites. I have a form I'd like to be somewhat dynamic and Google Apps Script seemed to be a viable option. As frequently happens when one is learning a new technology, I copied and pasted the code below from a tutorial/documentation. I then published it, and inserted the script widget into a page on the site and saved the page. When I reload the page, the "place holder" for the widget is there, but nothing happens - no buttons, no panel, nothing. Same results when I run it from the script editor. I'm sure I'm missing something obvious, but I haven't been able to get the UI to render at all. A little direction would be greatly appreciated.
thanks in advance!
function doGet(e) {
Logger.log("Executing the doGet() method . . .");
var app = UiApp.createApplication();
var aPanelRoot = app.createVerticalPanel();
var button = app.createButton('Click Me');
aPanelRoot.add(button);
var label = app.createLabel('The button was clicked.');
label.setId('statusLabel');
aPanelRoot.add(label);
var handler = app.createServerHandler('myClickHandler');
handler.addCallbackElement(label);
button.addClickHandler(handler);
aPanelRoot.setVisible(true);
return app;
}
function myClickHandler(e) {
var app = UiApp.getActiveApplication();
var label = app.getElementById('statusLabel');
label.setVisible(true);
//app.close();
return app;
}
It seems that you simply forgot to add aPanelRoot to the app in the doGet() function
app.add(aPanelRoot)
also : by default all widgets are visibles so you can remove all the setVisible(true) statements as they are only necessary if you set them to false somewhere else...
And if I may add a last comment, it's generally a good idea to choose the parent widget as callbackElement so you don't risk to forget to add elements when you begin to have lots of them (all children are automatically included in the parent) .