How do I call CreateMenu() from within an Apps Script Library?

Riaz Shageer

I'm building a library within Apps Script and would like to make it pretty self sustaining. Essentially, if someone wants to use this Lib in their Google Sheet, they'd need simply to put in the following code in their Sheets Script

function onOpen(){
  myLib.initialize();
}

And this would set up the sheet as needed. One of the things I do here is to actually add a menu item in the Sheet itself. Therefore, in my Library code, I'll have something like;

function initialize(){
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Custom Menu')
      .addItem('First item', 'someCallback')
      .addToUi();
}

The problem with this approach is that when the menu item is clicked, the "someCallback" function cannot be found. This makes sense since it resides in a separate library. It should be called using dot notation like this: myLib.someCallback

Is there some way that I can get the Library Identifier at run time so that I can create the string required to create the menu?

I can do a few things which are not my first choices such as:

  • pass the "myLib" string to the initialize function
  • type in the "myLib" to the addItem() function directly, but I"m thinking this is not good practice, what if the end user changes the identifier from myLib to something else.

Maybe there's some Runtime way that I can get the Library Identifier?

Rafa Guillermo

Answer:

Unfortunately at the moment this isn't possible to do.

More Information:

I tested out a few things using both the this keyword and the eval() function in order to either dynamically get the redefined identifier of myLib or calling someCallback directly in the initialize function, however even embedding the callback function inside initialize:

funciton initialize() {
  var cb = function someCallback() {
    // do stuff
  };

  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Custom Menu')
      .addItem('First item', 'cb')
      .addToUi();

or:

function initialize() {
  function someCallback() {
    //do stuff
  }
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Custom Menu')
      .addItem('First item', 'someCallback')
      .addToUi();
}

throw the same error with either cb or someCallback not defined.

Problems with this:

To answer your direct question

Maybe there's some Runtime way that I can get the Library Identifier?

The answer is yes. Kind of.

The this keyword is pretty powerful, and at runtime you can use it to get the name of the user-set identifier in the following way:

function onOpen(){
  myLib.initialize(this);
}

And in myLib.initialize():

function initialize(name) {
  console.log(Object.keys(name));
}

The console showing: ['myLib', 'onOpen']

This issue is, is that while the names of imported libraries come before the list of functions defined in the user's script, if more than one library has been imported you have no way of telling which of the keys refers to your library, and which refer to the others. Resultantly just calling name[0] won't cut it.

Doing Some Digging:

I took to Google's Issue Tracker and discovered that there are some feature requests which have very similar use cases to yours:

While the use-cases aren't exactly the same, the underlying issue on both is that anonymous functions nor parameters can be passed to libraries that use the UI methods of Apps Script.

There is also this related feature request which asks to implement a catch-all style method which runs a method if a library method which doesn't exist is called:

What to do:

Normally, I would suggest following the Issue Tracker links and clicking the star. In this case, however, as your use case isn't exactly defined in the scope of the aforelinked feature requests, I would urge you to use this link to file an Apps Script feature request and detail all the information you put here in your question.

As far as workarounds go; the best thing you can do in the meantime is to document that the initialize() function needs to be passed the identifying name of the library. It's not an elegant solution by any standard, but given the complexity of this and the feature requests that are yet to be realised this may be the easiest option.

It might be possible to loop through the Object.keys(this) array but I feel like this is a very hacky workaround which could introduce more problems than necessary (especially if, for example, another library creator also happens to have a function called someCallback...)

I know this is generally bad news, but I hope this is helpful to you!

References:

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

How Do I Use Map Within a Function - Apps Script

How do I add an Apps Script Library to AppMaker?

How do I limit the characters pulled from getBody in apps script

How do I call a function from within a statement in the event listener?

how do i call web service from within a web service

How do I call a function from within a nested function in typescript?

How do I call my function from within my function?

How do I call firebase functions from within a react component

How do I run an r script from within an r script from within power BI?

how do I extract an ip address from within a script

How do I call the functions of the imported library from my function?

How do I get the ResultCode from Exec call on Batch script?

In django, how do I call the subcommand 'syncdb' from the initialization script?

How do I call a python function from a cgi script with javascript?

How do I call a function from a shell script in Docker?

How do I call a function from within a PL/SQL process within Oracle APEX 4.2

How can I set __package__ of a script from within an imported library?

How do I call a method within a setString

How do I call methods within a constructor?

Google Sheet Apps Script: How do I edit the Apps Script below to only copy over data from Column A to L and P to S?

How can I view the source of a google apps script Library

How do I get the directory where a Bash script is located from within the script itself?

How do i use google apps script to modify data that i pull from google analytics?

How to call Google Apps Script encapsulated function from html template

How to call a Cloud Function from Google Apps Script with Authentication?

How to call an API running locally from Apps Script

How do I get 5 rows from the end of my sheet in Google Sheets using Apps Script?

How do I get Google search results from urlfetch in google apps script

How do I extract the text from a docx file using apps-script?