Fixed
Status Update
Comments
ph...@gmail.com <ph...@gmail.com> #2
For the avoidance of doubt, if I create a function
function myFunction() {
Library.libFunction1();
}
and then run myFunction, that works fine.
function myFunction() {
Library.libFunction1();
}
and then run myFunction, that works fine.
jk...@google.com <jk...@google.com>
yu...@gmail.com <yu...@gmail.com> #3
Yes, libFunction1 - library function should be called directly from the menu, not from the upper level script. Currently it works in next way:
-----------LIB-----------
function libMenu() {
var mySheet = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [ {name: "libFunction1", functionName: "Library.libFunction1"},
{name: "libFunction2", functionName: "libFunction1"}
];
mySheet.addMenu("Library Functions", menuEntries);
}
-----------LIB-----------
-----------CLIENT-----------
function onOpen() {
Library.libMenu();
}
function libFunction1() {
Library.libFunction1();
}
-----------CLIENT-----------
but client script should contain only onOpen function.
-----------LIB-----------
function libMenu() {
var mySheet = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [ {name: "libFunction1", functionName: "Library.libFunction1"},
{name: "libFunction2", functionName: "libFunction1"}
];
mySheet.addMenu("Library Functions", menuEntries);
}
-----------LIB-----------
-----------CLIENT-----------
function onOpen() {
Library.libMenu();
}
function libFunction1() {
Library.libFunction1();
}
-----------CLIENT-----------
but client script should contain only onOpen function.
yu...@gmail.com <yu...@gmail.com> #4
[Comment deleted]
yu...@gmail.com <yu...@gmail.com> #5
When you plan to fix it? It's very important issue. Thanks.
[Deleted User] <[Deleted User]> #6
This is a big inconvenience, especially when you deploy a library that create a menu Ui. Would be great if this could be fixed. Regards,
mc...@gmail.com <mc...@gmail.com> #7
Please fix!
m....@ciid.dk <m....@ciid.dk> #8
Yes, a big inconvenience. One way to circumvent it could be to call a master libfuntion in the client, with a parameter:
function libFunction1(menuitem) {
Library.libFunction1(menuitem);
}
but... menuitems do not accept parameters.
So, my second choice will be to populate my client script (which should ideally only contain onOpen) with a number of "generic" menu function triggers, some of them just sitting there, ready for future expansions, hopefully enough so that I will never have to alter the client script when i expand the library with more menu items, and at the same time not having misleading names (not descriptive either, unfortunately):
function libFunction1() {
Library.libFunction1();
}
function libFunction2() {
Library.libFunction2();
}
...
function libFunction20() {
Library.libFunction20();
}
function libFunction1(menuitem) {
Library.libFunction1(menuitem);
}
but... menuitems do not accept parameters.
So, my second choice will be to populate my client script (which should ideally only contain onOpen) with a number of "generic" menu function triggers, some of them just sitting there, ready for future expansions, hopefully enough so that I will never have to alter the client script when i expand the library with more menu items, and at the same time not having misleading names (not descriptive either, unfortunately):
function libFunction1() {
Library.libFunction1();
}
function libFunction2() {
Library.libFunction2();
}
...
function libFunction20() {
Library.libFunction20();
}
co...@gmail.com <co...@gmail.com> #9
Instead of passing a functionName, why not passing the function itself?
e.g.,
-----------LIB-----------
function libMenu() {
var mySheet = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [ {name: "menuItem1", handler: menuItem1},
{name: "libFunction2", handler: function() {menuItem2(3);}}
];
mySheet.addMenu("Library Functions", menuEntries);
}
function menuItem1() {
}
function menuItem2(someArg) {
}
-----------LIB-----------
-----------CLIENT-----------
function onOpen() {
Library.libMenu();
}
-----------CLIENT-----------
e.g.,
-----------LIB-----------
function libMenu() {
var mySheet = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [ {name: "menuItem1", handler: menuItem1},
{name: "libFunction2", handler: function() {menuItem2(3);}}
];
mySheet.addMenu("Library Functions", menuEntries);
}
function menuItem1() {
}
function menuItem2(someArg) {
}
-----------LIB-----------
-----------CLIENT-----------
function onOpen() {
Library.libMenu();
}
-----------CLIENT-----------
gr...@gmail.com <gr...@gmail.com> #10
Without this feature, libraries are really nobbled!
+1 for passing the function itself!
+1 for passing the function itself!
am...@gmail.com <am...@gmail.com> #12
Please Fix it.
an...@gmail.com <an...@gmail.com> #13
I actually thought cooledco's suggestion was a current solution to the problem, but alas it is just a suggestion to how a possible solution might be implemented.
+1 for the idea though. This passing of function "names" seems very old skool!?
+1 for the idea though. This passing of function "names" seems very old skool!?
sl...@gmail.com <sl...@gmail.com> #14
I just ran into this as I'm upgrading a script used by many spreadsheets (that I don't necessarily have access to).
What I'm planning is this:
1. Create a new Upgrade menu
2. Upgrade menu item will run onEdit with no argument
3. onEdit calls library's onEdit
4. Library's onEdit, when it sees no argument passed to it will know the user is trying to upgrade and offer instructions to copy and paste new code.
4. New code will contain lots of generic function names for the future to avoid this happening again as longer as possible.
What I'm planning is this:
1. Create a new Upgrade menu
2. Upgrade menu item will run onEdit with no argument
3. onEdit calls library's onEdit
4. Library's onEdit, when it sees no argument passed to it will know the user is trying to upgrade and offer instructions to copy and paste new code.
4. New code will contain lots of generic function names for the future to avoid this happening again as longer as possible.
ma...@gmail.com <ma...@gmail.com> #16
A year later and this has been ignored?? What is the point of having a global library if you have to write a freaking wrapper for it each time?! The mind boggles. Please fix this, it should be callable from both the spreadsheet cells AND any buttons (images -> via assign script) on the spreadsheet that has the library included.
fa...@kettering.edu <fa...@kettering.edu> #17
I, too, have been forced to constantly edit my client scripts any time I want to make changes to the Library. I came across this post as I was looking for a solution, but it looks like there really is no convenient solution at the moment. That would be very nice if there were.
+1 for calling a library function directly from the menu
+1 for calling a library function directly from the menu
[Deleted User] <[Deleted User]> #18
to me works SpreadsheetApp.getUi().createMenu('MenuName').addItem('ItemName', 'Library.libFunction1').addToUi();
jo...@google.com <jo...@google.com> #19
Here is a workaround that allows you to call any library function if you paste in this one generic wrapper function. Then you can call this from the spreadsheet.
For example, if I had a library called MyLib with a function add(x, y) (pretend x is in cell A1 and y is in cell A2) I could call it like this:
=LIB_FUNC("MyLib", "add", A1, A2).
It's a little ugly but at least allows me to only have to paste this one function and then access any library function. Note that this depends on undocumented structure of the "this" object that is in scope when calling the wrapper function. Small chance this could break over time. Might see if I can publish this as an add on.
function LIB_FUNC(libraryName, functionName) {
var result;
var lib = this[libraryName];
var extraArgs = [];
if (lib) {
var func = lib[functionName];
if (func) {
if (arguments.length > 2) {
extraArgs = Array.apply(null, arguments).slice(2);
}
result = func.apply(this, extraArgs);
} else {
throw "No such function: " + functionName;
}
} else {
throw "No such library: " + libraryName;
}
return result;
}
For example, if I had a library called MyLib with a function add(x, y) (pretend x is in cell A1 and y is in cell A2) I could call it like this:
=LIB_FUNC("MyLib", "add", A1, A2).
It's a little ugly but at least allows me to only have to paste this one function and then access any library function. Note that this depends on undocumented structure of the "this" object that is in scope when calling the wrapper function. Small chance this could break over time. Might see if I can publish this as an add on.
function LIB_FUNC(libraryName, functionName) {
var result;
var lib = this[libraryName];
var extraArgs = [];
if (lib) {
var func = lib[functionName];
if (func) {
if (arguments.length > 2) {
extraArgs = Array.apply(null, arguments).slice(2);
}
result = func.apply(this, extraArgs);
} else {
throw "No such function: " + functionName;
}
} else {
throw "No such library: " + libraryName;
}
return result;
}
na...@gmail.com <na...@gmail.com> #20
Just in case people are still looking for solutions.
function TESTF() {
return myLib.TESTF.apply(null,arguments);
}
Can be applied in a for loop for every method on myLib.. I use this in all of my scripts so I just have a 5 line script in the document, add the library, and walah, the library is directly part of this script as if I was "using namespace myLib;"
[edit] Also, this means that spreadsheets can call those functions as well as if they were actually written in this script.
Hope it helps.
function TESTF() {
return myLib.TESTF.apply(null,arguments);
}
Can be applied in a for loop for every method on myLib.. I use this in all of my scripts so I just have a 5 line script in the document, add the library, and walah, the library is directly part of this script as if I was "using namespace myLib;"
[edit] Also, this means that spreadsheets can call those functions as well as if they were actually written in this script.
Hope it helps.
mo...@hotmail.com <mo...@hotmail.com> #21
Comment 20 explanation is a little opaque to me. Can anyone elaborate?
Seems silly that library functions aren't exposed to the documents once included. Makes them somewhat pointless if a wrapper must be included in every document, or unless #20 is on to something with a generic 5 line wrapper.
Seems silly that library functions aren't exposed to the documents once included. Makes them somewhat pointless if a wrapper must be included in every document, or unless #20 is on to something with a generic 5 line wrapper.
fi...@gmail.com <fi...@gmail.com> #22
I am also interested in a deeper explanation of comment #20
I understand she/he meants using a loop to navigate all methods in library, in order to easily define a new function inside the sheet-bounded-script for each library method.
But, how can we loop every method on the library? And how can we define a new function inside that loop, which takes its name from the library?
I understand she/he meants using a loop to navigate all methods in library, in order to easily define a new function inside the sheet-bounded-script for each library method.
But, how can we loop every method on the library? And how can we define a new function inside that loop, which takes its name from the library?
ju...@gmail.com <ju...@gmail.com> #23
same here, please explain if possible !
jb...@google.com <jb...@google.com> #24
As far as I can tell, calling library functions from menus as in SpreadsheetApp.getUi().createMenu('MenuName').addItem('ItemName', 'Library.libFunction1').addToUi() has been supported since 2013. I don't see any additional work that needs to be done here.
is...@moreycorp.com <is...@moreycorp.com> #25
Judging by the comments in the thread, I believe the expectation is that functions in a Library could be called from not only a menu item, but also from the Sheet's own script, and even directly from a formula entered in a cell, just like any other function local to the Sheet's script would be called, only difference being that the referred function would be in the Library.
Description
However, it appears that it is not possible to call a Library function from a spreadsheet menu.
What steps will reproduce the problem?
Create a function in a shared library
- Library name "Library"
- function name "libFunction1"
Create a menu in a spreadsheet:
function libMenu() {
var mySheet = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [ {name: "libFunction1", functionName: "Library.libFunction1"},
{name: "libFunction2", functionName: "libFunction1"}
];
mySheet.addMenu("Library Functions", menuEntries);
}
The menu is created but when I select option 1 I get
Script function Library.libFunction1 could not be found
when I select option 2 I get
Script function libFunction1 could not be found
So how can I call library functions from a spreadsheet menu ?
On which browser & OS?
Chrome, W7
Please provide any additional information below.