How to Test OnOpen() menu populate in Apps Script Sheets Add On? - google-apps-script

For months I'm trying, without success, to submit my Google Sheets Add-On to be available at Google Workspace Marketplace. On the last tentatives I'm receiving this message:
The App doesn’t meet the publishing review criteria on the following:
Menu - Menu options not shown after App is installed. Please ensure that the add-on correctly uses onInstall() and onOpen() to populate its menu. The menu items populate when the add-on is first installed and when a different file is opened. See Editor add-on authorization.
My question is: How can I simulate the installation by myself in order to detect what function or variable is causing the problem?
I already try to avoid declaring Global variables, tried zillions of different ways to populate the menu, but it seems that nothing work. The documentation of Google Apps Script is too generic, the people at GWM doesn't show what error is happening. I really doesn't know what can I do.
How can I avoid a situation that I cannot replicate?
If I just have access to the my own add on GWM page to test it.
Sometimes I ask myself if Google is interested in have third party add on. It's so hard to have information.
Any help will be welcomed.
This is my initialization routine right now:
var ui = function(){
return SpreadsheetApp.getUi()}
/**
* #OnlyCurrentDoc
* ver: https://developers.google.com/apps-script/guides/services/authorization
*/
// The onOpen function is executed automatically every time a Spreadsheet is loaded
function onOpen(e) {
ui().createAddonMenu()
.addItem('Importar fontes', 'ExtrairComentarios')
.addSeparator()
.addItem('Relação de fatores', 'doFactors')
.addItem('Análise simples', 'doTable')
.addItem('Georreferenciamento', 'doMap')
.addSeparator()
.addItem('Gera matriz multimodal', 'GeraMatrizMM')
.addItem('Análise multimodal', 'doMultimodal')
.addItem('Gráfico multimodal', 'doGet')
.addItem('Gráfico multifatorial', 'doMultifatorial')
.addSeparator()
.addItem('Tutorial', 'openTutorial')
.addSeparator()
.addItem('Versão atual', 'DoVersaoAtual')
.addItem('Start!', 'DoStart')
.addToUi();
// Script external request
//eval(UrlFetchApp.fetch("https://cdnjs.cloudflare.com/ajax/libs/alasql/0.6.2/alasql.min.js").getContentText())
}
/**
* The event handler triggered when installing the add-on.
* #param {Event} e The onInstall event.
*/
function onInstall(e) {
onOpen(e);
}
P.S. Believed me, I already spend months trying to solve this.

Google recently released a way to test Editor add-ons and updated the docs. See https://developers.google.com/apps-script/add-ons/how-tos/testing-editor-addons
Now it's possible to create a test deployment for Editor add-ons. Please checkout the details on the previous link.
If you have a Google Workspace account, an alternative might be to publish the add-on for internal use only for testing purposes. Once you have it working you might make a copy to publish publicly, and keep the internal use only for testing future changes.
To prevent having problems use the simple onOpen trigger only to show the custom menu. If you want that the add-on does something else on open, do that using an installable trigger, this imply to add a way for the end-user to create this trigger, i.e. include a option on the custom menu for that.

Related

GAS Add-on, onOpen function running continuously?

I have two Google Sheets add-ons that I have written for private use by users in my domain. Both add-ons use the onOpen function to generate a menu in Sheets. Both are written with the standard format provided in the Google Developers documentation. An example of the code for the menu is below. Note that no triggers are installed in any portion of my script.
function onOpen(e) {
var ui = SpreadsheetApp.getUi();
ui.createAddonMenu()
.addItem('1️⃣ Authorize', 'authFunction')
.addItem('2️⃣ Format Sheet', 'ResetDataHTML')
.addSubMenu(ui.createMenu('3️⃣ Type & Clean Up')
.addItem('🅰️ Set Trip type', 'setTripType')
.addItem('🅱️ Remove & Set Count', 'deleteNoTrans'))
.addItem('4️⃣ 📧 Email to Transportation', 'emailSheetNote')
.addToUi();
return;
}
The add-ons both function properly. The "problem" I am noticing is when viewing the Execution Logs in the new IDE. For one add-on the onOpen function is constantly running/completing at an interval of about 1-3 seconds. The other add-on seems to run the onOpen function at intervals of about 20-30 minutes. My question is, "why would these add-ons continue to run the onOpen function? Am I noticing normal behavior or is this abnormal? (I have not noticed this behavior with any other script that uses the onOpen function.)
Thank you to anyone that might have some insight as to my issue.
Yes. Every time you or the other users visit or refresh the sheet, it does trigger the onOpen trigger thus possibly showing in your execution logs multiple times. Don't worry about it as that is entirely normal.

SpreadsheetApp.getActive() fails in onOpen trigger in Google Sheets addon

I would like to read the Active spreadsheet and add menu items based on that. Below is the code in OnOpen(e) trigger:
function onOpen(e) {
var sheet = SpreadsheetApp.getActive().getSheetByName(sheetName);
//add menus based on values of sheet
}
I am getting below exception:
[Exception: You do not have permission to perform that action.]
I have gone through the documentation and found that the AuthMode is None in OnOpen trigger which does not allow access to any services that require authorization.
Please suggest if there is any other way to accomplish my task.
Thanks.
It's not possible to access the spreadsheet unless the owner or editor of the spreadsheet uses the add-on in that spreadsheet. As written in the official document,
However, because an editor add-on automatically runs its onOpen(e) function to add menu items when a document opens, the behavior above adds some complexity to Apps Script's authorization rules. After all, users wouldn't be comfortable with an add-on accessing personal data every time they open a document.
The add-on needs to be enabled for the document for the addon to get access to the document. When it's enabled, onOpen() runs in AuthMode.LIMITED, where you get access to the bound document. This "enabled" state is caused by
Getting an add-on from the store while using that document, or
Using a previously installed add-on in that document
In all other cases, add on runs in AuthMode.NONE. In this mode, You are only able to add menu items without access to any data including the bound spreadsheet. Add Menu items to request access to such data. Then, after getting AuthMode.FULL, the rest of the workflow can be done.
References:
The complete lifecycle

When Google document is copied with container-bound script, how to get its installable triggers?

Issue
I have a container-bound script attached to my document.
It has onOpen installable trigger and I need to get the script in newly created documents.
The most effective way I found is to create the new documents by copying from the original document.
The problem is, that the triggers are not copied with it.
Conditions:
Simple triggers are not enough, I need to use action requiring authorization
I don't want to force my users to create manually trigger for each document
I don't mind if the installable trigger is created after clicking button from the programmatically created menu
My thoughts:
I wanted to create it programmatically – there is a problem with the testing environment. I am getting an error:
The add-on attempted an action that is not permitted in Test as add-on
mode. To use this action, you must deploy the add-on.
as I understood, I need to release the project to the store to use this, which I don't want to do.
I don't mind release as an add-on, but the google script IDE only offers to release as web Docs web add-on.
Code:
function onOpen(e){
DocumentApp.getUi() // Or DocumentApp, SlidesApp, or FormApp.
.createMenu('Custom menu')
.addItem('Open sidebar automatically', 'createTrigger')
.addToUi();
}
function createTrigger() {
var doc = DocumentApp.getActiveDocument();
ScriptApp.newTrigger('onOpenReal')
.forDocument(doc)
.onOpen()
.create();
}
function onOpenReal(e){
...something requiring authorization...
}
I figured the answer partially:
I think it is not possible to copy the document together with its triggers, but I didn't find any official documentation about that.
But the error:
The add-on attempted an action that is not permitted in Test as add-on
mode. To use this action, you must deploy the add-on.
in the seemingly regular environment was caused by saved test configuration in the Google apps script editor.
To get rid of the error you need to first delete all test configurations in "Test as add-on" option. Until that the system sees all launches as "test" even if opened as a regular user.

Apps Script: Set triggers on a new form to show sidebar or menu items

I have a script that is creating a copy of a form. When the form is opened by the user for the first time I'd like it to display the sidebar or menus items. Is this possible before any authentication flow has occurred?
Adding an onOpen function the doesn't seemed to have worked as it's not automatically triggered unless you've already been through the authentication process.
The way add-ons work seems to be the behaviour I'd like but I'm unsure if you can create Add-ons for Forms yet.
Code samples would help please... Thanks
It is possible to create menu items for a Form via onOpen() prior to the user authorizing. For example, the following will create a single menu with a single menu item:
function onOpen(e) {
// Only creates menu item, and nothing else
FormApp.getUi()
.createMenu('My Menu')
.addItem('My Menu item','myFunction')
.addToUi();
}
function myFunction() {
// Functionality here; may include code that requires authorization
}
The thing to keep in mind is that onOpen should only be used to create the menus -- it should not contain any code that requires authorization. The reason is that Apps Script allows onOpen() to run without authorization, but will prevent its execution entirely if anything inside of it requires authorization. This is a user-safety mechanism -- onOpen() is run before the user interacts with the Form, and it should never automatically run things without getting the user's permission first. Therefore, if a script hasn't been authorized, Apps Script will only allow certain tasks (like menu creation) to be performed.
For the same reason, it is important not to use global variables which access Apps Script services. Global variables are read and processed as the script file is read, and thus execute before the user can be asked to authorize. If you use global variables, it's best practice to limit them to simple constants.
You can read more about the Apps Script Authorization Lifecycle. This documentation focuses on the authorization of Apps Script add-ons, but much of it is relevant to regular Apps Script scripts.
The other answer is correct about authorizations, the onOpen has limited functionalities because it runs without user explicit permission. You can use it to create a sidebar as well (not only menu items)
example below :
function onOpen() {
var userInterface = createUi();
var ui = formApp.getUi();
ui.showSidebar(userInterface)
}
function createUi(){
var app = UiApp.createApplication().setTitle('test sidebar');
var panel = app.createVerticalPanel();
panel.add(app.createLabel('This is a SideBar'));
return app.add(panel);
}
As mentioned above too (but I insist ;-) be careful if you use global service calls as these are executed when EVERY function is called (including the onOpen) and might prevent your script from working as expected.

Deploying and Using a Google App Script

I followed the app script guide to create a menu for my spreadsheet.
I was tested during development in the spreadsheet running it by going to:
Tools -> Script manager...
But now I want to permanently add it to the spreadsheet, but I don't know hot to deploy it.
I deployed it as a webapp, but when I click the test link i get:
Script function not found: doGet
I can not find documentation to complete that doGet function.
Any help on the last step to use my first Google App Script?
if the function that create your menu is called onOpen(e) it should automatically do the job for you when the document is opened, you don't need to publish the app or anything like that.
But in order to be executed the onOpen function must not call personnal data for the user this function onOpen (when triggered automatically, when you open the sheet) has limited rights:
in the doc https://developers.google.com/apps-script/guides/menus,
it say:
Warning: Note that the add-on menu sample above compares the
e.authMode property to values from the ScriptApp.AuthMode enum. This
is because an add-on that has not been used in the current document
runs its onOpen(e) function with severe restrictions, as explained in
the guide to the add-on authorization lifecycle. If your published
add-on fails to add its menu items, look in the browser's JavaScript
console to see if an error was thrown, then examine your script to see
whether the onOpen(e) function or global variables call services that
aren't allowed in AuthMode.NONE.