Google Spreadsheet - Custom menu won't load because onOpen won't fire - google-apps-script

I'm doing everything as prescribed in the 'Defining Spreadsheet Menus' tutorial. The menu is modified using the onOpen event handler.
I have made this 'Text to Columns' script available publicly in the 'Script Gallery' but I'm concerned that users who download may be confused when it takes a long time for the custom menu to pop up.
Getting the script to load the first time is proving to be a pain. Much of the time the onOpen trigger is missed altogether. It appears that the trigger isn't being set correctly because manually resetting the onOpen trigger will fix it.
For personal use I'd consider this a minor annoyance but for a shared script it becomes a support issue.
Note: Every subsequent load consistently takes about 7 seconds to appear which is OK but far from ideal.
Here's the onOpen handler:
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
menuEntries.push({ name:"Text to columns", functionName:"textToColumns" });
menuEntries.push({ name:"Text to columns (custom separator)", functionName:"textToColumnsCustom" });
menuEntries.push(null);
menuEntries.push({ name:"Columns to Text", functionName:"columnsToText" });
menuEntries.push({ name:"Columns to Text (custom separator)", functionName:"columnsToTextCustom" });
ss.addMenu("Advanced", menuEntries);
}
Note: This was tested on a new (ie empty) spreadsheet with only one user.

i'm not sure but the user have to log in i guess, if not, i've got this problem once and solved it with making tow or more triggers all of them are on open and the same function,however try to get internet speed more than 30KB/s to make sure that the problem is from the code , not from your devices

Related

Google Sheet Error: Service Spreadsheets timed out while accessing document with id

I get this error "Service Spreadsheets timed out while accessing document with id ..." every time I run a very simple code, in which I am basically copying data from one google sheet to another using getValues() and setValues().
I don't think it is because of 5M cells limit, because the same exact function is working perfectly fine in another Google Sheet with even bigger size. So I really don't understand where the problem is.
I have tried to create an empty GS and run the function, so I am only pulling data without any other calculation, but still, it gives me the same error.
Any idea what the reason could be?
Here the code as reference:
function MyFunction(){
var pm_ss_0 = SpreadsheetApp.openById('...');
var pm_tab_0 = pm_ss_0.getSheetByName('...');
var pm_data_0 = pm_tab_0.getDataRange().getValues();
var target_ss_0 = SpreadsheetApp.getActiveSpreadsheet();
var target_tab_0 = target_ss_0.getSheetByName('...');
target_tab_0.clearContents();
var target_data_0 = target_tab_0.getRange(1, 1, pm_data_0.length,
pm_data_0[0].length).setValues(pm_data_0);
}
I solved the issue inserting a flush before and after the line where the error appeared.
SpreadsheetApp.flush();
ss.insertSheet("Report "+fogl.getName(), ss.getNumSheets()); //line with the error in my code
SpreadsheetApp.flush();
This issue has also been reported on Google's Issue tracker
Go there and star the issue so you get the updates on it.
This problem is more random than 95% of the commentary on the Web about it attests to. I just had this happen to me for the first time, and it even affected a Macro that did absolutely nothing but hide the Active Tab. I couldn't do anything with Script Editor.
I tried simply duplicating the document. BION, that was the end of the problem for me. Or at least, so far.

Why is a second taking longer than a second?

I'm trying to create a timer in Google Apps Script, such that when there is a number displayed on a cell, and I start the script, the script will automatically decrement that number once every second, until the value reaches zero.
So I found this answer on a related question, and managed to implement code that does the same thing just fine. My one problem is that the code seems to run slowly - so that a second doesn't actually take a second. At a guess, it's between 1.5 to 2 seconds. This obviously isn't hugely ideal for a timer, and I'm wondering if it's a fixable problem. Is there a code optimization that might make my timer run on time, or something I've not factored in?
Here's a link to a test spreadsheet, with the code in the Script Editor (it's View Only for safety, but the spreadsheet can be copied.) A UI control should initiate the "Start Timer" function if you want to test it.
Here's the full code:
var ss = SpreadsheetApp.getActiveSpreadsheet();
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu("Timer controls")
.addItem("Start Timer", "startTimer")
.addToUi();
}
function startTimer() {
var timer = ss.getRangeByName("Timer");
var timeval = timer.getValue();
while (timeval > 0) {
timeval--;
timer.setValue(timeval);
SpreadsheetApp.flush();
Utilities.sleep(1000);
}
}
Timer
function undertest() {
var start=new Date().getTime();//milliseconds
//all your other code here
Logger.log(Number((new Date().getTime()-start)/1000).toFixed(2));//seconds
}
Tl;Dr There is no fix for your code.
You are missing that there are communications processes between your web browser and Google servers...
and that Google Apps Script methods are slow,
and that editing a cell value triggers the recalculation of the whole spreadsheet.
You should start over and instead of using sever side code and Google Sheets to display a timer, follow the recommendation of Cooper on his answer to the same question of the answer that in linked in the question: Use client-side code.

Google Sheets - Script function could not be found

I am working to link an image in my Google Sheet document to a specific cell in another tab. I'm doing this by building a simple function that will do this. However, when I assign the function and then click on the image, I then get the error "Script function "test" could not be found". When I run the function in the script manager interface, it works fine. It's when I try to actually use it in the sheet with the image.
Function Script:
function test()
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("TX Marketing Data");
sheet.setActiveRange(sheet.getRange("A91"));
};
Steps to recreate:
1) Create image
2) Go to image, right click, go to drop down and select "Assign Script"
3) Enter "test" as the assign script
Remove ";" at the end of your function (after }).
Had a similar problem and just solved it.
When assigning a script function to a button make sure to call the specific function name(i.e. "getWeatherData") and not the App Script name (i.e. "WeatherAPI").
Another thing that can happen is that you have a library that has the same name as the function. For example you have imported a library that to refer to "test" in your code. If you name your function
function test(){
your code
}
Then you will get the same error that you got.
Try reloading the page.
Sounds like a simple 'turn it off and on again' fix but after having the same issue and trying to save a new version, renaming the function, creating new function etc. a page reload was all it took!
I had exactly the same problem. Eventually I found the problem when I looked at the script Function name, which should be Function followed by the name you gave the script when it was created. when creating file names sometimes you are not able to use special characters which is what I had done. Once I gave it a name that had allowable characters there was no problem. In programming when you call a function that does not match the name given to the function or procedure you will end up getting the error function not found.
I had the exact same issue, when I used submitdata , after I changed it to submitData it said it submitdata was deleted. so i put it back to original form and bam!! fixed.
Same issue, but much dumber reason for me.
So, here is my answer: Make sure to hit the "Save" button in Apps Script.
I was so used to all the other google apps automatically saving/syncing I didn't realize that I actually had to hit "Save" on the scripts. I caught it when I noticed the function I was trying to run wasn't appearing in the list of functions to run in Apps Script. Once it hit save, the name of the function appeared in the list AND clicking my button ran it successfully from the sheet.
You should call your function name, not the script itself. If your function is called myFunction() you should write myFunction. And be careful to rename your function to something that isn't already in your library
Ran into the same issue but solved it by renaming it with a prefix, executing it in Sheets and then renaming it back without the prefix.
function calculateSomething() {
return 10;
}
To
function prefixCalculateSomething() {
return 10;
}
Update the Sheet with the new name, it should work now.
Now rename it back.
function calculateSomething() {
return 10;
}
Update the Sheet with the original name, and it should still work.
Maybe a refresh would've worked as well but that's not how I solved it.
I found that I had renamed my Macro, removed spaces, and added Uppercase, but the name in the script function statement didn't match what I could swear I had set in
"Extensions->Macros->Manage Macros".
When I changed the syntax of the image to match the function statement, including case, it worked fine.
(I don't know if spaces work in the name, I originally had them, but remembered that I've had trouble with them in Excel. I removed them at the same time as doing other changes, so I didn't confirm if it was an issue.)

URLfetch in an event failing

I have two combo boxes in cells that are populated by ranges in the sheet. When the first one changes, I build a URL and call:
var resp = UrlFetchApp.fetch(url, {"method": "get","muteHttpExceptions":false});
And it populates a 2nd range which controls the 2nd combo box. This works just fine in debug mode. But my goal is for this to work using the onEdit mode. If the first combo box is changed, the method runs and populates the second. Using this statement:
mydoc.getActiveSheet().getRange(15, 1).setValue("Some debug message");
I have it placed throughout the method to see where it dies. I have a statement right after the UrlFetchApp.fetch() method that never writes, so I know that's where the problem is. Can you make these types of calls during events?
Again, it works just fine running it manually via the script editor, but not when called from onEdit.
I see this question where they do not allow it, but the last comment in the thread said he got it to work by attaching another custom method to onEdit. I call URLFetchApp from another method, but I tried creating a myOnEdit function, and called URLFetchApp from there, but it still fails. Not sure what he meant by manually attaching to the event...
Using a simple trigger:
function onEdit(e) {
var response = UrlFetchApp.fetch('http://www.google.com/');
Logger.log(response.getContentText());
}
I get the following error (View -> Execution transcript):
Execution failed: You do not have permission to call fetch (line 2, file "Code") [0.008 seconds total runtime]
One possible workaround is to create a installable trigger:
function myOnEdit(e) {
var response = UrlFetchApp.fetch('http://www.google.com/');
Logger.log(response.getContentText());
}
/*
In the Spreadsheet, create new trigger:
Run: myOnEdit
Events: From spreadsheet
On edit
*/

function onOpen() is not running

My function includes adding a menu and toast to the document. I have verified that the trigger (onOpen) is set as well. It only works when a user goes into Tools, Script Manager, Run. We have too many users with too many backgrounds to expect then to know how to do this. Why isn't it working? (Using Chrome)
function onOpen()
{
var menus = [{name: "Advance in Workflow", functionName:"sendEmail"}];
SpreadsheetApp.getActiveSpreadsheet().addMenu("Auto Advance FG Workflow", menus);
//sheet.toast(Notify/Remind users);
sheet.toast("While you are here we kindly ask that you do not add, modify or remove any columns.","Welcome - " + username,8);
}
Thanks,
I was having the same issue.
I realized, sometimes Google create some kind of cache of the scripts (I'm used to have a "test" script and I usually alter it's content, and, sometimes, the script runs as if I didn't).
So, what I did that solved the onOpen() not working was changing the function name and ading a trigger manually.
Go to "Resources -> Current script's triggers…"
Choose the function to run on open
It worked like a charm here!
Updated Location Information:
or
Then
This is an old post but I just had this problem and find out why it was not working correctly in my case:
I had, at the top of my script file a variable that required some authorisations and that prevented the script to correctly run. I saw that OP called var username = Session.getActiveUser().getUsername(); (that requires authorisations, and it's may be the cause).
eg:
this code won't work:
function onOpen(){
SpreadsheetApp.getUi()
.createMenu("Exportation")
.addItem("Lancer l'exportation", "exportationMenu")
.addToUi();
}
var stConsCons= SpreadsheetApp.openById(sgcid).getSheetByName("Consultant");
but this one will work:
function onOpen(){
SpreadsheetApp.getUi()
.createMenu("Exportation")
.addItem("Lancer l'exportation", "exportationMenu")
.addToUi();
}
function whatever(){
var stConsCons= SpreadsheetApp.openById(sgcid).getSheetByName("Consultant");
...}
It turns out that you need to add the onOpen(e) function to Triggers!
In my case, onOpen wasn't working because I had a variable, outside of a function, opening a sheet with SpreadsheetApp.openById() rather than SpreadsheetApp.getActiveSpreadsheet(). I guess onOpen doesn't work with openById() even if the sheet you are opening is bound to the script. onOpen() won't work with this kind of a variable outside of a function:
var sheet = SpreadsheetApp.openById("1b_PQD...").getSheetByName("demos")
If your script is bound to the sheet, you can solve this problem by using the getActiveSpreadsheet() function. Otherwise, you can solve it by putting your openById() call into a function.
In my case there was a reference error, that while did not stop the script entirely, it did stop the menu from appearing.
I was only able to detect that error after I run a debug on the script.
It looks like the problem may be that "sheet" isn't defined, which is why the toast is failing.
I know this is a really old question, but for any one finding this now, I may have a solution. The onOpen function often runs with the authorization mode none instead of limited when being used as an event trigger. This may cause errors in things that are related to the specific file or user data. For example:
function onOpen(e) {
SpreadsheetApp.getActivePresentation(); //Will error out if permissions are not set to limited.
SpreadsheetApp.getUi(); //This will always run even if the AuthMode is set to NONE
}
Additionally it is worth noting that if you have any variable used or initialized before onOpen(e), basically any global variables that access sensitive info fail if the AuthMode is set to NONE.
var ss = SpreadsheetApp.getActivePresentation(); //bad
var ss;
...
function init() {
ss = SpreadsheetApp.getActivePresentation(); //good because now that the function is already run we should have full permissions
}
Simple triggers silently fail if they lack permission. I ran into this with an onOpen() in a script that initialized File objects of non-bound files. I moved all File object instantiation to menu functions that do have permission.
In other words, this will not work
function onOpen(e) {
...
let file = DriveApp.getFileById(nonBoundFileId);
...
}
but this will work
function menuFunction() {
...
let file = DriveApp.getFileById(nonBoundFileId);
...
}
because menuFunction can be given permission(s) that simple triggers lack.