Google sheets: Class google.script.run not working - html

My problem is simple. All the possible solutions I searched for online did not address my question.
Google's developer website for Class google.script.run (https://developers.google.com/apps-script/guides/html/reference/run#withSuccessHandler) showcased the method myFunction(...) (any server-side function).
I have copied their exact code and html code and deduced that the function doSomething() does not execute. Nothing gets logged.
I intend to use this to execute an HTML file so that I could play a sound file. I could do this so far with a sidebar popping up from the side, as discussed in this thread: Google Script: Play Sound when a specific cell change the Value.
However, this code provided by Google does not work. Why?
function doGet() {
return HtmlService.createHtmlOutputFromFile('Index');
}
function doSomething() {
Logger.log('I was called!');
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
google.script.run.doSomething();
</script>
</head>
<body>
</body>
</html>

By using google.script.run you are calling a server-side Apps Script function.
https://developers.google.com/apps-script/guides/html/reference/run
Please double-check that you follow the following steps to do it correctly:
Please make sure that you put the html part of the code in a separate HTML file (which you create through File->New->HTML file) with the name corresponding to the one you are calling in HtmlService.createHtmlOutputFromFile() - in your case Index.html
Select “doGet” as the function to be run.
Deploy the script as a web app - this is the requirement for using Apps Script HTML service. Please find the instructions here: https://developers.google.com/apps-script/guides/web
Make sure that every time after you implement changes in your code, you deploy the script as a NEW project version. This is necessary to update the changes.
Open the current web app URL you obtain after updating your version, to open your html output.
In your case only an empty HTML file will be opened, to test functionality - insert some text in your HTML body, to test the correct functionality. The latter can be confirmed by viewing the Logs after running the code.

Related

How can I add a Title of the webApp build with Google Appscript

I have a project wherein I have created a file named javascript.html, page.html , stylesheet.html and code.gs . I want to print out the title of my web app. Passing the title in page.html in <head> tag. However the same is not working. Is there any other way to do the same in Google appscript.
Below you can see there are three html tags. However I have defined only one in my page.html in appscript code.
Below is the code :
Other than that I haven't added any html tag in my code.
Kindly let me know how to do so?
If you are running your Web Apps with doGet() function, how about using setTitle? The sample script is as follows.
Sample script:
function doGet() {
return HtmlService.createHtmlOutputFromFile("index").setTitle("sample title");
}
By setTitle("sample title"), when the source of Web Apps is seen, you can see <title>sample title</title> in the HTML header.
Reference:
setTitle(title)

Google Apps Scripts - server-side function calling

I run the doGet() function. It creates a modal dialog on a spreadsheet. It will show a "Close" and "Make Copy" button where the latter will run a server-side function, doSomething(), that makes a copy of a template. Regardless of whether I attach the function to a button or run it straight in a script tag, it refuses to run. Is there anyway to fix or at the least debug this?
Code.gs
function doGet() {
return SpreadsheetApp.getUi().showModalDialog(HtmlService.createHtmlOutputFromFile('Index'), 'Report');
}
function doSomething() {
var file = template.makeCopy();
file.setName('NEW FILE NAME')
google.script.host.close()
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
google.script.run.doSomething()
</script>
</head>
<body>
<input type="button" value="Close" onclick="google.script.host.close()"/>
<input type="button" value="Make Copy" onclick="google.script.run.doSomething();" />
</body>
</html>
doGet() is a reserved word for web apps.
SpreadsheetApp.getUi only could be used on bounded projects
google.script.host.close() is a client-side method that only works for dialogs and sidebars not for web apps.
Suggestions:
As your project is a bounded project,
change the name of the doGet() function.
Remove google.script.host.close() from doSomething()
Remove
<script>
google.script.run.doSomething()
</script>
Once you make the above changes add menu to call your renamed function. If still doesn't work look for errors at the browser console for client-side errors and to Stackdriver logs for server-side errors.
Quotes
doGet(e) runs when a user visits a web app or a program sends an HTTP GET request to a web app.
google.script.host is an asynchronous client-side JavaScript API that can interact with dialogs or sidebars in Google Docs, Sheets, or Forms that contain HTML-service pages. To execute server-side functions from client-side code, use google.script.run. For more information, see the guide to communicating with server functions in HTML service.
References
https://developers.google.com/apps-script/guides/triggers/
https://developers.google.com/apps-script/guides/html/reference/host#close
In Apps Script, the doGet() and doPost() functions are strictly for sending HTTP requests to GAS-based web apps. Spreadsheet-bound scripts can be published as web apps - however, according to the docs
To create a web app with the HTML service, your code must include a
doGet() function that tells the script how to serve the page. The
function must return an HtmlOutput object, as shown in this example.
In your case, the showModalDialog() method returns 'void'. Also,
Unlike a web app, a script that creates a user interface for a
document, spreadsheet, or form does not need a doGet() function
specifically, and you do not need to save a version of your script or
deploy it. Instead, the function that opens the user interface must
pass your HTML file as an HtmlOutput object to the showModalDialog())
or showSidebar() methods of the Ui object for the active document,
form, or spreadsheet.
Long story short, you don't need to deploy your script as a web app. Instead, you should put the UI building code directly into your main function and, finally, tie that function to the button.

Way to execute Google Standalone Script directly from Drive

Well, I've been reading the documentation for a long time but, as per usual, it's really unclear...
I'm developing a Google Script with the Script Editor that is already working as expected (it have nothing to see with any G suite program but with Drive).
By now, the only way to execute it is opening the script editor and press on the "play" button or the "execute" bar and press on the function.
Obviously this is not a solution since anyone from the bussines could modify/see the code.
So the question is this: how can I make from this script something like an "exe" that I just have to double ckick (its obviously located at Drive) and it executes the script?
I saw this but seems it says no way to do it except from opening the code and execute from the google app script editor...
A Web App is triggered by either an HTTPS GET or POST request. You don't need to use Google Drive.
Ways to trigger a Web App:
Chrome Extension - You can create a Chrome Extension to make an HTTPS GET or POST request. The user would need to install the Chrome extension, and the Chrome extension could put a button in the browser.
Link - Some HTML with a link in it. An email with a link in it. Click the link.
Address Bar - Browser's address bar - Every browser's address bar issues an HTTPS GET request, so you can run a Web App directly from the address bar. Put the published Web App url into the browser address bar and click whatever the browser uses to load the page. (Only for a GET request)
Bookmark - The user could bookmark the link to your Web App. So, they would need to click the link in their bookmark.
Any program that can make an HTTPS GET or POST request. For example, make a POST request from Python or C++.
For a GET request, you need a doGet() function in your script, and to react to a POST request you need a doPost() function.
From what I understand of your requirements the only way would be to deploy your script as a web app with a minimal user interface, just a short message to confirm proper execution for example.
You will never have a "local" executable file since everything in Apps Script is done on google's servers, not in our computers. Instead you will have an url... (with the advantage that it is completely OS independent ! )
The script will remain private unless you share it and you'll be able to choose who can use that url.
Try this:
Build the menu first.
Click "Run My Code".
Click the "Run My Code" button.
runmycode.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
function runMyCode()
{
google.script.run
.withSuccessHandler(updateMyDiv)
.myFunctionName();
}
function updateMyDiv(hl)
{
document.getElementById('MyDiv').innerHTML+='<br />'+ hl;
}
</script>
</head>
<body>
<input type="button" value="Run My Code" onclick="runMyCode()" />
<div id="MyDiv"></div>
</body>
</html>
runMyCode.gs:
function myFunctionName() {
return "Your function has run";
}
function startYourSideBar()
{
var ui=HtmlService.createHtmlOutputFromFile('runmycode');
SpreadsheetApp.getUi().showSidebar(ui);
}
function buildMenu()
{
SpreadsheetApp.getUi().createMenu('Run My Code')
.addItem('Run My Code', 'startYourSideBar')
.addToUi()
}

How to create Multiple file picker/upload button in single HTML web app

I am using google drive file picker in HTML web app, it's working perfectly fine with a single button, I am trying to add a 2nd button to upload the files and save in a different folder.
Please find my complete script in below sheet, please help me to fix or achieve the requirement
Smaple Sheet with Code
You have used the same function name for picker 2. Change the function name so that app script can distinguish it.
In Code.gs change the change the 5th function name from initPicker to initPicker2 and in javascript2.html make the below changes.
function openPicker2() {
google.script.run
.withFailureHandler(showMessage)
.withSuccessHandler(showFilePicker)
.initPicker2();
}
function openUploader2() {
google.script.run
.withFailureHandler(showMessage)
.withSuccessHandler(showFileUploader)
.initPicker2();
}
In saving, try using Save to Drive Button.
As discussed in the documentation, include the necessary JavaScript resource and to add the Save to Drive button tag:
<script src="https://apis.google.com/js/platform.js" async defer></script>
<div class="g-savetodrive"
data-src="//example.com/path/to/myfile.pdf"
data-filename="My Statement.pdf"
data-sitename="My Company Name">
</div>
With this, you can place multiple buttons per page which is implemented sequentially.
See documentation to learn more.

HTML Service Slow

I'm trying to create an add-on for Google Docs using a modal dialog with the HTML Service but the time between running my script and something happening in the dialog window is pretty slow.
Here's a really simple example. (It's a little hack-y because calling foo from Example.html overwrites the first log)
// Code.gs
function openDialog() {
var html = HtmlService.createHtmlOutputFromFile('Example')
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
Logger.log("hi");
var temp = Logger.getLog();
DocumentApp.getUi()
.showModalDialog(html, temp);
}
function foo() {
Logger.log("bye");
}
and
// Example.html
<script>google.script.run.foo();</script>
If I run this there's a ~4 second difference between the first log and the second log. Is this just the way it is?
Short answer: Yes. Your approach is among the best ways to call a server-side function.
Long answer: Per documentation, try loading data asynchronously. It says -
Templated HTML can be used to quickly build simple interfaces, but its use should be limited to ensure your UI is responsive. The code in templates is executed once when the page is loaded, and no content is sent to the client until the processing is complete. Having long-running tasks in your scriptlet code can cause your UI to appear slow.
You could also try providing spinners / pre-loaders in the UI too and that should help with improving UX.
It also recommends us to Use the HTML5 document type declaration i.e.
If your page is served using the newer IFRAME sandbox mode, make sure to include the following snippet of code at the top of you HTML file.
<!DOCTYPE html>
Hope this helps.