Google Scripts lets you create custom menus. For example:
function makeMenu(){
var ui = SpreadsheetApp.getUi();
ui.createMenu("Scripts")
.addItem("My Script","myScript")
.addToUi();
This works great if you have only ONE file you want to script.
Let's say, however, you have 50 files that you want to all have the same menu running the same functions.
You can easily update the functions themselves by putting them in a library and having those 50 files reference the library version HEAD:
function myScript(){
MyLibrary.myScript();
}
Now, if you want to update the myScript() function, you simply update it in your library, and the changes propogate.
However, I have two problems:
- The only way I can see to add a NEW menu function to all 50 files is to manually go into each file and add:
function myNewScript(){
MyLibrary.myNewScript();
}
Is there any way to update them all at once?
NOTE: While you could "library out" the "makeMenu" function, and the individual scripts would then have the new menu item, they will error out when the menu function is used, as the menu function will only call the function if it exists within the file itself (as opposed to the library).
- The only way I can see to use versioning with the library (so users can have a stable version while the developer works on the HEAD version) is, again, to manually go through all 50 files and update the library version.
Is there any way to use versioning without having to go into each file and manually update the library version it uses?
I did find this close-but-not-quite answer about dynamically updating menus; however, as far as I can tell, it will only work within a single script, and does not apply to libraries (see my NOTE for #1 above): Update app script executable functions menu as new functions are added
CodePudding user response:
- Create menus from library itself
- Call functions in library from the including script using
libraryIdentifier.libraryFunction
Library file.gs:
function mkMenu(libraryIdentifier="MyLibrary"){
SpreadsheetApp.getActive()
.addMenu('ClickMe!',[{name:'alert!',functionName:`${libraryIdentifier}.alertLib`}])
}
function alertLib() {
SpreadsheetApp.getUi().alert('Library function running!');
}
Including script.gs:
function onOpen(){
//You need to pass a specific library identifier, if it is different from `MyLibrary`
MyLibrary.mkMenu();
};
- Alternatively, Use google-apps-script-api to modify multiple files' scripts, which can also be used to modify the currently available library version in
dependencies:{version:versionNumber,userSymbol:libraryIdentifier}
inappsscript.json
CodePudding user response:
I actually found a simpler way to do this based on TheMaster's answer (thank you!).
I had not thought to simply pass the library reference to Menu.addItem
as part of the function name.
So within the library you have something like:
function makeMenu(){
var ui = SpreadsheetApp.getUi();
ui.createMenu("Scripts")
.addItem("My New Script","Library.myNewScript")
.addToUi();
}
function myNewScript(){
SpreadsheetApp.getUi().alert("Hello world!");
}
And within the file that references the library all you need is:
function onOpen(){
Library.makeMenu();
}
This removes the need to list function myNewScript
within the file's script.
Maybe there is something about TheMaster's answer that makes it more modular that I am not understanding, but based on my current understanding, what I have just described is the simplest way to accomplish what I want.
Thanks again!