Way to execute Google Standalone Script directly from Drive - google-apps-script

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()
}

Related

Inject HTML signature into Gmail from hosted page

I have the basic shell of a Chrome extension done and have come to the point where I am trying to inject an HTML signature into Gmail using code hosted on an unindexed page on my site. The reason I want to do this is to be able to include web fonts, something that for the life me I can't figure out why Gmail hasn't allowed you to do from their font library.
In any regard, as I said, I have a right-click context menu option ready to trigger a script from my js function page and the extension loads without errors. I need to figure out the best way to inject the HTML into the email and without losing any of the formatting that has been done on the page.
I have created the extension manifest, set the permissions on the context menu and created a function to call back to the js page that will inject the signature.
var contextMenus = {};
contextMenus.createSignature =
chrome.contextMenus.create(
{"title": "Inject Signature",
"contexts": ["editable"]},
function (){
if(chrome.runtime.lastError){
console.error(chrome.runtime.lastError.message);
}
}
);
chrome.contextMenus.onClicked.addListener(contextMenuHandler);
function contextMenuHandler(info, tab){
if(info.menuItemId===contextMenus.createSignature){
chrome.tabs.executeScript({
file: 'js/signature.js'
});
}
}
The end result is nothing enters the page and get massive errors related to cross-site because the domain is not the same obviously. This has obviously been solved as there are numerous signature extensions out there. I would probably use one of theirs but a) I want to build it on my own, b) they all want you to use their templates, none of them that I have seen will let you just use your own code.
So, any ideas?

Google sheets: Class google.script.run not working

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.

Get the full browser URL in Apps Script

I'm looking to get the full URL of the current browser window in Apps Scripts while displaying the web app via HTMLService
When I try this, it doesn't work because the Apps Scripts is sandboxed and I get another server url of some sort
window.location.href
When I try this, I can only fetch the hash or parameters, not the full url
google.script.url.getLocation(function(location) {
console.log(location.parameters);
console.log(location.hash);
});
source: https://developers.google.com/apps-script/guides/html/reference/url#methods
Purpose for the above:
I want a button that people click on in the published Web App to remove the browser toolbar. However, the browser toolbar is not removable in the current browser window. So I want to fetch the Web App URL and put it in window.open() as a new window with the current web app because the browser toolbar can be remove this way. But I can't seem to get the current URL.
Any ideas how I can achieve this?
Thanks in advance!
I don't know what you meant by developer mode either but I took a guess at this being the answer to the question. If not, let me know and I'll remove it.
On the clientside you can use Javascript:
<script>
function getUrl(){
google.script.run
.withSuccessHandler(function(url){
document.getElementById('mydiv').innerHTML='<p>' + url + '</p>';
})
.getScriptUrl()
</script>
<body>
<div id="mydiv"></div>
</body>
In Google Script:
function getScriptURL() {
return ScriptApp.getService().getUrl();
}
Jan 10, 2021: Tested the above code in a window.onload and it is returning the correct url with a business account, V8 runtime and the new editor.
I'd suggest this code for the current script URL:
function getScriptURL() {
// dev URI
'https://script.google.com/macros/d/' + ScriptApp.getScriptId() + '/edit';
}

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.

doPost stopped working google app script

I have had an HTML Service script that has worked for at least 8 months that uses a doGet for the first page and doPost of all subsequent pages.
Yesterday, when I loaded the page, the doGet works fine, pulls info from a spreadsheet and renders the the form. Regardless of what selections I make, the submit button does nothing.
I then went back to my personal gmail account, unrelated to the production account, untouched and using private dummy copies of data, where I originally coded it and that one no longer works.
I looked in the execution transcripts and it shows proper html rendering to the bottom of the first page, but nothing else.
Has doPost been retired?
I've had a working script fail recently, the fix was to force the Sandbox emulation mode to EMULATED.
The default mode WAS emulated with a caveat in the docs saying this could change.
Without seeing your code I'm not sure if that is relevant or not....
function doGet() {
var html = HtmlService.createTemplateFromFile("FormHtml");
html = html.evaluate();
html.setSandboxMode(HtmlService.SandboxMode.EMULATED);
return html;
}