Google Sheets - Script function could not be found - google-apps-script

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.)

Related

How to easily refresh all functions in a google sheets spreadsheet? (like deleting the function and entering it again)

I hope you're well.
I'm using google sheets to help manage some data for my work. One of our programmers wrote a google apps script for me to log into our website, pull the data I need, and then dump it into google sheets. It works well, however sometimes it encounters and error and it fails to log in to our website. (please see the photo below)
Error I encounter
To fix the error, I need to delete the cell's contents, and then enter the function in that cell again. This forces the function to try again from scratch and it will load successfully.
What I cut and paste to fix it
What I need a way to automatically run all the functions again (something functionally the same as deleting it and entering it again manually).
I'm hoping for someway to create a button that I could press which would delete and re-enter the text in the relevant cells, or something like that. However, I would appreciate any solution that anyone can suggest.
I really appreciate it!
-edit: I should also mention that I'm using this function a lot in a large range of spreadsheets and they're all interconnected so when one gets an error, it kills the entire web of documents and I need to root around for which one failed and then copy its contents, delete it, then enter it again.
edit 2: Thank you fir your first response and sorry about posting images of the error I received. You've set me down the right path and I've combined this onEdit function for when I edit single sell to directly replace the text in that cell. When I use "foo" or something like that, it works and replaces the text in that sell with "foo". However, what I really need to replace it with is =ImportJSON("expertList", 1) but when I try i get an error:
Syntax error: SyntaxError: Unexpected identifier line: 341 file: Code.gs
Here's the code in question:
function onEdit(e) {
if (e.range.getA1Notation() === 'A1') {
refresher()
}
}
function refresher() {
var newValue = '=yourfunction()';
var sheetName = "sheet name";
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName);
var range = sheet.getRange("this is the cell you want to re-write");
range.clearContent();
SpreadsheetApp.flush();
range.setValue(newValue);
}
Last Edit:
Thanks for the help! If anyone stumbles on this post in the future, the above code works to delete what's in cell, then enter it again into that same cell (thereby resetting the function)

Looking for an onEdit script that can be used to change the color of a google sheets cell when it is edited?

I am using google sheets to monitor a project that includes multiple users. I would like to use an onEdit command to change a cell's color to yellow when the content is edited. Below is the code that I am working with. However, I am unable to get it to function. Coding is still new to me, so any advice would be greatly appreciated.
function onEdit1(e)
{
var range=e.range;
var column=range.getColumn();
if(column>3 && column<27)
{
range.setBackground('#ffff00')'
}
}
function onEdit(e){
if(e.range.getSheet().getName()!="Sheet1")return;
if(e.range.columnStart>3 && e.range.columnStart<27) {
e.range.setBackground('#ffff00');
}
}
I also added a line to limit it to only one sheet. You may wish to change the name of that sheet or even remove it entirely if you want it to run on your entire spreadsheet.
A lot of new programmers try to run these onEdit(e) functions from the script editor. Unfortunately, that doesn't work because the e parameter is expecting to be populated by the event trigger. Without the event object you'll normally get an error like Cannot read property range from undefined because e has not been populated by the event trigger.
I test them by making sure I'm editing the correct sheet and correct range and I use the e.source.toast() function to provide me with feed back sort of like the console.log() does.
If you want to learn more about the event object then try adding a Logger.log(JSON.stringify(e)); to the first line after the function declaration. And then get it to run by editing the appropriate sheet in the appropriate way and go to view log to see the results.

Autocomplete Not Working - Google App Script

I'm having trouble with the autocomplete feature in Google App Script.
Built-in methods like SpreadsheetApp. will provide an autocomplete menu with methods to choose from.
However, if I create my own child object, autocomplete works for a little while, and then it just stops working.
for example:
var skywardRoster = SpreadsheetApp.getActiveSheet();
skywardRoster. will produce method options for a while, and then it stops.
However, the code still functions, and methods work if I type them out manually, so I know the declarations must be right. The menu simply won't appear, and it's just very inconvenient to have to look up each method individually as I go.
I have tried: breaking the variable and retyping that line; copy and pasting the code back into the editor; using different browsers; copying the gs file itself and working within the copy; and signing out completely and signing back in. Nothing seems to get it back to work.
I'm really new to coding, and I'm not sure what can be causing this.
Does anyone know how to fix this issue?
You might want to check Built-in Google Services:Using autocomplete:
The script editor provides a "content assist" feature, more commonly called "autocomplete," which reveals the global objects as well as methods and enums that are valid in the script's current context. To show autocomplete suggestions, select the menu item Edit > Content assist or press Ctrl+Space. Autocomplete suggestions also appear automatically whenever you type a period after a global object, enum, or method call that returns an Apps Script class. For example:
If you click on a blank line in the script editor and activate autocomplete, you will see a list of the global objects.
If you type the full name of a global object or select one from autocomplete, then type . (a period), you will see all methods and enums for that class.
If you type a few characters and activate autocomplete, you will see all valid suggestions that begin with those characters.
Since this was the first result on google for a non-working google script autocompletion, I will post my solution here as it maybe helps someone in the future.
The autocompletion stopped working for me when I assigned a value to a variable for a second time.
Example:
var cell = tableRow.appendTableCell();
...
cell = tableRow.appendTableCell();
So maybe create a new variable for the second assignment just during the implementation so that autocompletion works correctly. When you are done with the implementation you can replace it with the original variable.
Example:
var cell = tableRow.appendTableCell();
...
var replaceMeCell = tableRow.appendTableCell(); // new variable during the implementation
And when the implementation is done:
var cell = tableRow.appendTableCell();
...
cell = tableRow.appendTableCell(); // replace the newly created variable with the original one when you are done
Hope this helps!
I was looking for a way how to improve Google Apps Script development experience. Sometimes autocomplete misses context. For example for Google Spreadsheet trigger event parameters. I solved the problem by using clasp and #ts-check.
clasp allows to edit sources in VS Code on local machine. It can pull and push Google Apps Script code. Here is an article how to try it.
When you move to VS Code and setup environment you can add //#ts-check in the beginning of the JavaScript file to help autocomplete with the special instructions. Here is the instructions set.
My trigger example looks like this (notice autocompletion works only in VS Code, Google Apps Script cloud editor doesn't understand #ts-check instruction):
//#ts-check
/**
* #param {GoogleAppsScript.Events.SheetsOnEdit} e
*/
function onEditTrigger(e) {
var spreadsheet = e.source;
var activeSheet = spreadsheet.getActiveSheet();
Logger.log(e.value);
}
I agree, Google Script's autocomplete feature is pretty poor comparing with most of other implementations. However the lack is uderstandable in most cases and sometimes the function can be preserved.
Loosing context
The autocomplete is limited to Google objects (Spreasheets, Files, etc.). When working with them you get autocomplete hints, unless you pass such object instance to function as an argument. The context is lost then and the editor will not give you suggestions inside the called function. That is because js doesn't have type control.
You can pass an id into the function instead of the object (not File instance but fileId) and get the instance inside of the function but in most cases such operation will slow the script.
Better solution by Cameron Roberts
Cameron Roberts came with something what could be Goole's intence or a kind of hack, don't know. At the beginning of a function assign an proper object instance to parameter wariable and comment it to block:
function logFileChange(sheet, fileId){
/*
sheet = SpreadsheetApp.getActiveSheet();
*/
sheet.appendRow([fileId]); // auto completion works here
}
Auto completion preserved

ALL Custom Functions return "unknown function" in one spreadsheet, but work in others

I have a few Simple Custom Functions that I use all the time. I have recently run into a spreadsheet that I desperately need to use them in, but when I try to use even the most basic custom functions, I get "#NAME?" with a hover text of "unknown function".
Even deleting all other code, and trying just this simple function, doesn't seem to work:
function double(d) {
return 2*d;
}
When I duplicate the spreadsheet, the code that comes with it DOES work.
A few Notes:
This is a Google Apps for Enterprise account.
I was originally not the owner on this spreadsheet, but have since become the owner, thinking that this might be the cause.
The spreadsheet originally had protected regions, which have since been removed, thinking that this might be the cause.
This spreadsheet is shared with hundreds of people, so I really want to find the root cause and fix it.
Any thoughts?
Way too late for the OP, but in case this helps someone else:
I had a similar issue where my spreadsheet suddenly stopped recognising custom functions that have been working for months. No code changes have been made recently and the spreadsheet hadn't even been edited since it last worked. When I went to Tools > Script editor it still showed the code with the custom functions.
Reloading the page and closing and reopening didn't fix it. I added a simple parameterless wrapper function to call the custom function with some appropriate arguments.
I then ran this wrapper function in the debugger with a breakpoint in the original custom function. When it hit this, I switched back to the spreadsheet and it could magically see the custom functions again.
If you already published as Add-on, then you need to do reactivate the addon for copied sheet with the following steps:
Click the menu Add-ons / YOUR-ADD-ON-NAME / Help / View in store,
click Manage and in the dropdown menu uncheck then check the 'Use in this document' again for the addon to be loaded to the current sheet.
I can not explain the exact cause, but here is a SOLUTION:
copy the expression written in the cell
delete the content of the cell
re-enter the expression in the cell!
Again, late in the thread, but it was the only thread I found on this --
My function had been running well, too and suddenly returned Unknown Function.
I found that the signature had changed - initially, I had a few parameters I was sending in and the cell returning the error still had parameters in the function call. The function hadn't used parameters for a long time. I removed the parameters and Voila! Apparently, something changed where it started enforcing call patterns...
When you have custom functions on a sheet - they areBOUND to that sheet. So it does work when you duplicate the sheet itself , but it does not automatically become a global or domain wide custom function.
The only way use it else where without actually publishing it as an add-on is to go to the tools menu, click on script editor and actually copy the code from the script bound to that sheet that it works with, then paste it in the script editor of the sheet you want to use it in.
I faced the same problems. I here document, what worked for me.
To create a new custom function, I did the following:
In spreadsheet: Menu -> Tools -> Script Editor
Wrote the function in Script Editor
In spreadsheet: Menu -> Tools -> Import -> Clicked "Add Function" next to the custom function name.
In spreadsheet: In a cell, I did =CustomFunctionName()
This worked.
Now, when I wanted to reuse the same in another spreadsheet, there are 2 ways to do that.
Make Copy of the sheet in which the custom function is written.
Make library of custom functions and reuse them in other sheets, by writing custom functions specific for a particular sheet.
#1 Make Copy of the sheet in which the custom function is written.
In this way, the whole custom function code gets duplicated. So, if any changes needs to be done in the custom function, the change must be done in all the copied files.
Also, once the sheet is copied, the custom function does not simply works. I had to delete the cells & reenter the function names again, to get them working.
#2 Make library of custom functions and reuse them in other sheets, by writing custom functions specific for a particular sheet.
This is better, because, the core logic will stay in one place. Only wrapper functions will be written for each sheet, in which the custom functions are used.
To create a library:
Write the function in Script Editor
Click on "Deploy -> New Deployment"
"Select Type -> Library"
Provide a description, if you want to and click "Deploy" & "Done"
Click on the "Project Settings" on the left menu & copy the "Script Id"(to use the library)
To use a library:
Goto the spreadsheet where you want the library to be used.
Menu -> Tools -> Script Editor
In Script Editor: Click + button next to the Library section on the left.
Enter the "Script Id" & Click on "Look Up".
You will see the script details. Then click on the "Add" button.
Remember the "Identifier" field value. Using that, the functions of the library can be accessed.
Now, in the Script Editor, you can call the library functions with the identifier name. See examples below.
Library Code:
function SheetName() {
return SpreadsheetApp.getActiveSpreadsheet().getName();
}
function SayHello(name) {
return 'Hello ${name}';
}
Let's say, while including this library into a spreadsheet, I entered the identifier as utility. So, in the script editor, I would write like this:
function SheetName() {
return utility.SheetName();
}
How to update a library and use the updated code in spreadsheets?
To update a library:
Make the changes in the library project.
Click on "Deploy -> Manage Deployments".
Select the correct deployment from the left side.
Click on the edit button(on top left).
Select "New Version" in the "Version" input.
Click "Deploy" & make note of the new version number displayed.
To use the updated library:
Goto the spreadsheet in which the library is already being used & open the Script Editor in there.
If the Script Editor of that sheet is already open, reload the page once.
Click on the library name in the Library section(on the left).
Select the latest version number on the Version input & click "Save".
Now, you can call the new functions in the same way you did previously & the existing functions will work in the new way(if there are any changes to the existing functions).
If "copy expression -> delete cell contents -> exit cell -> re-enter expression" fixes your problem, then the easiest way to implement it en masse is to select all faulty cells, hit backspace to delete their contents, and then undo the deletion.
Doing so will force reevaluation of affected cells which bypasses the cache.
I faced exactly the same problem ! My code worked well and was properly linked to the correct spreadsheet. Unfortunately deleting the content of the cell didn't work for me.
Another solution I found is to simply rename the function.
For example:
"myFunction" renamed as "my_Function" and it worked for me ! I guess maybe it's due to an important amount of calls (over 35 000 in my case). Maybe it makes it run into an error or something.
Cheers !
I created a copy of my sheet as a backup and closed up for the night. I came back in the morning with the functions unable to be called. So I did the usual, cut the function from the cell and pasted it right back. This usually fixed things. Not this time.
Tried reopening browser, tried re-logging in. Nothing worked.
Than I simply renamed the function in the Project Editor (appended "call" in front of the function name) and edited the sheet to match. It just worked.
When writing the functions, the comment section was not done properly. Here was what I wrote initially:
/*
A custom function that converts US Dollars to SwissFrancs
#param {number} dollars The total number of dollars
#return {number} swissFrancs The total number of SwissFrancs
#customfunction
*/
Upon inspection of the comments, I found out that I used the comment notation wrongly. I ought to have placed an asterisk just after the opening comment tag /* and on every newline in the comments place an asterisk sign and finally place another asterisk sign before the closing multiline comment tag (*/) like so:
/**
* A custom function that converts US Dollars to SwissFrancs
*
* #param {number} dollars The total number of dollars
* #return {number} swissFrancs The total number of SwissFrancs
*
* #customfunction
**/
One last thing, don't forget to add the #customfunction in the comment section.
As per the documentation by Google, it is important to add the comments before the custom function. Otherwise the function won't appear in the autocomplete popup.
/**
* Multiplies the input value by 2.
*
* #param {number} input The value to multiply.
* #return The input multiplied by 2.
* #customfunction
*/
function DOUBLE(input) {
return input * 2;
}
I've solved as follows
#1. Created 2 instances of the same funcion:
/**
* Multiplies the input value by 2.
*
* #param {number} input The value to multiply.
* #return The input multiplied by 2.
* #customfunction
*/
function DOUBLE(input) {
return input * 2;
}
/**
* Multiplies the input value by 2.
*
* #param {number} input The value to multiply.
* #return The input multiplied by 2.
* #customfunction
*/
function DOUBLE2(input) {
return DOUBLE(input);
}
The second instance returns the result of the first one
#2. Created a function to fix the issue:
function updateFormulas_() {
var f = SpreadsheetApp.getActive();
var r = f.getActiveRange();
var f1 = 'DOUBLE('; // !! Mind "("
var f2 = 'DOUBLE1(';
var finder1 = r.createTextFinder(f1).matchFormulaText(true);
var found1 = finder1.findNext();
if (found1) {
finder1.replaceAllWith(f2);
}
var finder2 = r.createTextFinder(f2).matchFormulaText(true)
var found2 = finder2.findNext();
if (found2) {
finder2.replaceAllWith(f1);
}
}
Note I've added opening parentheses to my functions in replacements in order not to break the original.
#3. Created onOpen Custom menu
function onOpen() {
createMenu_();
}
function createMenu_() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Dispatch menu')
.addItem('Update Formulas', 'updateFormulas_')
.addToUi();
}
Now if error occurs user can select a range with error and fix it manually.
The other option #3 is to create a time trigger to do this.
Another late entry. This error can also come as a signature violation. This can occur if the type of variable being passed into the custom function is different from what is expected. I was "cleaning up" my spreadsheet and re-formatted some of the entries. This caused a not found. Detecting this error is made easy if you enabled the function for prompting. In my case I started typing the function name and it came up (so Google knew it was there), but when it came to execution I got the error.

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.