Google Apps - Script - Side bar OnOpen/OnInstall function - google-apps-script

I'm recently having issues with Google Apps Scripting, I have a script which installed domain wide, which is enables users to make some tasks easier with the side-bar menu however from last week side-bar menu is not popping up anymore. Nothing has been changed on the code.
I did some workaround and tried all possible ways - deauthorization \ authorization, deploying the same code with different name, nothing worked except if the user removes it and adds it to the spreadsheet which they work - it's popping up and working only for that sheet and only for one time.
Can you please advise, how to fix this issue?
Here is my OnInstall and OnOpen functions:
function onInstall(e)
{
onOpen(e)
}
function onOpen(e) {
var html = HtmlService.createHtmlOutputFromFile('Index')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setTitle('BB KING');
SpreadsheetApp.getUi().showSidebar(html);
}
Thanks in advance.
Edit : Triggers making the side-bar work on simple scripts on spesific spreadsheets, but this method is not working on domain-wide installed add-ons.

It should be possible to add a trigger to run the custom function which shows the SideBar.
I have a function like the following in my code that runs on my domain:
function createOnOpenTrigger()
{
var sheet = SpreadsheetApp.getActiveSpreadsheet();
// Trigger on open
ScriptApp.newTrigger(FunctionToRunOnOpen)
.forSpreadsheet(sheet).onOpen().create();
}
function FunctionToRunOnOpen()
{
var html = HtmlService.createHtmlOutputFromFile('Index')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setTitle('BB KING');
SpreadsheetApp.getUi().showSidebar(html);
}
You could then put the createOnOpenTrigger function as an option in your custom menu - to be run only once everytime a copy is made of the entire spreadsheet.

Related

Can't run function from sidebar [duplicate]

This question already has answers here:
Google Apps Script PERMISSION_DENIED with sheets addon
(2 answers)
Closed 1 year ago.
I'm having problems calling a server-side Apps Script function from a html sidebar in Google Sheets.
I've replicated my issue with the simple example code below.
What it should do
Clicking the button should call alert in my Code.gs script and display an alert to the user.
What actually happens
Clicking the button shows the error:
We're sorry, a server error occurred while reading from storage. Error code PERMISSION_DENIED.
There are no entries in the 'executions' section of the Apps Script dashboard for alert(), so it seems like the function never even gets called?
Code.gs:
function onOpen() {
const ui = SpreadsheetApp.getUi();
ui.createMenu('Matthew')
.addItem('Show Sidebar', 'sidebar')
.addToUi();
};
function sidebar() {
const html = HtmlService.createHtmlOutputFromFile('test.html')
.setTitle('Matthew Experiment')
.setWidth(300);
SpreadsheetApp.getUi().showSidebar(html);
}
function alert() {
SpreadsheetApp.getUi().alert("alert!");
}
test.html (well the body)
<body>
<div class="container">
<button class="btn btn-success" onclick="doSomething()">Click Me!</button>
</div>
<script>
function doSomething() {
google.script.run.withFailureHandler(function(error) {
console.log("error")
console.log(error.message)
}).withSuccessHandler(function(result) {
console.log("done!")
}).alert();
}
</script>
</body>
I've confirmed that the client-code is getting properly inflated with server-side function names, it's just calling the function that doesn't work.
My code seems to be the same as all of the getting started guides, but I don't see anyone else posting about this issue. Hoping someone here has deeper knowledge of the problem than I do.
Update, even weirder
I opened a private window and it worked, so I thought, maybe this is an extension causing problems? But even disabling all extensions doesn't fix it in the main window. I've logged out/in to my google account but still can't get it to work without opening a private browser window.
This problem is consistent across chrome/edge/firefox.
This happens when the global logged in user is different from the owner of script.
Logout all your google account and then re-login with the account you used to created the script. This fixed the issue.
Here's a simple example of a side bar dialog communicating with server
function showMySideBar() {
var html='<input type="button" value="Click Me" onClick="doSomething()" />';
html+='<script>function doSomething(){google.script.run.withSuccessHandler(function(msg){window.alert(msg);}).pleaseHelp();}</script>';
SpreadsheetApp.getUi().showSidebar(HtmlService.createHtmlOutput(html));
}
function pleaseHelp() {
return 'What can I do to help?';
}

Create a Dialog box with custom buttons and Links

So I have an internal emailing list that I want to subscribe new employees to and unsubscribe employees that have left.
I'm using a google sheet with a check box to do this. Mainly because this sheet is already used in the HR process, so it's easy to remember to do.
When the check the box is checked I want a dialog box to pop up with a buttons that says
Subscribe and Unsubscribe. These buttons are linked to locations within the emailing tool that allows people to subscribe or unsunscribe.
The scribe I have at the moment is
var result = ui.alert
(
'What would you like to do?',
'Subscribe a new Employee or' + "\n" + 'Unsubcribe an employee thats left',
ui.ButtonSet.Subscribe_Unsubscribe
);
if (result == ui.Button.Subscribe)
{
}else
{
ui.alert('Employee has been removed from the internal mailing list');
}
}
I'm not sure how if by changing the button set names work this way and I dont know how to assign a link to the buttons either.
Looking forward to your responses!!!
Step 1:
First you would need to create an installable trigger that would execute a function in GAS whenever a cell is edited.
You can find an explanation / reference on Installable Triggers here:
Installable Triggers
Why installable triggers? Because you would need to connect to an email service, which requires authorization.
Sample Code:
/**
* Creates a trigger for when a spreadsheet is edited.
*/
function createSpreadsheetEditTrigger() {
var ss = SpreadsheetApp.getActive();
ScriptApp.newTrigger('myFunction')
.forSpreadsheet(ss)
.onEdit()
.create();
}
Step 2:
To create custom dialog boxes you need to create the HTML file from scratch in GAS, the IDE allows you to create HTML files from the menu.
Then in your script you would need to use getUi().showModalDialog to display the dialog box.
I have some sample code in a Stack Overflow post here: Stack Overflow
Note that the HTML would need both onclick="google.script.run" and onclick="google.script.host.close()" parameters to execute functions within Apps Script.
References:
showModalDialog()
Templated HTML
Communication between HTML and Apps Script

Can I use Slides API to add an "Agree to Terms" dialogue before allowing viewer access to a Slides presentation?

I have a Google Slides presentation that I'd like to gate with a request to agree to "Terms & Conditions" before viewing. (The dialogue box would include an external link to the legal fine print.)
I see that with Google App Script adding a dialogue box is possible, but if one can be customized in this manner is unclear to me.
Thanks in advance for any help on this.
You want to open a dialog, when users open the Google Slides.
In this case, users are logged in to each Google account.
You want to make users show "Terms & Conditions" by the external link.
When users click "ok" button, when users reopen the Google Slides, you don't want to open the dialog.
When users click "cancel" button, when users reopen the Google Slides, you want to open the dialog.
You want to use a custom dialog for this.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Issue and workarounds:
In order to open the custom dialog when users open the Google Slides, it is required to use the installable trigger. But at Google Slides, unfortunately, in the current stage, the OnOpen event trigger cannot be used as the installable trigger. By this, when users open the Google Slides, the custom dialog cannot be opened. It seems that this is the current specification. So in order to achieve abour your goal, it is required to think of the workaround. In this answer, I would like to propose the following 2 workarounds.
Workaround 1:
Fortunately, at Google Slides, the simple trigger can be used instead of the installable trigger which cannot be used. In this case, the OnOpen event trigger can be used as the simple trigger. So in this workaround, the built-in dialog is used with the simple trigger.
Sample script:
Please copy and paste the following script to the container-bound script of the Google Slides and save it. When you open the Google Slides, a dialog is opened. When "ok" is clicked, keyObject is set to the PropertiesService. By this, when you open the Google Slides again, the dialog is not opened. In this case, getUserProperties() is used. So keyObject can be used for each users.
function onOpen() {
var keyObject = {key1: "value1"}; // Here, key and value for checking whether user had clicked "ok" button.
var prop = PropertiesService.getUserProperties();
var value = prop.getProperty(Object.keys(keyObject)[0]);
if (value != keyObject.key1) {
var ui = SlidesApp.getUi();
var result = ui.alert('sample title', 'Please check this link.\nhttps://###/', ui.ButtonSet.YES_NO);
if (result == ui.Button.YES) {
ui.alert('"ok" was clicked.');
prop.setProperties(keyObject);
} else {
ui.alert('"cancel" was clicked.');
}
}
}
In this case, the URL cannot be clicked. So user is required to access to the URL. I think that this is the limitation when this workaround is used.
If you want to delete keyObject. Please use the following script.
function deleteProperty() {
var keyObject = {key1: "value1"};
var prop = PropertiesService.getUserProperties();
prop.deleteProperty(Object.keys(keyObject)[0]);
}
Workaround 2:
In this workaround, the built-in dialog and the custom menu are used with the simple trigger. In this case, the custom dialog is used.
Sample script:
Please copy and paste the following script to the container-bound script of the Google Slides and save it. When you open the Google Slides, a dialog is opened. The dialog shows "Please open dialog from the menu.". Users click "ok" button and open the custom dialog from the custom menu. When "ok" is clicked at the custom dialog, keyObject is set to the PropertiesService. By this, when you open the Google Slides again, the dialog is not opened. In this case, getUserProperties() is used. So keyObject can be used for each users.
function onOpen() {
var keyObject = {key1: "value1"};
var prop = PropertiesService.getUserProperties();
var value = prop.getProperty(Object.keys(keyObject)[0]);
if (value != keyObject.key1) {
var ui = SlidesApp.getUi();
ui.createMenu('Open dialog').addItem('Open dialog', 'openDialog').addToUi();
var result = ui.alert('sample title', 'Please open dialog from the menu.', ui.ButtonSet.OK);
}
}
function openDialog() {
var ui = SlidesApp.getUi();
var html = 'link<input type="button" value="ok" onClick="ok()"><input type="button" value="cancel" onClick="cancel()"><script>function ok() {google.script.run.withSuccessHandler(()=>google.script.host.close()).setProp()}function cancel() {google.script.host.close()}</script>';
ui.showModalDialog(HtmlService.createHtmlOutput(html), "sample");
}
function setProp() {
var keyObject = {key1: "value1"};
var prop = PropertiesService.getUserProperties();
prop.setProperties(keyObject);
}
In this case, the URL can be clicked. But in order to open the custom dialog, it is required to open it from the custom menu. I think that this is the limitation when this workaround is used.
Note:
Above scripts are the simple scripts for testing the workaround. So please modify them for your actual situation.
References:
Simple Triggers
Installable Triggers
Alert dialogs
Custom dialogs
If I misunderstood your question and this was not the direction you want, I apologize.

google-apps-script restric menu use/creation to users

I have a sheet with a google apps script that does various things. One of those things is building a menu on open.
I would like this menu to be built only when a certain specific user is acessing the sheet. How can I achieve this?
You cannot have restrictions inside onOpen since the user's email address is not available in any context that allows a script to run without that user's authorization. You can however include checks in the function that runs on clicking menu items.
function onOpen(e) {
SpreadsheetApp.getUi()
.createMenu('Menu')
.addItem('First item', 'doSomething')
.addToUi();
}
function doSomething() {
if (Session.getActiveUser().getEmail() !== "abc#example.com") return;
// else do something here
}

Google App Script WebApp, Manipulating UI

Hi and Good day to all,
Google App Script can be used in so many ways. I know cause I have tried some of them but Iam not an expert so, the situation is.
I have created an Spreadsheet
create a form using the new UI Building that comes with the script editor.
named:gtest01
UI compose of:
label, id=label_caption
button 1, id=button_hide, event-onmouseclick=hide_label
button 2, id=button_show, event-onmouseclick=show_label
button 3, id=button_message, event-onmouseclick=message_me
now, the code is:
/* This is so when I want to just deploy it as a [webapp] using the
script editor -> Publish Deploy as Web App
*/
function doGet(e) {
var app = UiApp.createApplication().setTitle("Sheet Application");
app.add(app.loadComponent("gtest01"));
Logger.log("Application UI Loaded");
return app;
}
function message_me(e) {
Browser.msgBox("my message");
}
function hide_label(e) {
var app = UiApp.getActiveApplication();
label =app.getElementById("label_caption");
label.setVisible(false);
}
function show_label(e) {
var app = UiApp.getActiveApplication();
label =app.getElementById("label_caption");
label.setVisible(true);
}
// this code is for when the spreadsheet is shared so they can access the form
function showform_() {
var app = UiApp.createApplication();
app.add(app.loadComponent("gtest01"));
SpreadsheetApp.getActiveSpreadsheet().show(app);
}
function onOpen() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var menuEntries = [];
menuEntries.push({name: "Show Form", functionName: "showform_"});
ss.addMenu("e-Test", menuEntries);
}
First scenario is that when spreadsheet is shared
when menu is clicked the form will load - thats good
when show and hide button nothing happens - why and how can i fixed
this?
when message button is click - message will show but the form will
close, how can I display a message without closing the form?
Second scenario is that when publish as Webapp.
When Developer Link is Access the UI is always updated - ok
When URL Link is Access the UI is always updated its like it is
cache, how can I fixed this?
on dev link: when show and hide button nothing happens - why and how
can i fixed this?
on dev link: when message button is click - will generate an error,
how can I display an alert message on WebApp
Please help I have search and tried the sample codes and answer in the forum am missing something.
Thanks
Nick Ace
First scenario
when show and hide button nothing happens - why and how can i fixed this?
In your functions, use return app at the end. Unless you return the app object, the UI doesn't get updated.
how can I display a message without closing the form? - Try
SpreadsheetApp.getActiveSpreadsheet().toast()
2nd scenario
When URL Link is Access the UI is always updated its like it is cache, how can I fixed this? - Save your most recent code as a version
on dev link: when show and hide button nothing happens - Again return app will take care of this
on dev link: when message button is click... - Browser.msgBox is not supported in a web app.
When Using UI it is generally a good idea to make everything happen inside this Ui, so try to avoid showing messages with Toast( as they are not supported in web apps anyway).
Since you are using the GUI it should be quite easy to use a label with your message that is initially invisible and to make it visible in an handler routine.
Note that this kind of handler can be a client handler as well unless you need to do something else from this action.
As for the other points of you question, our (very fast) friend Srik has already answered thoroughly ;-)