Display the Answer to a Previous Q in gApps Forms - google-apps-script

I would like a question in my form to display the answer to a previous question. I am not asking about question logic or the Go To feature.
For example:
Q1: What type of entree would you like?
Meat
Fish
Vegetarian
Q2: Which cuisine do you prefer?
Indian
American
Mexican
Page break.
Q3: In the previous questions, you selected an [Q2] [Q1] entree.
If the answer to Q1 was Meat and to Q2 was Indian, then Q3 should display:
In the previous questions, you selected an Indian Meat entree.
This is possible in SurveyMonkey (with the use of square brackets). Can this be done in Google Forms?

I've written some dirty code in the boss´ time
It's a mix of server and client side script, I could have created the question Q3 in the function q1H & q2H.
var q1A = new Array(" Meat", " Fish", " Vegetarian")
var q2A = new Array(" Indian" ," American", " Mexican")
function doGet(e) {
var app = UiApp.createApplication().setTitle("Dev Test Sitemap");
var mainPanel = app.createVerticalPanel()
var homePanel = app.createHorizontalPanel()
var q1 = app.createLabel("Q1 What type of entree would you like?")
var q1ListBox = app.createListBox().setName("q1ListBox") ;
for (var i = 0; i < q1A.length; i++) {
q1ListBox.addItem(q1A[i]);
}
var handlerQ1 = app.createServerHandler("q1H");
q1ListBox.addChangeHandler(handlerQ1)
mainPanel.add(q1);
mainPanel.add(q1ListBox);
var q2 = app.createLabel("Q2 Indian American Mexican?")
var q2ListBox = app.createListBox().setName("q2ListBox") ;
for (var i = 0; i < q2A.length; i++) {
q2ListBox.addItem(q2A[i]);
}
var handlerQ2 = app.createServerHandler("q2H");
q2ListBox.addChangeHandler(handlerQ2)
mainPanel.add(q2);
mainPanel.add(q2ListBox);
mainPanel.add(app.createLabel("----------------------------------- pagebreak ---------------------") );
var horP = app.createHorizontalPanel()
//Q3: In the previous questions, you selected an [Q2] [Q1] entree.
var q3 = app.createLabel("In the previous questions, you selected an")
horP.add(q3)
var q2ans =new Array()
for (var i = 0; i < q2A.length; i++) {
q2ans[i] = app.createLabel(q2A[i]).setId("q2A"+[i]).setVisible(false);
horP.add(q2ans[i])
}
var q1ans =new Array() ;
for (var i = 0; i < q1A.length; i++) {
q1ans[i] = app.createLabel(q1A[i]).setId("q1A"+[i]).setVisible(false);
horP.add(q1ans[i])
}
var q32 = app.createLabel(" entree")
horP.add(q32)
mainPanel.add(horP);
app.add(mainPanel); //red
return app.close();
}
function q1H(e) {
var app = UiApp.getActiveApplication();
var q1ListBox = e.parameter.q1ListBox;
for (var i = 0; i < q1A.length; i++) {
if (q1ListBox == q1A[i] ){
app.getElementById("q1A"+[i]).setVisible(true);
}
}
return app;
}
function q2H(e) {
var app = UiApp.getActiveApplication();
var q2ListBox = e.parameter.q2ListBox;
for (var i = 0; i < q2A.length; i++) {
if (q2ListBox == q2A[i] ){
app.getElementById("q2A"+[i]).setVisible(true);
}
}
return app;
}
Working example

Related

renameCustomField() Change the Label Field Name

SVP i'm newsbe in Appsscript with API PEOPLE
This script don't work : I want to rename "CKD EPI" by "CKD EPI / CROKOFF / CREAT"
Can you tell me what's wrong ?
function renameCustomField() {
var debug = true;
var group = People.PeopleApi.getContactGroups().get("Mygroup").execute();
var oldFieldName = "CKD EPI";
var newFieldName = "CKD EPI / CROKOFF / CREAT";
for (var i = 0; i < group.members.length; i++) {
var contact = group.members[i];
var fields = contact.userDefined;
for (var j = 0; j < fields.length; j++) {
if (fields[j].key === oldFieldName) {
fields[j].key = newFieldName;
if (debug) {
console.log("Renaming field for contact: " + contact.names[0].displayName);
}
}
}
var updateContact = {
resourceName: contact.resourceName,
updatePersonFields: "userDefined",
userDefined: fields
}
People.PeopleApi.updateContact(updateContact).execute();
}
}

Is a unicode code point can be displayed normally?

I want to know whether a unicode code point can be displayed in chrome, and check it in golang, so I can escape some parts of a string before i send it to chrome.
I have found that there is three types of unicode code point can not be displayed normally in chrome :
Space . like code point 0x20(32). ' '
Font not exist. There is a question mark in the square box. (occupy two English letters width) like code point 0x378(888) "͸"
Invaild code point value. A diamond-shaped black box with a question mark inside (occupy one English letter width) like code point 0xd800(55296) "�"
I found that I can use js and OffscreenCanvas to render all of the unicode code point and check if them looks like above three types.
Then I got a function that can tell you whether a rune/character can be displayed normally by the operating system. https://github.com/fastslothlab/fslRune
js code:
(function(){
var start = 0;
var end = 1114111;
const imageSize = 20;
var tufoCiList = [32,888,55296];
var num = end-start+1;
var startTime = performance.now()
var hasDataCiList = [];
var c = new OffscreenCanvas(imageSize,imageSize);
var ctx = c.getContext("2d");
function getImageDataByCi(ci){
var s = String.fromCodePoint(ci);
ctx.clearRect(0,0,imageSize,imageSize);
ctx.fillText(s, 5, 15);
var imgD = ctx.getImageData(0,0,imageSize,imageSize);
var hasNoneZero = false;
var buf = imgD.data;
return buf;
}
var tofuBufList = [];
for (var i in tufoCiList){
tofuBufList.push(getImageDataByCi(tufoCiList[i]));
}
function debugImage(){
c.convertToBlob({
type: "image/png",
}).then(function(blob) {
var url = URL.createObjectURL(blob);
var imgObj = document.createElement("img");
imgObj.src = url;
document.body.appendChild(imgObj);
console.log(url);
});
}
function bufEqual(buf1, buf2){
if (buf1.byteLength != buf2.byteLength) return false;
for (var i = 0 ; i != buf1.byteLength ; i++){
if (buf1[i] != buf2[i]) return false;
}
return true;
}
for (var ci =start;ci<=end;ci++){
var buf = getImageDataByCi(ci);
var hasFound = false;
for (var i in tofuBufList){
if (bufEqual(buf,tofuBufList[i])){
hasFound = true;
break;
}
}
if (hasFound){
continue;
}
hasDataCiList.push(ci);
}
console.log((performance.now()-startTime)/num);
console.log(JSON.stringify(hasDataCiList));
})();

Cannot append option for select form

I want to load option data from a Sheet and append to the select element, but I cannot set the global variable
var select_values = [];
google.script.run.withSuccessHandler(loadOpt).loadData("Test");
function loadOpt(data_arrar) {
const arrayColumn = (arr, n) => arr.map(x => x[n]);
select_values = arrayColumn(data_arrar, 1);
}
var opt = document.getElementById("select_opts");
for (i = 0; i < select_values.length; i++) {
let option = document.createElement("option");
option.value = i;
option.text = select_values[i];
opt.appendChild(option);
}
The result is nothing appended to [select_opts].
I'm update the code.gs.
var TestSheets = SpreadsheetApp.openById("XXX");
function doGet(e) {
if (!e.parameter.page) {
// When no specific page requested, return "home page"
return HtmlService.createTemplateFromFile('Home').evaluate();
}
// else, use page parameter to pick an html file from the script
return HtmlService.createTemplateFromFile(e.parameter['page']).evaluate();
}
function loadData(Sheetname) {
var sheet = TestSheets.getSheetByName(Sheetname);
var rows = sheet.getRange("A1").getValue();
var Columns = sheet.getRange("B1").getValue();
var data_return = [];
for (var i = 0; i <= rows; i++) {
data_return[i] = [];
for (var j = 0; j <= Columns - 1; j++) {
data_return[i][j] = sheet.getRange(i + 2, j + 1).getValue();
}
}
return data_return;
}
Note that function loadData works well & has been tested.
The problem is that Javascript code outside of functions will be called on loading of the HTML document
It will not be reevaluated after running code in functions
If you want your loop to run after function loadData(Sheetname) - you need to put the loop into another function that is called after the execution of function loadData(Sheetname)
Sample:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<script>
var select_values = [];
google.script.run.withSuccessHandler(loadOpt).loadData("Test");
function loadOpt(data_arrar) {
const arrayColumn = (arr, n) => arr.map(x => x[n]);
select_values = arrayColumn(data_arrar, 1);
console.log(" select_values: " + select_values);
callLater();
}
console.log(" select_values in call outside: " + select_values);
function callLater(){
console.log(" select_values in callLater: " + select_values);
var opt = document.getElementById("select_opts");
for (i = 0; i < select_values.length; i++) {
let option = document.createElement("option");
option.value = i;
option.text = select_values[i];
opt.appendChild(option);
}
}
</script>
</body>
</html>

body.replaceText() in Google Docs

I wrote a function for using a spinText synonyms in docs. Ie. I have a text in the document like this: "{Hello|Hi} Mr {Thomas|Mathew|Andrew}"
Function give me 2 arrays: toreplace[], synonyms[] but the result of
for (var i = 0; i < rangeElements.length; ++i) {
body.replaceText(toreplace[i],synonyms[i]);
}
give me a text like this: Hi|Hi Mr Andrew|Andrew|Andrew but i would like to get "Hi Mr Andrew".
I tried Logger.log(toreplace[0]) and gets "{Hello|Hi}" and Logger.log(synonyms[0]) show "Hi" so it should be translated into body.replaceText('{Hello|Hi}','Hi');
What i am doing wrong?
function synonymize() {
var body = DocumentApp.getActiveDocument().getBody();
var rangeElements = [];
var rangeElement=null;
var start=[];
var end=[];
var lentabs=[];
var str;
var synonyms=[];
var toreplace=[];
var x=0;
while (rangeElement = body.findText('[{].+?[}]',rangeElement))
{
rangeElements.push(rangeElement);
start.push(rangeElement.getStartOffset());
end.push(rangeElement.getEndOffsetInclusive());
}
for (var i = 0; i < rangeElements.length; ++i) {
lentabs[i]=rangeElements[i].getElement().getText().substring(start[i]+1, end[i]).split('|').length
toreplace[i]=rangeElements[i].getElement().getText().substring(start[i], end[i]+1);
min=0;
max=lentabs[i]-1;
rand=Math.floor(Math.random()*(max-min+1)+min)
synonyms.push(rangeElements[i].getElement().getText().substring(start[i]+1, end[i]).split('|')[rand]);
}
for (var i = 0; i < rangeElements.length; ++i) {
body.replaceText(toreplace[i],synonyms[i]);
}
}
Ok. The problem was in the "|" which is treated as a regex pattern. I changed text in the document to "{Hello#Hi} Mr {Thomas#Mathew#Andrew}" and now it's working ok.

Check if current user is the administrator of a certain Google group

I want to go through all the Google groups I am a member of and get the list of all the users of each group :
var list = GroupsApp.getGroups();
for(var i = 0; i< list.length; i++){
for(var key in headerObj){
var text = "";
if(key == "users"){
var tab = list[i].getUsers();
if(tab.length > 0){
text = tab[0].getEmail();
for(var j = 1; j < tab.length; j++){
text += ", " + tab[j].getEmail();
}
}
headerObj[key].push(text);
}
}
}
But I always get this Exception :
You do not have permission to view the member list for the group: "group email"
Is there a way to go through all the Google groups of which, I am the administrator ?
Unfortunatly such a thing is not possible there is however the workaround of a try catch:
function myFunction() {
var allGroups = GroupsApp.getGroups();
for (var i in allGroups){
try {
var users = allGroups[i].getUsers();
for (var j in users){
Logger.log(users[j]);
}
}
catch (e) { }
}
}