I have a system (I'm the only user of this system, and that's not expected to change, ever) in which spreadsheets are copied from a template file. This template has a script, which populates a few menus to perform some operations. So each new copy of the template spreadsheet has its own copy of the script. The problem with this is that every time a new spreadsheet is used, the user (me) has to authorize the execution of the script. This didn't use to be that bad, but the authorization process has recently become way more annoying (see for example https://developers.google.com/apps-script/images/unverified-app-ui.gif). Given that I'm the only user of these spreadsheets, I think this process is unnecessary and wish to get around it.
I have tried to get around this by extracting the code into a standalone script file and publishing as an add on (https://developers.google.com/apps-script/quickstart/docs) but actually publishing it requires me to pay 5 dollars, and I think this is ridiculous given that I am the only user.
Any other ideas?
Thanks in advance.
AFAIK, that's the intended behavior. Check guide to the authorization lifecycle for add-ons.
Add-on automatically runs its onOpen(e) function to add menu items when a document opens — but to protect users' data, Apps Script restricts what the onOpen(e) function can do.
Note that only published add-ons can be in AuthMode.NONE.
The concept of authorization modes applies to all Apps Script executions.
Related
I have a shared Google Sheet which is an Installation Schedule for a small company. Each sheet is a week. I've created script actions that do things like look for data changes, and if appropriate, hide and unhide rows. This works for everyone that the spreadsheet is shared with, with no prompting for permission.
The function to create a new weeks is executing by clicking on a entry in a Custom Menu. It then prompts the user for the date of the first week and the number of weeks to create. After some user entry error checking, it copies a hidden template sheet to a sheet named after the week's date range, updates a date entry cell, copies sheet protections and then unhides the newly copied sheet. This works for me as the sheet owner, however, it is creating authentication dialogs for any other user to which the sheet has been shared.
I could get around this by deploying this as a test app in the Google Cloud Platform interfaces, but then I would have to specifically share it with the users, which a) are not part of a Google Workspace and b) are likely to change, therefore requiring on-going maintenance.
Given that the script is modifying "my" sheets file, I don't understand why permission would be needed and am hopeful there is a way around this.
I have searched for and tried many possibilities, but none seem to solve the problem.
Anyone have any expertise? I am a competent coder, but relatively new to Google Apps, so please be as detailed as possible.
Functions called from Google Workspace editor custom menus executes under the active user. If the function use any method that requires authorization to run it will show the OAuth consent screen for your script.
Unfortunately there is no way to avoid this. Even making calls to APIs through UrlFechApp by passing the appropriate credentials, in this case to call the Google Sheets API, it will be required authorization of the active user for https://www.googleapis.com/auth/script.external_request.
The option to use the custom menu to open a dialog or sidebar to run client side code will also require the user to authorize the script.
Considering the above iF you really want to avoid to ask the user to authorize anything, forget about using custom menus. You might consider to use installable triggers, i.e. use edit / change installable triggers to call functions when edit is made like clicking a checkbox or selective a value from a data validation dropdown.
Related
https://developers.google.com/apps-script/guides/sheets
I have been searching for a solution to a Sheet Protection issue, I have a Sheet that includes automated scripts to write data into the Sheet below from some fields at the top. I want the user to be able to provide the data in the fields at the top and then to run a script that adds the data below. The script to add the data works fine for the owner of the sheet if Protection is enabled, but fails for any user that has Edit rights as the Protection cannot be cleared by script for the data to be written to the bottom of the sheet.
https://developers.googleblog.com/2015/02/control-protected-ranges-and-sheets-in.html
I found this code from a Google blog post a few years ago and have tried variations without success....is this type of approach just not possible with Google Sheets and Google Script ?
Unfortunately, that is not currently possible to run a bound script as the owner without using a workaround. Scripts can only be run as the owner when they use Triggers or when you make a standalone Script Web App. You can see this for more information.
This should bypass fooling around with scripting protection ranges!
The Workaround!
There is a way you can get around this by creating a web app so that your bound script talks to the web app which runs on the spreadsheet. See this answer for more information.
So the process looks like this: User clicks a button that runs a function on a bound script. This function makes a web call to a web app that can run a function as the person who created the script.
I would also recommend you pay attention to a comment by Augustine C:
...you may also find it helpful to have a shared secret key saved in your spreadsheet and then verify it using the backend webapp script, or to perhaps verify that the recipient of the email is, in fact, also an editor of your Google Sheet.
How can I allow users with permissions of "View Only" the ability to execute an apps script in a spreadsheet?
I've created a custom menu choice triggered by onOpen() that launches the script fine for anyone with edit permissions. However, onOpen() does not run for anyone with only view/comment permissions (consistent with the documentation) and thus the menu is not created and there is no way to launch the script.
Ideally, I would like view only users to view and execute the script, but not modify it.
If executing the script results in modifying any content of the sheet then I think it's reasonable to expect only those users with edit rights will be able to run the script. In view of this I am not sure I understand the question at all.
Ideally, I would like view only users to view and execute the script, but not modify it.
Simple triggers and installable triggers that are able to use SpreadsheetApp.getUi like onOpen and onEdit are executed only for users with edit permissions.
Instead of using a custom menu you could add a link to script published as web app allowed to be accessed by anyone and run. The link could be added to a cell or to an image.
Related
Threads with answers with score > 0
Google App Script - allowing access for anonymous users
Threads with one answer with 0 score
Extend Google Spreadsheets UI with a Google Web App
Google Spreadsheet - Custom menu won't load because onOpen won't fire
I just spend a few days on this and don't believe you can! In order to let an anonymous user execute a web app google app script, you have to set it to "Anyone on the internet with this link can edit" in the app script sharing options. Plus you have to make the sheets the script touches editable by anyone. Plus you have to deploy it as executed by you and everyone has access.
No sir, I don't like it. The app script should be executable without being editable. Google's choice makes no sense, especially considering how difficult they've made it to share content with anonymous users. You'd think they would allow an execute privilege without a modify privilege. (Are opinions allowed in answers?)
I wrote a script in GSheets we use at my work that uses custom menus. Because everyone is set to "Can view" on the template, they are forced to make a copy as to not affect the template.
The downside of that is each spreadsheet will require authorization to run every single time the form is sent in and the menus need to be used which makes the process more cumbersome. Is there a way I can provide authorization to run the code, whether it be through an onOpen trigger or some other means?
The code includes moving sheets into folders, extracting data to a central spreadsheet, and sending emails. The email does not need to come from the user, it can be sent as a no-reply/anonymous user if that helps.
I have created a standalone Apps Script from Google Drive, but when I try to access it from a Google Spreadsheet, I don't see a way to access the script (even though when I created the script, I created it as a spreadsheet script).
In the spreadsheet, the "Tools->Script manager..." menu item doesn't show my script, nor does the "Tools->Script editor...". The latter has a section for 'recent projects', but it doesn't list my newly created script, nor its associated project.
If I create a new script from inside the spreadsheet (i.e .Tools->Script editor...) and cut and paste the code from the standalone script, it works fine. However, this can only be used in the single spreadsheet -- to use it from another one, I have to cut and paste / go through auth again.
Is there a way to do this without publishing the script to the gallery, which I assume makes it public (I don't have a problem making it public, but it seems like there must be a better way)? The script is here -- it is world readable with the link. It adds a menu to a google spreadsheet that lets you run a query in BigQuery and dumps the results into your spreadsheet.
The behavior you describe is exactly how it is intended to work... the script you wrote can only work if it is bounded to a spreadsheet.
The fact that you wrote it in an independent script makes it indeed a standalone app but it can only be executed from within the script editor and in this context an onOpen function like the one you wrote doesn't make sense (it runs on opening a document/spreadsheet, not the script).
For now a script can only be bounded to a spreadsheet by copy/pasting the code, at least a script that you want to use as you do (with a menu and direct function calls and activeSheet calls), maybe one day Google will expand the concept of libraries to make your script function available from different document directly (read also the doc about libraries).
There are actually 2 types of standalone Apps Scripts, the one you tried that runs only from within the editor and webapps that are deployed and run in a browser window by themselves. The latter are always build around a doGet function that represents an entry point for the application. You should read the documentation on the subject to get all the details.
To summarize : if you want to access your spreadsheet using getActiveSpreadsheet() and similar methods then you have to write (or paste) the script in the script editor bounded to the spreadsheet.
If you want to have a standalone script you can also interact with spreadsheets (and other document as well) but you have to access them by their ID and the spreadsheet will only be viewable from another browser window, without link between them, and there will be no "active spreadsheet" nor "active sheet"...
A webapp can of course also do that with the advantage of a user interface that you can adapt to your needs but this is becoming a bit too far from the scope of your question.
Hoping I've made it (a bit) more clear, at least I tried to make it simple ;-)
I worked this out with Jordan, following the instructions here:
https://developers.google.com/apps-script/guide_libraries
First, he had to share his standalone script with me, so I had read access to it (probably setting the script as public read would work too).
Then he told me his project key.
I took his project key and inserted it in "Find a Library", in the "Manage Libraries" menu.
For this to work, Jordan had to export "a version" of his library - so third parties can rely on stable code and upgrade at their own rhythm.
As Jordan's script runs automatically on onOpen(), my code had to define a function onOpen() that called his script onOpen(). To do this, the library manager gave me an identifier for the imported library.
Sample code once the library is imported and the library manager gives you an identifier for the library:
function onOpen() {
GivenLibraryIdentifier.onOpen();
}
You can also use installable triggers. If you install an installable trigger (such as onOpen) from your standalone script into the document, it gets similar privileges as if it were a simple trigger.
And better yet, when the installable trigger calls its function from your standalone script, it executes WITHIN your standalone script! So it can call any other function in your standalone script. Its Logger.log() entries can even be viewed from your standalone script, even though it was executed from your sheets document.
So basically, if your script installs an onOpen() trigger tied to one of its functions, it's as good as if your Sheets document had required() your whole standalone script file.
(Assuming the owner of the script has edit privileges to the file.)