Spreadsheet Editor's Ability to Run Scripts from Library - google-apps-script

I will be maintaining Google spreadsheets for 100 different schools. Each school's spreadsheet will have similar functions (e.g., jumping to a certain cell based on the date or creating a note in a certain cell based on inputted text) and multiple people will have access to edit it (e.g., principal, teachers, coaches, etc). I imagine that creating a library is easiest for this purpose since the functions are the same for each spreadsheet! For example, the script file for each document uses the onOpen() event to call .addMenu(). Then .addMenu calls a wrapper function and this function calls the "jumpToToday" method in my library. (I saw the posts about how the library method cannot be called directly from the menu, so that is why I did it this way). I have two questions:
When I (the owner) share the spreadsheet with an editor, the menu shows up, but when the editor selects one of the menu options, the script returns the error:
You do not have access to library ExternalSupport, used by your script, or it has been deleted.
After I saw this, I shared the library file (Can View) with the spreadsheet editor and then it worked. Do I have to share the library (view only) with ALL editors of the spreadsheet so that they can run the functions? If so, that's fine (I was just trying to avoid it because most principals/teachers/coaches are not techie, so I didn't want to confuse them by sharing a file of code...I just want them to use the spreadsheet).
Because the editors of the spreadsheet will only be able to view the library, it seems like they only have access to the Version that is selected (even if dev mode is on).
When I update my library to another version, do I have to go into the Script Editor of all 100 spreadsheets and then go to Resources > Manage Libraries and update the version? Or is there a way to make all files use the latest version of the library?

1) Yes. According to the documentation
you must grant at least a read-level access to your project for all potential users.
I agree that this may be confusing for other users but at the moment it is necessary.
2) There is no way to make a file use the latest version of a library. Though, there is a way to make a file use the development version of a library. For this to work you need to grant editor-level access to your library to the user. However, bear in mind that any changes that you make to the library will be reflected immediately at the user's end. You can find more information in the documentation.

Related

Can one iterate through bound scripts and edit their manifest files via a script?

I am building an application that will have many users, each of whom will have many Google documents. Each doc will have a custom menu and that custom menu will invoke a library script. I may need or want to change the coding in that library script from time to time.
As changes to a library script must be "saved" as a new version in order for the changed version to be passed on to client scripts (in my case, the scripts bound to Google Docs), I need a way that users can "batch" update the version number in their docs' bound script appsscript.json
file.
I have researched this issue and there seems to be two general alternatives: set the client scripts' library mode to "Developmental" or use an add-on.
The problem with the former is that it won't work unless the users are all granted edit mode access to the library script (which seems particularly a bad idea as the users may well not even be known to me).
The problem with the later is essentially complication and cost. If I make the add-on private, it only works for users in the same domain which means I have to create a G-Suite domain (and pay at least (as of this writing) $72 per year per user—a non-starter for this project).
If I make the add-on public, in addition to the complication, I have to sign up to the Google Cloud Platform and the costs for that require one to navigate a veritable maze of choices and alternatives such that at this point, I really have no idea what the cost per service or user would be.
Below I present some "mock-up" code that should at least indicate the direction I am trying to go.
function upDate() {
var version = 23
var scripts = "https://script.google.com/u/0/home"
//while (scripts.hasNext()) {
//var script = files.next();
//Note: All of the script's have the same name as they commence life bound to a template, which template is duplicated to create the rest of the user's docs
if( scriptName = ScriptName){
//set.dependencies.enabledAdvancedServices[].version
}
}
I don't even know if it's possible to step through bound scripts the way one step's through files in a Google Drive, so that is the first question. Then, the second question is whether, assuming you can step through the scripts one by one, you can change a manifest value—in this case, the version number.
One cannot step through container-bound scripts as they are (no longer) located in one's Google Drive. Moreover, despite Google's documentation about using a "stable" value in the version section of the manifest, that documentation appears erroneous. Finally, one cannot programmatically edit standalone scripts.
However, there is a workaround. What I ended up doing was writing a script that steps through all of the involved Google Docs and copies them to a blank template (i.e., in effect, duplicates them all). That blank template has the bound script installed in it with the new version number of the library. Then, delete original docs (via the same script) and voilà, batch update to all of the target docs is accomplished. (One drawback of this is: if Google Doc revision history is important to you, be advised this gambit jettisons that (unless you keep the original versions).

Google Sheets - Menu Click Function in Library

I have gsheet menu item as follows, where the executing function resides in library "rm".
ui.createMenu('Test').addItem('Test-Lib', 'rm.test');
I have tested this and it works. However, I was not able to find any documentation on this. So my question is; is this a supported feature which I can rely on going forward?
The use case here is: I will be distributing copies of the same gsheet to different clients, so having a single code repository helps updating all clients at the same time. -

Can a library be used to force all copies of a spreadsheet to reference the most current version of a script?

I've created a Google Sheets spreadsheet template with a script that my users can access via a menu option. This "template" is new and undergoes frequent enhancements and bug fixes.
I'd like to find a way to ensure that all copies that are made of the template access the most recent version of the script.
I read this: https://developers.google.com/apps-script/guides/libraries#testAndDebug
...but the first warning at the top of the page says not to use libraries for long-running scripts. Mine takes 3 - 30 minutes to run, depending upon the amount of input data.
If I do use a library, do I have to put it in development mode in order for copies of the template to reference the latest version of the script?
Sorry. I hope this is making sense. I'd appreciate any advice you might have.

Using Google Apps Script Libraries

I have read all Google documentation on managing and creating libraries, yet I still do not know if they are an appropriate option for the problem I am trying to solve.
I know how to save a version of a standalone script. I know how to add the library to a spreadsheet via the script editor. But I don't understand, very simply, how to trigger the library script within the new spreadsheet.
I have a spreadsheet that serves as an often-copied template within my organization. The template contains a script that (onOpen) accesses data on a separate spreadsheet (a master database) and sets those values on a tab called "admin." The desired result is to have a copy of the master database living within the template sheet (and every subsequent copy of the template sheet). At this point, there are thousands of copies of the template sheet, each running that same script.
Whenever I have to change the script, I have to change it within thousands of sheets. Can I use a library instead? I'd like to be able to create a new version of the script in the library and have all sheets connected to that library experience the change. I understand that the library needs to be in development mode (within each sheet) to do this. I also understand that in order to make this switch, I will probably still have to go into each sheet to add the library. I'm just hoping it will be the last time I have to do such a tedious task.
Any advice or links to solid info is appreciated.
besides making an add-on (already covered in another answer) I will answer your libraries question. They will work for you. What you are missing is the "connect" part.
For this you want to trigger the library code from say, onOpen. The onOpen in the library is not enough and not detected by apps script. Instead each of your spreadsheet's script needs an onOpen(e) which just calls yourlibrary.onOpen(e).
since those "hook" calls rarely change, specially once you stabilize your library api, and using it in "development" mode will let you modify just the library.
whenever one of those hooks needs to change (say a callback from an html GUI needs a new parameter) you need to update all the spreadsheets. to avoid this, make all your callbacks receive a single json object instead of multiple parameters.
Sorry if I am repeating other answers, but I would like to sum up and add something:
You can access your library functions as follows:
From the app using the library you go to the Resources/Libraries. You can see the library name under "Identifier". On the same line where you can select Development mode.
Library name found in resources
Now in your library you have for example a function
function onOpen(e)
{
Browser.msgBox("HELLO!");
}
In the spreadsheet app you wish to access it you use the library name found in the resources, for example "testlibrary"
function onOpen(e)
{
testlibrary.onOpen(e);
}
Now if you have development mode on, the modifications to functions in the library update automatically to your application (spreadsheet) as long as the user using the application has edit access in your library script.
If anyone using your spreadsheet has a restricted access to your library script (meaning only view access) or development selection is off in the application, you have to go to the application's script, Resources/Libraries and select the most recent version of your library to be used in the app everytime you update the library and save a new version of it.
Still, especially if you are using mostly only the onOpen function , I would recommend using the library rather than copy-pasting the function to the script of each spreadsheet, as it is easier to track which scripts are up to date and it is easier to avoid errors and differences between the scripts.
Even in the more restricted case, if you update function in library - as long as you are already calling it in the app - all you have to do is select the new version of the library used.
I hope I had anything to give in this conversation and my language was appropriate, this was my first answer..
A good question Melly. I've been through a bunch of the documentation and some tutorials on this subject but haven't tried adding any libraries yet. My understanding is that once you are connected to a library all you have to do is call the applicable functions. That once a library is connected the functions in the library become an extension of all the other Apps Script classes available in the script editor.

Calling apps script function from drive UI

I just implemented a function which operates on a File object in Google Drive(*). Long story short: the function doSomething(file) { ... } exists (in a standalone Google Apps Script) and is well tested.
I want to call this from the Drive UI, e.g. using context menu -> Open With ... (but really any sensible means would be OK).
Is there a straightforward way to achieve this? I prefer not to go through 'registering an app in the Chrome store' whole shebang when all I need is a glorified macro for myself.
I just finished listening to https://www.youtube.com/watch?v=0HVJMIeb3aE which comes closest so far but it seems to skip the technical details of exactly what I need.
(*) There is a rather frustrating repetitive per-file workflow within my organization whereby one needs to switch all write accesses to read-only, then assign ownership to a given user then change your own rights to read-only.
This can absolutely be done in Apps Script. There is a bit of set-up. That video you posted was the one I used to figure it out. When your app is attached to the drive ui your registered mime-types will have your app in the right-click menu.
I made a barebones framework that is highly commented about this process. It also shows how I handle the cases of being installed from the chrome store and called launched from chrome/chrome app launcher. You can make a copy of it here:
https://script.google.com/d/1nrwcxTjzysJl2DMSNB3BHyYfJLEbm02-ekusjUg4V9abzLZ3R_1Yqctj/edit?usp=sharing
*note: This assumes a bit of apps script familiarity. As the '13 IO videos were my first intro to apps script I'm fairly certain it is not that bad to get going.