Logger.getLog() is not working: Google Apps Scripts - google-apps-script

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.

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.

Inserting sleep inside a particular function in Google Sheets Script

I'm trying to pull data out of an API from a third party and inserting into Google Sheets. However this third party only allows 3 requests per minute, so I'm trying to use a Utilities.sleep feature inside the function I'm building for this request.
My sheet looks like this:
It has the two inputs necessary for the function I'm using (this below):
function GET_DETAILS_RECEITA(CNPJ,sleep_seconds) {
Utilities.sleep(sleep_seconds*1000);
var fields = 'nome,fantasia,email,telefone';
var baseUrl = 'https://www.receitaws.com.br/v1/cnpj/';
var queryUrl = baseUrl + CNPJ;
if (CNPJ == '') {
return 'Give me CNPJ...';
}
var response = UrlFetchApp.fetch(queryUrl);
var json = response.getContentText();
var place = JSON.parse(json);
return [[ place.nome,
place.fantasia,
place.telefone,
place.email,
]];
}
Technically it should work but for some reason I'm getting a return only in the first one.
The error I'm getting is very generic "Erro: Erro interno ao executar a função personalizada." (something like "Error: Internal error in the execution of personalized function").
Any ideas?
From https://developers.google.com/apps-script/guides/sheets/functions
A custom function call must return within 30 seconds. If it does not, the cell will display an error: Internal error executing the custom function.
Considering the above, it's not a good idea to use sleep on a custom function that will be used as intended by the OP. Instead use a custom menu or the Script Editor to execute a script.
In order to minimize changes to your function, you could use a function that read/write the values to the spreadsheet and pass the required arguments to GET_DETAILS_RECEITA
I would consider using something like this in a dialog. You can pass an extra parameter in the set interval as long as your using Chrome.
<script>
var CNPJ='what ever';
window.onload=function(){setInterval(getDetails,25000,CNPJ);}
function getDetails(CNPJ){
google.script.run.GET_DETAILS_RECEITA(CNPJ)
}
</script>
And if you want a callback then use with withSuccessHandler();

Google Scripts Sheets hide/ unhide

In writing a 'custom function' Google Script for my particular sheet, I simply want to hide a column:
function hideColumn(index) {
// get active spreadsheet
var ss = SpreadsheetApp.getActiveSpreadsheet();
// get first sheet
var sheet = ss.getSheets()[0];
sheet.hideColumns(index);
}
This code works fine when I run it from within the Script editor but if I try to run it from inside a cell "=hideColumn(2)", I get the following error:
"You do not have permission to call hideColumns (line 48)."
From the same sheet/ script I'm able to run other custom functions such as:
function metersToMiles(meters) {
if (typeof meters != 'number') {
return null;
}
return meters / 1000 * 0.621371;
}
This seems to be some issue with the hideColumns function being run from inside a sheet? (ie. custom function?)
Your script 'hideColumn' is not a custom function, but a 'normal script'. Also it does not return anything (whereas the second function does). Only custom functions can be entered like formulas in the spreadsheet. See here for more info. My advice would be to create an extra menu-item using an onOpen trigger so you can run the function from the (spreadsheet)menu.
Hope that helps ?

Google Apps Script Execution Order

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.

Google Docs Custom Refresh Script

I'm trying to write a script that allows me to execute commands as soon as Google finishes making calculations (i.e. I'm trying to add to a script to Google docs that imitates some VBA "Calculate" functionalities).
The script is conceived to work by converting a range into a string and looking for the substring "Loading..." (or "#VALUE!" or "#N/A") in that string. The "while" loop is supposed to sleep until the unwanted substrings are no longer found in the string.
I'm using the following spreadsheet as a sandbox, and the code seems to work okay in the sandbox just searching for "Loading...":
https://docs.google.com/spreadsheet/ccc?key=0AkK50_KKCI_pdHJvQXdnTmpiOWM4Rk5PV2k5OUNudVE#gid=0
In other contexts, however, I have cells whose values may return as "#VALUE!" or "#N/A" for reasons other than the fact that Google is still loading/thinking/calculating. What's the way around this?
function onEdit() {
Refresh();
};
function Refresh () {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var sheet2 = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet2");
// set the range wherever you want to make sure loading is done
var range = sheet.getRange('A:A')
var values = range.getValues();
var string = values.toString();
var loading = "Loading";
do
{
var randomWait = Math.floor(Math.random()*100+50);
Utilities.sleep(randomWait);
}
while (string.search(loading) ==! null);
range.copyTo(sheet2.getRange('A1'), {contentsOnly:true});
customMsgBox();
};
function customMsgBox() {
Browser.msgBox("Data refreshed.");
};
rather than using a while loop to "sleep" you should add an event handler to your document which captures the update/refresh event and then runs whatever math/processing you need.
Here's a good place to start reading about events: https://developers.google.com/apps-script/understanding_events
but if you search the api documents for eventhandler you can get some example code fast...