Problem description:
I want to create an add-on on my google sheet (g-1). When the user opens the add-on, I want to immediately read another google spreadsheet (g-2) and populate dropdowns on g-1 based on those columns.
I have enabled the Googlesheet Api
in Code.js:
function readSpreadsheet() {
var questions = Sheets.Spreadsheets.Values.get("_ID_", "SHEET!A2:k").values
if (!questions) {
return 'No data found.';
} else {
return questions
}
}
the function above works, because if I add that to the title on the add-on I see the correct number of columns:
HtmlService.createHtmlOutputFromFile('QuestionBank').setTitle(readSpreadsheet().length)
or I can print the first row
readSpreadsheet()[0]
............
So far so good.
Now in my html file, QuestionBank.html,
Problem #1. I am not able to call readSpreadsheet, it returns undefined. var question_rows returns undefined.
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<script>
/**
read all rows, upon clicking on sync button. But this is not necessary if I can populate the dropdowns on load
**/
$(function() {
$('#sync').click(readSpreadsheet);
});
function readSpreadsheet() {
this.disabled = true;
$('#error').remove();
var question_rows = google.script.run
.withSuccessHandler(
function(textAndTranslation, element) {
element.disabled = false;
})
.withFailureHandler(
function(msg, element) {
element.disabled = false;
})
.withUserObject(this)
.readSpreadsheet();
for (var row = 0; row < question_rows.length; row++) {
alert(question_rows[row])
}
}
</script>
Problem #2: I have several dropdowns that I want their value to be unique value of the g-2 columns. I want those dropdowns to be populated when the add-on opens.
<select class="filter">
<option value="volvo">Volvo</option>
<option value="saab">Saab</option>
<option value="mercedes">Mercedes</option>
<option value="audi">Audi</option>
</select>
so instead of Volvo, etc, I want the first column of my data, unique values
Problem #3: if on load is not possible, I can include a button to read the data and populate the dropdowns
<button class="sync-button" id="sync">sync</button>
How about the following answers?
Answer for Problem #1
google.script.run doesn't return values. When it uses values from google.script.run, in your case, textAndTranslation of withSuccessHandler is the returned value. So you can modify readSpreadsheet() as follows.
function readSpreadsheet() {
this.disabled = true;
$('#error').remove();
google.script.run
.withSuccessHandler(withSuccessHandler)
.withFailureHandler(
function(msg, element) {
element.disabled = false;
})
.withUserObject(this)
.readSpreadsheet();
}
function withSuccessHandler(textAndTranslation, element) {
element.disabled = false;
var question_rows = textAndTranslation;
for (var row = 0; row < question_rows.length; row++) {
alert(question_rows[row])
}
}
Answer for Problem #2
You can achieve it by putting google.script.run in $(function() {}). The sample is as follows. This is a sample. So please modify the variables to yours.
<select class="filter"></select>
<script>
$(function() {
google.script.run.withSuccessHandler(sample).readSpreadsheet();
});
function sample(data) {
for (var i=0; i < data.length; i++) {
$('.filter').append($('<option>').html(data[i]).val(data[i]));
}
}
Answer for Problem #3
Of course, you can set values to <select class="filter"></select> using a button.
If I misunderstand your questions, I'm sorry.
Related
I am using the Semantic UI multiple search selection dropdown within an html dialog in an Apps Script project. It works perfectly but I can only get the values to return in alphabetical order.
I have found two ways to get the values:
Using <form> tag
Using the .dropdown("get value") method as shown in the documentation
Both output alphabetically, not in the order that the user selected them.
[This picture shows an example of a user selection.]
It outputs as Chinese, Hmong, and Spanish but I need it to come out as Hmong, Spanish, and Chinese.
<html><link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet" />
<head><base target="_top"></head><body>
<form>
Translate to:
<select class="ui fluid search dropdown" multiple="" id='languages' name='languages'>
<option value='Chinese (Simplified)'>Chinese (Simplified)</option>"
<option value='Hmong'>Hmong</option>"
<option value='Spanish'>Spanish</option>"
<option value='Arabic'>Arabic</option>"
</select></form>
<button onclick='usingFormTags()'>Save Preferences</button>
<button onclick='passingAsVariable()'>Save Preferences</button>
<script>
function usingFormTags() {
google.script.run.getForm(document.forms[0]);
}
function passingAsVariable() {
var data1 = $("#languages").dropdown("get value");
google.script.run.getData(data1);
}
</script></body></html>
This is using the .dropdown("get value")
function doGet(){
return HtmlService.createHtmlOutput("html");}
function getData(data1){
Logger.log(data1)}
This is using the <form> tag
function doGet(){
return HtmlService.createHtmlOutput("html"); }
function getForm(form) { var languages = form.languages Logger.log(languages)}
I've also tried the .dropdown("get text") in place of "get values" but it returns nothing. Everything I can find online discusses how to get an array of values but nothing about how to get them in the user-defined order.
I believe your goal is as follows.
You want to retrieve the selected values in order.
In this case, how about the following modification? In this modification, I used onChange of the built-in actions. When this is reflected in your script, it becomes as follows.
Modified script:
From:
<script>
function usingFormTags() {
google.script.run.getForm(document.forms[0]);
}
function passingAsVariable() {
var data1 = $("#languages").dropdown("get value");
google.script.run.getData(data1);
}
</script>
To:
<script>
let ar = [];
$('#languages').dropdown({
onChange: function (value) {
const obj1 = ar.reduce((o, e) => (o[e] = true, o), {});
const obj2 = value.reduce((o, e) => (o[e] = true, o), {});
value.forEach(e => {
if (!obj1[e]) ar.push(e);
});
ar.forEach(e => {
if (!obj2[e]) ar.splice(ar.indexOf(e), 1);
});
}
});
function usingFormTags() {
console.log(ar);
google.script.run.getForm(ar);
}
function passingAsVariable() {
console.log(ar);
google.script.run.getData(ar);
}
</script>
In this modification, the same value is returned for both buttons. So, please modify this for your actual situation.
And, in this modification, even when the selected values are removed, the order of values is kept.
Testing:
Also, you can test this modification at jsfiddle.net as follows.
https://jsfiddle.net/dm7ubyst/
Reference:
Specifying Select Action
I have a sheet with a column of group names, and things they need to report that they did or didn't do. I'm having trouble creating a script that would get the column of names to make a multiple choice question AND direct to the correct next page based on the answer.
Names Option1 Option2 Option 3 Option4
Frank Something1 Something2 Something3
Hank AnotherThing AnotherThing1 AnotherThing3 Anotherthing4
Bob Foo Bar
First question is Multiple Choice with column 1 with the answers.
Depending on the answer I need it to direct to a new section with the other columns with content on the same row as the chosen answer.
Choose Frank and submit to be sent to a Checkbox question with 3 options.
Anyone have the faintest on how to do this? I can make the questions manually but when it comes to directing the GO_TO_PAGE part I can't get that to work.
Thanks in advance!
Here's a possible approach to your problem. I'm using a sidebar which could just as easily be a dialog if you want to make it wider and could ultimately be a webapp.
Take a look at the dialog or sidebar and you'll see that you get a drop down list of name from your spreadsheet and when you select a name and click on GetToDoList then you get a list of to do items from your spreadsheet along with buttons that have links to different sheets that I've included in your spreadsheet.
Code.gs:
function getNames()
{
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('ToDoList');
var rg=sh.getDataRange();
var vA=rg.getValues();
var names=['Select Name'];
for(var i=1;i<vA.length;i++)
{
names.push(vA[i][0]);
Logger.log('%s',vA[i][0]);
}
return names;
}
function loadToDoSideBar()
{
var userInterface=HtmlService.createHtmlOutputFromFile('todolist').setTitle('ToDoLists');
SpreadsheetApp.getUi().showSidebar(userInterface);
}
function getToDoList(name)
{
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('ToDoList');
var rg=sh.getDataRange();
var vA=rg.getValues();
var hl='';
for(var i=0;i<vA.length;i++)
{
if(vA[i][0]==name)
{
for(var j=1;j<vA[i].length;j+=2)
{
if(vA[i][j] && vA[i][j+1])
{
hl+=Utilities.formatString('<br /><label>%s<input class="btn1" type="button" value="%s" onClick="goToSheet(\'%s\')" /></label>',vA[i][j],'Go to' + vA[i][j+1],vA[i][j+1]);
}
}
}
}
return hl;
}
function goToSheet(name)
{
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName(name).activate();
}
todolist.html
<!DOCTYPE html>
<html>
<head>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$(function() {
$('#txt1').val('');
google.script.run
.withSuccessHandler(updateSelect)
.getNames();
});
function updateSelect(vA)
{
var select = document.getElementById("sel1");
select.options.length = 0;
for(var i=0;i<vA.length;i++)
{
select.options[i] = new Option(vA[i],vA[i]);
}
}
function getToDoList()
{
var name=$('#sel1').val();
google.script.run
.withSuccessHandler(updateToDoList)
.getToDoList(name)
}
function updateToDoList(hl)
{
document.getElementById('viewlist').innerHTML=hl;
}
function goToSheet(name)
{
google.script.run.goToSheet(name);
}
console.log('My Code');
</script>
<style>
div.scroll{background-color: #ffffff;width: 250px;height:100%;display:block;margin:0 0 0 5px;padding:0 0 0 10px;}
#sel1 option{width:250px;}
.type{color:#ff0000;font-weight:500;}
.date{color:#080b58;font-weight:500;}
.note{font-weight:500;}
.btn1{margin:10px 10px 10px 10px;vertical-align:25%;}
body{margin:5px 5px 5px 10px;width:275px;}
</style>
</head>
<body>
<select id="sel1" style="width:125px;height:35px;margin:10px 0 10px 0;">
<option value="" selected></option>
</select>
<input type="button" value="GetToDoList" onClick="getToDoList()" />
<br /><div id="viewlist" class="scroll"></div>
</body>
</html>
Here's what I did with your data. I just added another column between each value for the Locations or Links (not sure what you want). But the code shows you how you can incorporate links to different sheets into the solution.
And this is what the dialog looks like:
This question already has answers here:
better way to load 2 dropdown in mvc
(5 answers)
Closed 5 years ago.
I know I can make a dropdown with a list of SelectedListItem> and #Html.DropDownList("someID") and os on..
My question is, what if you had 2 dropdowns, and the second dropdown depended on the selected item from the first dropdown?
How do you populate it? With JS? How would you go about it?
Would you change the populate with another list, change the whole dropdown or maybe have a partialview for each dropdown combination, so it's a matter of replacing with the right dropdown.
I have added NetFiddle example. Works here
I would suggest to use jquery $.getJson() to fill second dropdown without refresh to page. You can implement like following example.
//html
<select id="EventId" name="eventId">
<option value="1">option1</option>
<option value="2">option2</option>
<option value="3">option3</option>
</select>
<label>Second</label>
<select id="SecondDropdown">
</select>
// jquery
$("#EventId").on("change", function(){
showValue($(this).val());
})
function showValue(val)
{
console.log(val);
$.getJSON('#Url.Action("GetDropdownList", "Home")' + "?value=" + val, function (result) {
$("#SecondDropdown").html(""); // makes select null before filling process
var data = result.data;
for (var i = 0; i < data.length; i++) {
$("#SecondDropdown").append("<option>"+ data[i] +"</option>")
}
})
}
//controller
[HttpGet]
public JsonResult GetDropdownList(int? value)
{
List<string> yourdata = new List<string>();
if(value == 2)
{
yourdata.Add("option2a");
yourdata.Add("option2b");
yourdata.Add("option2c");
return Json(new { data = yourdata}, JsonRequestBehavior.AllowGet);
}
else
{
return Json(new { data = ""}, JsonRequestBehavior.AllowGet);
}
}
I have created a google sheets sidebar using the google script HTML service which has various text boxes and checkboxes. i have no problem passing the variables through to the google script. The problem i have is that the value of my checkbox is always true or "Y" in my case whether is is checked or not. I really would like to know how to set the value as "Y" or "N". I wont upload complete script just the important bits because they are quite long.
This is my checkbox within my sidebar HTML...
</div>
<div class="block form-group" id="Headset">
<label for="headset-Check">Headset?:</label><br>
<input id= "headset-Check" type="checkbox" value="Y">
</div>
this is my javascript calling various google script functions the bit that uses the checkbox is near the bottom,
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"> </script>
<script>
$(function() {
// Assign handler functions to sidebar elements here, if needed.
$('#GetSerial-button').click(onGetSerialClick);
$('#Submit-button').click(onSubmitClick);
});
function onGetSerialClick() {
this.disabled = true;
google.script.run
.withSuccessHandler(
function(msg, element) {
$('#Serial-value').val(msg);
showStatus('Pulled Serial Successfully.');
element.disabled = false;
})
.withUserObject(this)
.getSerialValue();
}
function onSubmitClick() {
this.disabled = true;
var serial = $('#Serial-value').val();
var warrantyNotes = $('#warrantyNotes-value').val();
var warrantyRepair = $('#Warranty-Repair').val();
var headsetCheck = $('#headset-Check').val();
google.script.run
.withSuccessHandler(
function(msg, element) {
showStatus('Submitted ');
element.disabled = false;
})
.withUserObject(this)
.setHeadsetValues(warrantyRepair,headsetCheck,warrantyNotes,serial)
google.script.run
.addNewRow();
}
function showStatus(msg, classId) {
$('#sidebar-status').removeClass().html(msg);
if (classId) {
$('#sidebar-status').addClass(classId);
}
}
i then have a GS function to put the variables into correct sheet.
UPDATE
i am now able to get true or false by doing this in the java script
var headsetCheck = $('#headset-Check').is(':checked');
does anybody know how i can get "Y" or "N" thanks
How to cancel change event for combo box (SELECT) element. There is no onbefore or onchanging event for HTML SELECT element. If I put:
<SELECT onchange="return false;">
<OPTION value=a>A</OPTION>
<OPTION value=b>B</OPTION>
</SELECT>
event is not canceled.
You need to save the original value of the <select> somewhere. So that you can change the value back.
Cancelling the event, only does that. It just cancels the event, it doesn't change the value.
Example (using jQuery):
$(function(){
$('select').each(function(){
$(this).data('selected', $(this).val()); // back up value
}).change(function(){
if(confirm('Are you sure you want to change the element?')){
$(this).data('selected', $(this).val()); // back up new value
}
else{
$(this).val($(this).data('selected')); // restore old value
}
});
});
DEMO: http://jsfiddle.net/pL2B4/
Pure JavaScript solution (no jQuery):
var select = document.getElementsByTagName('select');
for (var i = 0, len = select.length; i < len; i++) {
var el = select[i];
el.setAttribute('data-selected', el.value);
el.addEventListener('change', function() {
if (confirm('Are you sure you want to change the element?')) {
el.setAttribute('data-selected', el.value);
}
else {
el.value = el.getAttribute('data-selected');
}
});
}
DEMO: http://jsfiddle.net/pL2B4/1/