I'm currently trying to make a paperwork wizard using google forms and apps script. At the end of the form, I'm trying to run an Apps Script once the form submits and display a HTML window. I tried using FormApp.getUI()along with the apps event trigger, but I keep getting the error Exception: Cannot call FormApp.getUi() from this context. From other posts it seems like this error is because the trigger runs the script server side. Is there a way to run this script client-side so the HTML window can be displayed?
EDIT: Conditional Sections Google forms this question is different from the one I'm asking now.
EDIT2: Code
Code.gs
function myFunction() {
var lock = LockService.getScriptLock();
var html = HtmlService.createHtmlOutputFromFile('display');
FormApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.showModalDialog(html, " Let's check if you need to present!");
SpreadsheetApp.flush();
lock.releaseLock();
}
display.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<p>Test</p>
</body>
</html>
From the question:
At the end of the form, I'm trying to run an Apps Script once the form submits and display a HTML window.
This is not possible.
If you collected the respondent email address you could send them an email
Related
I want to start off by saying I have limited coding experience in google scripts, but have had extensive experience coding in R. I have tried a using previous stackedoverflow solution (Using QR Code to enter value into Google Form?), but any time I would edit the URL, it'll say "Sorry, unable to open the file at this time."
I copied the code that was listed under code.gs into the main script and changed 'your-form-id-here' to match my google sheet's ID and added the two HTML codes for 'Success' and 'Failure', but it hasn't worked.
I have a google form that asks people to input their unique ID Number. Rather than having folks mis-type their number, I would like to set it up so that they can scan a QR code on their phone and have the Google Form auto-populate the first question that asks for their ID#. There are additional questions on the google form they need to answer, but I would just like for the first question to be auto-populated.
Here is the Google Form: https://docs.google.com/forms/d/e/1FAIpQLSdsP0e2FsC54QY0Nyrpipi21yC-8ODjO9aRlfOMq51vODRaew/viewform?usp=sf_link
The Form ID I used was 1FAIpQLSdsP0e2FsC54QY0Nyrpipi21yC-8ODjO9aRlfOMq51vODRaew, which I assumed was the ID based on the Google Form URL.
EDIT: Here is my current script for the Code.gs:
function doGet(e){
try {
var passNo = e.parameters.passNo;
var qNumber = e.parameters.qNumber;
var form = FormApp.openById('1FAIpQLSdsP0e2FsC54QY0Nyrpipi21yC-8ODjO9aRlfOMq51vODRaew');
var items = form.getItems();
// assuming question 1 is the pass number question
var q = items[qNumber[0] - 1].asTextItem();
var itemResponse = q.createResponse(passNo[0])
var FormResponse = form.createResponse();
FormResponse.withItemResponse(itemResponse);
FormResponse.submit();
return HtmlService.createHtmlOutputFromFile('Success')
}
catch(e){
return HtmlService.createHtmlOutputFromFile('Failure');
}
}
I also added the Success.html and Failure.html code exactly as written in the previous example:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Success
</body>
</html>
and
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Failure
</body>
</html>
After deploying the script, I got the URL and practiced adding the "passNo" and "qNumber" exactly as they did in the example by adding ?passNo=21480&qNumber=1 to the end of my URL, but the URL leads to a page error:
https://script.google.com/macros/s/AKfycbx9oXtjZXGNHPN1axSjKvP5StGbBej0IbQzK1vNT-HB6hzEvIzDbcLor-qtgVDU3ftQ/exec?passNo=1234&qNumber=1
Issue and solution:
When I saw your current script, I noticed that at ar form = FormApp.openById('1FAIpQLSdsP0e2FsC54QY0Nyrpipi21yC-8ODjO9aRlfOMq51vODRaew'); and https://docs.google.com/forms/d/e/1FAIpQLSdsP0e2FsC54QY0Nyrpipi21yC-8ODjO9aRlfOMq51vODRaew/viewform?usp=sf_link, you are using the ID from the URL of preview. In this case, that ID is not the Google Form ID. I thought that this might be the reason for your issue.
For example, when I tested your script by using the correct Google Form ID, no error occurs. "Success" is returned. So please modify as follows.
From:
var form = FormApp.openById('1FAIpQLSdsP0e2FsC54QY0Nyrpipi21yC-8ODjO9aRlfOMq51vODRaew');
To:
var form = FormApp.openById('### Google Form ID ###');
In this case, please use ### of https://docs.google.com/forms/d/###/edit.
Note:
When you modified the Google Apps Script, please modify the deployment as a new version. By this, the modified script is reflected in Web Apps. Please be careful this.
You can see the detail of this in the report of "Redeploying Web Apps without Changing URL of Web Apps for new IDE".
I would like to have a google sheet that when you pick something on a google sheet it brings up an html file on a new google tab that has info from the google sheet. I am using the code below as a quick test to see if this is possible.
Right now I have a menu item that calls myFunction(), then I would like that to bring up the new html page. This doesn't come close to working, as it just enters and exits myFunction and no html page. So was wondering if anyone knows if this is possible. If so can you give me some hints on how to do it.
code.gs
function myFunction(){
HtmlService.createTemplate('page');
};
page.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<title>Hello<\title>
</body>
</html>
Change myFunction() to doGet(), and you need to return the HtmlService from the doGet function. Also, the statement inside the doGet() function is different than what you currently have.
Your myFunction() function should look like this
function doGet() {
return HtmlService.createTemplateFromFile('page').evaluate();
}
doGet() is a special function that Google Apps Script web app scripts should handle any GET requests.
For more information, please refer to one of these guides:
https://developers.google.com/apps-script/guides/html/templates
https://developers.google.com/apps-script/guides/html
This is absolutely possible.
What you want to implement is a web app.
Simple Example
function doGet() {
textOutput = ContentService.createTextOutput("Hello World! Welcome to the web app.")
return textOutput
}
Put this in a script file and then deploy the script as a web app - instructions. The deploy process will give you a link with which you can visit the web app and see your text output.
What apps script does is that every time someone visits the URL, the doGet function is run.
HTML Example
function doGet(){
let HTMLString = "<style> h1,p {font-family: 'Helvitica', 'Arial'}</style>"
+ "<h1>Hello World!</h1>"
+ "<p>Welcome to the Web App";
HTMLOutput = HtmlService.createHtmlOutput(HTMLString);
return HTMLOutput
}
As you have already seen, HtmlService is what to use to serve up HTML.
Linking to Spreadsheet
The best way IMO to approach this is:
Create a spreadsheet.
Create the script from the spreadsheet menu - this ensures that the script and sheet are linked.
Decide how you want to present the information from the Spreadsheet and get it with something like:
let file = SpreadsheetApp.getActive(); // getActive only possible if script and sheet are linked
let sheet = file.getSheetByName("Sheet1");
let range = sheet.getDataRange();
let values = range.getValues();
Figure out how to translate that into HTML.
Write your doGet function.
Deploy
Profit!
Docs
Google Apps Script Web Apps
HTML Service
Spreadsheet Service
I'm learning how to use Google Web App and am following this YouTube video Google Sheets Web App Example - Google Apps Script Web App Tutorial - Part 1 and I am really enjoying the series. It is very easy to follow along with the videos. But I am running into a little issue with the first video. For some reason when I try to do log the button click on the HTML page, nothing happens. I sure it's going to be something silly. But I have been at this now for a few hours and I can't figure out what is wrong.
Code.gs:
function doGet(e) {
Logger.log(e.parameter);
return HtmlService.createHtmlOutputFromFile("page");
}
function userClicked(name){
Logger.log(name + " & noah clicked it!");
}
page.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<h1>Hello</h1>
<label>Name:</label><input type="text" id="username">
<button id="btn">Run It!</button>
<script>
document.getElementByID("btn").addEventListener("click",doStuff);
function doStuff(){
var uname document.getElementByID("username").value;
google.script.run.userClicked(uname);
}
</script>
</body>
</html>
Please tell me there is something silly that I am just not seeing.
I think that your script of HTML side is not correct. By this, the script is not run. So I think that Logger.log is not run. Please modify your script of HTML side as follows and test it again.
Modification points:
getElementByID is getElementById.
var uname document.getElementByID("username").value; is var uname = document.getElementById("username").value;.
Modified script:
From:
<script>
document.getElementByID("btn").addEventListener("click",doStuff);
function doStuff(){
var uname document.getElementByID("username").value;
google.script.run.userClicked(uname);
}
</script>
To:
<script>
document.getElementById("btn").addEventListener("click",doStuff); // Modified
function doStuff(){
var uname = document.getElementById("username").value; // Modified
google.script.run.userClicked(uname);
}
</script>
By this modification, you can see the log at Apps Script Dashboard.
IMPORTANT:
In your case, when you access to the Web Apps using your browser by logging in to your Google account, the log can be seen. But if you want to access to a script and curl, please include the access token to the request header. By this, the log can be seen. Please be careful this.
When you cannot include the access token to the request header, in that case, please link the Google Apps Script project to Google Cloud Platform (GCP) Project. By this, the log can be seen at Apps Script Dashboard.
References:
getElementById()
Apps Script Dashboard
Here is my code for show a sidebar. When click at OK button, I will insert a new record to my sheet.
It works well when I disable V8 by Run->Disable new App Script .. V8.
When I enable V8, onClicked in Code.gs not fired anymore.
I have checked the V8 Runtime Overview but I didn't find anything.
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<button onclick="okClicked()"> OK </button>
<button onclick="close()">Close </button>
<script>
function okClicked(){
window.alert("A");
google.script.run.okClicked();
}
function close(){
google.script.host.close();
}
</script>
</body>
</html>
Code.gs
function showSidebar() {
var html = HtmlService.createHtmlOutputFromFile('Index')
.setTitle('My custom sidebar')
.setWidth(300);
SpreadsheetApp.getUi().showSidebar(html);
}
function okClicked(){
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Data");
sheet.appendRow(["A", "B"]);
}
Any help or suggestion would be great appreciated.
Someone posted an issue similar to createHtmlOutputFromFile and V8 on Google's Issue Tracker. You can check if this issue is adequate for your case and hit the Star to let them know you have the same issue.
If you believe that this issue does not correspond with yours, you can also create a new issue with your case there.
2021 Answer
FWIW, I found that Google Apps Script was erroring out like this when my partner and I were both logged into the same Google account.
We also found that this can happen when new features have been built into your Google Apps Script / Sheets backend code that require updated permissions that haven't been granted yet. It's a bit hacky, but I fixed this by:
Sharing the sheet with another account I own
Logging into that account, then trying to run the function
Agreeing to grant the permissions asked by Google Auth / Scopes in the dialog that follows
I can't get the simple example copied from the google dev site to work.
The error is: Cannot call FormApp.getUi() from this context
I am NOT attempting to deploy this a web form/app but I am simple trying to run this via the editor!!!
Not sure what I'm doing wrong?!?!?!
The following has been pasted into index.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
Hello, World!
</body>
</html>
The following is pasted into Code.gs:
// Use this code for Google Docs, Forms, or new Sheets.
function onOpen() {
FormApp.getUi()
.createMenu('Dialog')
.addItem('Open', 'openDialog')
.addToUi();
}
function openDialog() {
var html = HtmlService.createHtmlOutputFromFile('Index');
FormApp.getUi()
.showModalDialog(html, 'Dialog title');
}
Answered my own question.
The script must be bound to a Form (which mine wasn't!)
So now I need to figure out how to create a Dialog for an Unbound script.
I don't think this is possible!
If I deploy it as a Web App then obviously I have no access to the user UI.
So how would I take the output from ContentService.createTextOutput() and cause a download of a file to occur?