Showing progress in Google scripts - javascript

I want to show progress of a lengthy script to the user. Ideally I want to use the yellow toast that comes up saying running script cancel dismiss when running a Google script
I know u can throw custom error but how can throw custom messages to this yellow box.
Or another alternative will do as well. Not msgbox as that stops the script.

I ended up using the spreadsheet class of toast:
SpreadsheetApp.getActiveSpreadsheet().toast('message')

I would think htmlService would work for you:
function function1() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheets()[0];
var htmlApp = HtmlService
.createHtmlOutput('Your Message')
.setTitle("Progress")
.setWidth(750)
.setHeight(220);
SpreadsheetApp.getActiveSpreadsheet().show(htmlApp);
}

Related

Trigger script when only certain sheets are activated

I have several sheets that begin with "Agent Report" followed by the name, like this: "Agent Report - John", "Agent Report - Adam", etc. I have a script that reads the name of the agent from a specific cell and retrieves the data from another spreadsheet for that person. I want to trigger the script when a sheet that begins with "Agent Report" is activated, so that when I move between the sheets, the sheet data are updated for each person in "Agent Report" sheets. So far I have this:
function onOpen(e) {
makeMenu();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sname = ss.getActiveSheet().getName();
if(sname.indexOf("Agent Report")>-1){
master();
}
}
Agent Report is not the first sheet, so the script correctly makes a custom menu (makeMenu) when I open the spreadsheet, but does not get triggered (master) when I switch to an "Agent Report" sheet. When I run the script manually from an "Agent Report" sheet, it runs fine.
My question is: Can I create a trigger that will run the script when I switch to a sheet with the name that begins with "Agent Report"? onOpen() doesn't seem to fit for that purpose.
If such a trigger is not possible, can there be a workaround - a loop that would go over every sheet, check the name and if it contains "Agent Report", run the script. Something like that:
function onOpen(e) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var numberOfSheets = ss.getSheets().length;
for (var i = 0; i<=numberOfSheets; i ++) {
if(SOMETHING HERE.indexOf("Agent Report")[i] > -1){
master();
}
}
}
Issue:
According to the official documentation:
The onOpen(e) trigger runs automatically when a user opens a
spreadsheet, document, presentation, or form that they have permission
to edit.
The problem with this approach is that onOpen is executed only the time you open the spreadsheet file. Therefore, even if you switch between sheets or do any other operations, the script won't be executed, unless you refresh/open the spreadsheet file again. In other words, onOpen will only be executed for the sheet that you open the first time.
Solution 1:
To execute a code when switching between different sheets you can use onSelectionChange(e):
function onSelectionChange(e) {
makeMenu();
const as = e.source.getActiveSheet();
if (as.getName().indexOf("Agent Report")>-1){
master();
}
}
I don't recommend you to choose this approach because every time you make a selection change in the script, the code will be executed.
Solution 2 (recommended):
As you also proposed, to control when you want to execute the script I would advice you to use a regular function that iterates over all sheets and checks if the sheet name matches the criterion. Add also onOpen to execute makeMenu():
function allSheets(){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
sheets.forEach(sh=>{
if(sh.getName().indexOf("Agent Report")>-1){
master();
}});
}
function onOpen() {
makeMenu();
}
You can execute this regular function in many different ways:
script editor
create a custom menu and execute it from the spreadsheet file
create an icon button within your spreadsheet file
create a time-driven trigger to execute on a particular time
Bonus information:
In both approaches, you can replace
if(as.getName().indexOf("Agent Report")>-1)
with
if(as.getName().includes("Agent Report"))
which does exactly the same thing, but it is more eye-friendly.
Related Issue:
As also pointed out by Iamblichus, an onSheetChange trigger function has already been requested by the community and it is reported in the IssueTracker. Go ahead and click on the star (★) button to the top left of the webpage to increase the chances of this feature to be implemented in the future.
The final solution was to use installable trigger (not a simple trigger, this is why the script did not run onOpen) with the following script:
function allSheets() {
makeMenu();
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheets = ss.getSheets();
sheets.forEach(sh=>{
SpreadsheetApp.setActiveSheet(sh);
if (sh.getName().includes("Agent Report")) {
master();
}
})
SpreadsheetApp.setActiveSheet(sheets[0]);
}
Thank you #Marios for all the helpful tips.

setValue() or setFormula() with complex formulas/"You do not have permission to call setFormula"

So I keep getting this error message in my spreadsheet when I try to run my code in google script:
You do not have permission to call setFormula.
I tried with both setValue() and setFormula() and the error is the same. I saw somewhere that setFormula() only works with simple formulas (ex. A2*B2/C2).
This is a simple function to concat a hyperlink to the content of the selected cell and forma a hyperlink sintax.
function HIPERLINK() {
var ws = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var cell = ws.getActiveCell();
var auto = cell.getValue();
var link = '=HIPERLINK("https://projudi.tjpr.jus.br/projudi/processo/buscaProcesso.do?actionType=pesquisaSimples&-H&Host:&projudi.tjpr.jus.br&-H&User-Agent:&Mozilla/5.0&(Windows&NT&6.3;&WOW64;&rv:49.0)&Gecko/20100101&Firefox/49.0&-H&Accept:&text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&-H&Accept-Language:&pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3&--compressed&-H&Referer:&https://projudi.tjpr.jus.br/projudi/processo/buscaProcesso.do?actionType=iniciarSimples&-H&Cookie:&projudiContCookie=0;&JSESSIONID=053165f8dd5f8532c326f3eb06d7;&projudi-route=4;&dtLatC=54;&dtPC=-;&dtCookie=49542FA50EF89B032E8685F08394F120|UHJvanVkaSstK0V4dGVybm98MQ&-H&Connection:&keep-alive&-H&Upgrade-Insecure-Requests:&1&--data&page=1&flagNumeroUnico=true&flagNumeroFisicoAntigo=false&numeroProcesso='
+auto+'";"'+auto+'")';
cell.setFormula(link);
}
If anyone knows a way to do this without the error message, thanks.
I tried this way and it worked for me without issues:
function setCustomLink(){
var ss = SpreadsheetApp.getActive().getActiveSheet();
var cell = ss.getActiveCell();
var cellValue = cell.getValue();
cell.setValue("https://projudi.tjpr.jus.br/projudi/processo/buscaProcesso.do?actionType=pesquisaSimples&-H&Host:&projudi.tjpr.jus.br&-H&User-Agent:&Mozilla/5.0&(Windows&NT&6.3;&WOW64;&rv:49.0)&Gecko/20100101&Firefox/49.0&-H&Accept:&text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8&-H&Accept-Language:&pt-BR,pt;q=0.8,en-US;q=0.5,en;q=0.3&--compressed&-H&Referer:&https://projudi.tjpr.jus.br/projudi/processo/buscaProcesso.do?actionType=iniciarSimples&-H&Cookie:&projudiContCookie=0;&JSESSIONID=053165f8dd5f8532c326f3eb06d7;&projudi-route=4;&dtLatC=54;&dtPC=-;&dtCookie=49542FA50EF89B032E8685F08394F120|UHJvanVkaSstK0V4dGVybm98MQ&-H&Connection:&keep-alive&-H&Upgrade-Insecure-Requests:&1&--data&page=1&flagNumeroUnico=true&flagNumeroFisicoAntigo=false&numeroProcesso=" + cellValue + ";" + cellValue);
}
Let me know if you get different result.
Tip:
you can create a button and assign setCustomLink function to it, and when you need reformatting just click the button.
Here is the link how to accomplish this: Clickable images and drawings in Google Sheets.

Google Scripts Trigger not firing

I'm struggling to get my script to auto-run at 6AM (ish). I have the trigger set up to run this script, "Time-Driven", on a "day timer" between "6-7 am". I'm getting no failure notifications (set up to email to me immediately), but the script isn't running. It works exactly as I want it to when I manually run it, but the whole point was to automate it, so I'm not sure what I am doing wrong here. I looked up other instances, and they seem to have been fixed by deleting and re-adding the triggers, but that doesn't solve the issue for me. Is it something in my script preventing an auto-run?
function getMessagesWithLabel() {
var destArray = new Array();
var label= GmailApp.getUserLabelByName('Personal/Testing');
var threads = label.getThreads(0,2);
for(var n in threads){
var msg = threads[n].getMessages();
var body = msg[0].getPlainBody();
var destArrayRow = new Array();
destArrayRow.push('thread has '+threads[n].getMessageCount()+' messages');
for(var m in msg){
destArrayRow.push(msg[m].getPlainBody());
}
destArray.push(destArrayRow);
}
Logger.log(destArray);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sh = ss.getActiveSheet();
if(ss.getLastRow()==0){sh.getRange(2,1).setValue('getMessagesWithLabel() RESULTS')};
sh.getRange(2,1,destArray.length,destArray[0].length).setValues(destArray);
}
I'm not 100% sure, but the reason for this could be that during a trigger there's no "ActiveSpreadsheet" if the script isnt directly linked to spreadsheet (As the spreadsheet is closed). So you should try using:
var ss = SpreadsheetApp.openById(id); // id is the id of the spreadsheet
// https://docs.google.com/spreadsheets/d/id_is_here/
var sh = ss.getSheetByName(name); // name of the actual sheet ("Sheet 1" for example)
Otherwise i see nothing wrong with your code (other than you using label.getThreads(0,2) which sets the maximum number of threads to be brought in to 2, but i assume that's intentional)
Also, you're setting 2,1 instead of what i assume needs to be 1,1 in
if(ss.getLastRow()==0){sh.getRange(2,1).setValue('getMessagesWithLabel() RESULTS')};
The problem is due to the use of getActiveSheet as it retrieves the sheet displayed on the UI but when your time-driven trigger runs there isn't a sheet displayed on the UI.
Replace getActiveSheet by getSheetByName or better get the sheet by it's ID (for details see Get Google Sheet by ID?)
Reference:
https://developers.google.com/apps-script/reference/spreadsheet/spreadsheet-app#getactivesheet

Access from Google sheets to Google drive

I have a simple function that creates a folder on google drive. I want to transfer the name to it and run it from the Sheets. But I'm denied access. How to solve this problem without triggers? Thank you
function myFunction() {
var folderName = "SEO";
var folder=DriveApp.getFoldersByName(folderName).next();
var fileName = "NewFolder";
var file=SpreadsheetApp.create(fileName);
var copyFile=DriveApp.getFileById(file.getId());
folder.addFile(copyFile);
DriveApp.getRootFolder().removeFile(copyFile);}
Result:
enter image description here
From Google Apps Script documentation:
If your custom function throws the error message "You do not have permission to call X service.", the service requires user authorization and thus cannot be used in a custom function.
The solution is to create a custom menu for your spreadsheet and execute your function upon clicking on the menu item.
function onOpen(){
var ui = SpreadsheetApp.getUi();
ui.createMenu('Menu')
.addItem('Menu item', 'yourFunc')
.addToUi();
}
function yourFunc(){
//your code
}
Hope this is helpful.

Google Scripts: accessing spreadsheet files, TypeError: Cannot call method "openById" of null. (line 2, file "Code") Dismiss

The code:
function myFunction() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().openById('https://docs.google.com/a/e4b.us/spreadsheets/d/1DBty8ZiTqZ8MHPkFipjL8wDZqR2Ae9PLrNAQtW2QD2k/edit#gid=0');
var ss = SpreadsheetApp.getActive();
var mylocationInfo = ss.getRange("A2:B4").getValues();
logger.log(mylocationInfo.getData)
}
I thought that maybe removing non-essential aspects of the url, like the /edit#gid=0, would help. It didn't.
Here's evidence that the URL is indeed valid:
EDIT I've tried it without the entire URL, just using the actual ID and I receive the same message.
EDIT I removed the function ".getActiveSpreadSheet" and get the error "Bad Value"
I tried changing getById to getByUrl, inputing the full URL, and i get the error message that the file with the ID is missing. As was shown by the screenshot, the file exists. The url was copy-pasted immediately before executing the script.
changed:3:07pm
EDIT I tried linking to a different spreadsheet using getByUrl and got the same error message. Changed 3:10pm
Why does getById return Null?
Why can't getByUrl find my files?
You are using: getActiveSpreadsheet() and openById() at the same time. That's a conflict. You need to use one or the other.
Your code:
var sheet = SpreadsheetApp.getActiveSpreadsheet()
.openById('https://docs.google.com/a/e4b.us/spreadsheets/d/Your ID/edit#gid=0');
var ss = SpreadsheetApp.getActive();
Plus you aren't using the ID, you are using the URL. If you want to get a reference to the file by URL, use the method: openByUrl()
The code should look like this:
var ss = SpreadsheetApp.openById('Your ID');
var sheet = ss.getActiveSheet();
The variable name ss stands for spread sheet. That's the entire spreadsheet file. sheet is one sheet tab inside the spreadsheet.

Categories