Open sidebar in Google App Script with parent menu - exception

I am trying to open sidebar in Google App Script with parent menu but without sub-menu.
but error coming Exception: Cannot call SlidesApp.getUi() from this context.
init.gs
function onOpen() {
showSidebar();
SlidesApp.getUi()
.createMenu('Test Menu')
.addItem('Add In', 'showSidebar')
.addToUi();
}
function showSidebar() {
var html = HtmlService.createHtmlOutputFromFile('sidebar')
.setTitle('My custom sidebar')
.setWidth(300);
SlidesApp.getUi()
.showSidebar(html);
}

You should change createHtmlOutputFromFile method or create a sidebar.html
This is working correctly if you change the method. By using your code there should be 2 files.
code.gs
function onOpen() {
SlidesApp.getUi()
.createMenu('Test Menu')
.addItem('Add In', 'showSidebar')
.addToUi();
}
function showSidebar() {
var html = HtmlService.createHtmlOutputFromFile('sidebar')
.setTitle('My custom sidebar')
.setWidth(300);
SlidesApp.getUi()
.showSidebar(html);
}
sidebar.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Hello, world! <input type="button" value="Close" onclick="google.script.host.close()" />
</body>
</html>
Otherwise you can directly define the HTML using the createHtmlOutput method.
code.gs
function onOpen() {
SlidesApp.getUi()
.createMenu('Test Menu')
.addItem('Add In', 'showSidebar')
.addToUi();
}
function showSidebar() {
var html = HtmlService.createHtmlOutput('Hello, world! <input type="button" value="Close" onclick="google.script.host.close()" />')
.setTitle('My custom sidebar')
.setWidth(300);
SlidesApp.getUi()
.showSidebar(html);
}
PoC

Related

google.script.run.function() call from HTML not working

I'm calling a function from a dialog HTML file bound to my google sheet. I copied the code from google development & wanted to call a simple function. However, it does nothing. I tried various things, but I just cannot get it to work. Bouth the script & HTML are bound to my spreadsheet.
Here is my script:
// Use this code for Google Docs, Slides, Forms, or Sheets.
function onOpen() {
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.createMenu('Dialog')
.addItem('Open', 'openDialog')
.addToUi();
}
function openDialog() {
var html = HtmlService.createHtmlOutputFromFile('Index');
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.showModalDialog(html, 'Dialog title');
}
function doSomething() {
Logger.log('I was called!');
}
and here is the simple HTML file
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
google.script.run.doSomething();
</script>
</head>
</html>
Try this:
GS:
function openDialog() {
var html = HtmlService.createHtmlOutputFromFile('ah3');
SpreadsheetApp.getUi().showModalDialog(html, 'Dialog title');
}
function doSomething() {
SpreadsheetApp.getActive().toast("I was called.")
}
HTML:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
window.onload=function(){
google.script.run
.withSuccessHandler(function(){google.script.host.close();})
.doSomething();
}
console.log("I am here");
</script>
</head>
<body>
</body>
</html>

Launch Google Form via Appscript as a Custom menu

I am trying to launch a Google Form that I created from a Google Sheet, via App Script. The script does not work and I am not sure what needs to be done to fix it. Here is the script:
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('Custom Menu')
.addItem('Edit/Delete', 'menuItem1')
.addSeparator()
.addItem('New Entry', 'menuItem2')
.addToUi();
}
function menuItem1() {
SpreadsheetApp.getUi () // Or DocumentApp or FormApp.
.alert('You clicked the first menu item!');
}
function menuItem2() {
// Open a fom. var form = FormApp.openByUrl('https://docs.google.com/forms/d/e/1FAIpQLSfYrw3nwiYt6p8bPEqyV0GD8hpnaFOfa1i4LHYMo01GPPM6dQ/viewform');
}
This is how I would approach this task. My Code.gs would like like this. It opens a mini modal. Let me know what you think.
function onOpen() {
var ui = SpreadsheetApp.getUi();
// Or DocumentApp or FormApp.
ui.createMenu('Custom Menu')
.addItem('Edit/Delete', 'menuItem1')
.addSeparator()
.addItem('New Entry', 'menuItem2')
.addToUi();
}
function menuItem1() {
SpreadsheetApp.getUi () // Or DocumentApp or FormApp.
.alert('You clicked the first menu item!');
}
function menuItem2() {
// Here register an HTML template that will render a modal/popup.
// 'form' is the name of a new 'form.html' file
var htmlOutput = HtmlService.createHtmlOutputFromFile('form')
.setWidth(250)
.setHeight(50)
// Here call the modal/pop to open when the menu button 'MenuItem2' is
// clicked
SpreadsheetApp.getUi().showModalDialog(htmlOutput, 'Form');
}
I would then have another html file call "form.html" which will render a modal when it is called.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Open Form
<!-- Below is an HTML trick to open a url in a new tab automatically -->
<!-- change the action url to any that is needed -->
<!-- foo can be any string -->
<form action='http://example.com' method='get' id='foo'></form>
<script>document.getElementById('foo').submit();</script>
</body>
</html>
The file structure in the Appscript should look like this:

fill sidebar form from sheet

In google sheet, I want to fill a form in a sidebar with values from the active sheet. Since I can't use a click on cell trigger, i want to use a function that takes the value of the active cell when a button in the sidebar is clicked.
I wrote this code but it didn't work unfortunately,
I am new to Apps script so excuse my low level code :)
Thank you !
test_sidebar.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
function tSubmit(form){
google.script.run.withSuccessHandler(updateT).getT(form);
}
function updateT(cellValue){
var div=document.getEelementById('T');
div.innerHTML='<input name="T" size = 10 value=' + cellValue + '>K'
}
</script>
</head>
<body>
<form>
<font color="red">Select conditions of interest:</font><p>
<ul><input value=T type="Button" onClick="tSubmit(this)"><div id="T"> = <input name="T" size = 10>K</div></ul>
<ul><i>P</i> = <input name="P" size = 10>bar</ul>
</form>
</body>
</html>
code.gs :
function onOpen() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.createMenu('Custom Menu')
.addItem('Show sidebar', 'showSidebar')
.addToUi();
}
function showSidebar() {
var html = HtmlService.createHtmlOutputFromFile('test_sidebar')
.setTitle('My custom sidebar')
.setWidth(300);
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.showSidebar(html);
}
function getT(form){
var cellValue= SpreadsheetApp.getActiveSheet().getActiveCell().getValue();
return cellValue;
}
You have a typo in the html file. Remove the extra e in getElementByID to make it:
var div=document.getElementById('T');
Also, there is no need to try to pass the form, which is also causing a problem anyway, so just remove those portions. You final codes will be:
test_sidebar.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
function tSubmit(){
google.script.run.withSuccessHandler(updateT).getT();
}
function updateT(cellValue){
var div=document.getElementById('T');
div.innerHTML='<input name="T" size = 10 value=' + cellValue + '>K'
}
</script>
</head>
<body>
<form>
<font color="red">Select conditions of interest:</font><p>
<ul><input value=T type="Button" onClick="tSubmit()"><div id="T"> = <input name="T" size = 10>K</div></ul>
<ul><i>P</i> = <input name="P" size = 10>bar</ul>
</form>
</body>
</html>
code.gs :
function onOpen() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.createMenu('Custom Menu')
.addItem('Show sidebar', 'showSidebar')
.addToUi();
}
function showSidebar() {
var html = HtmlService.createHtmlOutputFromFile('test_sidebar')
.setTitle('My custom sidebar')
.setWidth(300);
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.showSidebar(html);
}
function getT(){
var cellValue= SpreadsheetApp.getActiveSheet().getActiveCell().getValue();
return cellValue;
}
Btw you can trigger a function with the use of an Image, and linking that image to a function.. A "trick" to trigger something from the cell

In Google Shreadsheet I have a created a new menu which opens a dialog and a sidebar. I want to be able to open the dialog from the sidebar

Sidebar is html.
Figured I could just link a button to the function that originally opens the dialog from the menu, but no luck...doesn't do anything. Wondering whether it could be because function call is now in an html file not in the actual spreadsheet? Maybe?
Here is code for sidebar:
<input type="button" value="New Booking" onclick="newContact()" ><p>
<script>
function newContact() {
var html = HtmlService.createHtmlOutputFromFile('Experimental')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(1050);
//.setHeight(800);
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.showModalDialog(html, 'New Contact');}
</script>
The HtmlService code needs to be run from a google script (.gs) file. It won't work in standard javascript as you have it set up in your question. From html and javascript, you can run .gs function with google.script.run.newContact(). Of course you can replace newContact with any .gs function you want to run.
.gs code
function sideBar(){
var html = HtmlService.createHtmlOutputFromFile('index')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setTitle('My custom sidebar')
.setWidth(300);
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.showSidebar(html);
}
function newContact() {
var html = HtmlService.createHtmlOutputFromFile('New Contact')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(1050);
//.setHeight(800);
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.showModalDialog(html, 'New Contact');
}
Index.html
<div>
<input type="button" value="New Booking" onclick="google.script.run.newContact()" ><p>
</div>
New Contact.html
<div style="width:50px; height:50px; color:red;">
</div>

How to use scriptlets in HTMLOutput in Google Apps Script

I'm loading a modal dialog with:
var html = HtmlService.createHtmlOutputFromFile('File')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(1000)
.setHeight(700);
SpreadsheetApp.getUi()
.showModalDialog(html, 'My Page');
Now, in File.HTML, I want to load another HTML file with CSS settings, how do I do that?
I've tried including it as in HtmlTemplate using scriptlets but it doesn't work:
<?!= include('File'); ?>
EDIT:
I have defined the include function in code.gs:
function include (file) {
return HtmlService.createTemplateFromFile(file).evaluate().getContent();
}
The problem is that you are using:
createHtmlOutputFromFile
instead of:
createTemplateFromFile
You need to create a template:
This is what you are seeing:
The scriptlet is not running, but being interpreted as text.
This is what you want to see:
Here is how the code should be:
Code.gs
// Use this code for Google Docs, Forms, or new Sheets.
function onOpen() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.createMenu('Dialog')
.addItem('Open', 'openDialog')
.addToUi();
}
function openDialog() {
var html = HtmlService.createTemplateFromFile('index')
.evaluate();//This is necessary
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.showModalDialog(html, 'Dialog title');
}
function include(File) {
return HtmlService.createHtmlOutputFromFile(File).getContent();
};
index.html
<?!= include('File'); ?>
Hello, world!
<input type="button" value="Close"
onclick="google.script.host.close()" />
File.html
<div>
This is a test. it worked!
</div>
Basically, you need to change:
var html = HtmlService.createHtmlOutputFromFile('index')
to:
var html = HtmlService.createTemplateFromFile('index')
Create a TEMPLATE from file.
And I also changed the code to this:
function openDialog() {
var html = HtmlService.createTemplateFromFile('index')
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
Original answer:
include is not something like a keyword or a built in function. You need to create a function in a .gs script file named include.
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename).getContent();
};
Also, you can't mix the HTML Service and the UI Service. I don't know if that's what you are trying to do, but I thought I'd mention it.
What you want to accomplish is describe in the documentation here:
Documentation - Best Practices