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

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>

Related

Open sidebar in Google App Script with parent menu

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

Calling library function from html in that library

In order to share with my colleagues the AppsScript code I am developing, I created a standalone project used as a library in our Docs template.
This library contains:
a .gs file for the server side code
a .html file for the client side sidebar
In the sidebar, I have a button which triggers a call to a function from the library with a parameter.
The javascript call is the following:
google.script.run
.withFailureHandler(
function(msg, element) {
showError(msg, $('#button-bar'));
})
.test();
I read on other pages that the library code wasn't exposed so the test function is in fact in the AppsScript code of my Docs and calls the equivalent library function.
As it was suggested here: Can a Google Spreadsheet Apps Script library contain a user dialog?
Code in the Docs AppsScript:
function test()
{
myLibrary.test();
}
Code in myLibrary library:
function test()
{
DocumentApp.getUi().alert('test');
}
The problem is that the failure handler from the javascript returns a ScriptError stating that I need to have the authorization to perform this action.
Any ideas of what I am doing wrong?
PS: I know I could make an add-on but this is not something I can easily do inside my company :)
Yes, when you use the html code (sidebar) from your library it'll call the test() function inside the script bound to the document rather that the one in the library.
You need to request permission to the user to be able to prompt UI elements, you can do this with a custom menu [1].
Also, the users need to have at least read access on the library [2]. I add the withSuccessHandler function [3] to show the response from client-side in the sidebar. The following code worked for me:
Script bound to the document:
function onOpen() {
DocumentApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.createMenu('Custom Menu')
.addItem('Show sidebar', 'showSidebar')
.addToUi();
}
function showSidebar() {
myLibrary.showSidebarLibrary();
}
//
function test() {
myLibrary.test();
}
Library:
code.gs
function showSidebarLibrary() {
var html = HtmlService.createHtmlOutputFromFile('Page')
.setTitle('My custom sidebar')
.setWidth(300);
DocumentApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.showSidebar(html);
}
function test() {
DocumentApp.getUi().alert('test');
return "Success";
}
Page.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Hello, world!<br>
<input type="button" value="Alert" onclick="alert()" /><br>
<input type="button" value="Close" onclick="google.script.host.close()" />
<p id="msg">Replace message with response<p>
</body>
<script>
function alert() {
google.script.run.withFailureHandler(handler).withSuccessHandler(handler).test();
}
function handler(msg) {
document.getElementById("msg").innerHTML = msg;
}
</script>
</html>
[1] https://developers.google.com/apps-script/guides/menus
[2] https://developers.google.com/apps-script/guides/libraries#gaining_access_to_a_library_and_including_it_in_your_project
[3] https://developers.google.com/apps-script/guides/html/communication#success_handlers

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

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