update dropdown from spreadsheet in apps script - javascript

I'm trying to learn Google's HTML Service UI service and am struggling to figure out how to update a dropdown list in a UI from data in a spreadsheet. I copied the following code from this Google Tutorial, which works fine. However, if I want to populate a dropdown using and to replace and below, it doesn't seem to work.
<p>List of things:</p>
<ul id="things">
<li>Loading...</li>
</ul>
<script
src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<script>
// The code in this function runs when the page is loaded.
$(function() {
google.script.run.withSuccessHandler(showThings)
.getLotsOfThings();
});
function showThings(things) {
var list = $('#things');
list.empty();
for (var i = 0; i < things.length; i++) {
list.append('<li>' + things[i] + '</li>');
}
}
</script>

The following Apps Script project files use Spreadsheet data to fill a drop-down select box in the UI. In the main Apps Script project file (default name is Code.gs), include:
function doGet(request) {
return HtmlService.createTemplateFromFile('DropDown')
.evaluate().setSandboxMode(HtmlService.SandboxMode.NATIVE);
}
function getMenuListFromSheet() {
return SpreadsheetApp.openById(*SPREADSHEET_ID*).getSheets()[0]
.getRange(2,1,4,1).getValues();
}
You will need to replace *SPREADSHEET_ID* with the ID of the spreadsheet containing the data you want to use to fill the select box. This example takes the data in the first sheet's A2:A5 range as the data to use (defined in the getRange() function).
Note also that this example uses NATIVE sandbox mode, which is more forgiving than the default EMULATED mode.
This example also needs an HTML file in the Apps Script project(named 'DropDown.html' here):
<p>List of things:</p>
<ul id="things">
<li>Loading...</li>
</ul>
<select id="menu">
<option></option>
<option>Google Chrome</option>
<option>Firefox</option>
</select>
<script
src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<script>
// The code in this function runs when the page is loaded.
$(function() {
google.script.run.withSuccessHandler(showThings)
.getMenuListFromSheet();
google.script.run.withSuccessHandler(showMenu)
.getMenuListFromSheet();
});
function showThings(things) {
var list = $('#things');
list.empty();
for (var i = 0; i < things.length; i++) {
list.append('<li>' + things[i] + '</li>');
}
}
function showMenu(menuItems) {
var list = $('#menu');
list.find('option').remove(); // remove existing contents
for (var i = 0; i < menuItems.length; i++) {
list.append('<option>' + menuItems[i] + '</option>');
}
}
</script>
This HTML file consists of a single list and a single select box, both with default contents. When the page is loaded, the contents of both will be replaced with the contents provided by the getMenuListFromSheet() function, which draws its returned value from the spreadsheet.
You can create these Apps Script project files bound to a Spreadsheet container, and then publish them as a web app.

Related

how to append html page inside current page using google web app?

I know how to include CSS or JS files using app script in a web script. but that way includes files content on page lode.
My question is it possible to include partial html page inside the currently opened page?
app script to include CSS or JS
/* #Include JavaScript & CSS & HTML-Partial-Views */
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
and I use like this
<?!= include('Css'); ?>
and here is my attempt.
html
<button onclick="getList("users")">show some html content</button>
<div id="users"></div>
<script>
function getList(users){
var listUsers = google.script.run.showHtml(users);
// how to return showHtml result [list of users]
for (var i; i <= listUsers.length; 1++)
{
document.querySelector("#users").innerHTML += <div>listUsers[i]</div>;
}
}
</script>
gs
function users(sheetName, pageName){
// get users from sheet
var ss= SpreadsheetApp.openById("435yh35h45b35nh6hg5bwh455j");
var dataSheet = ss.getSheetByName(sheetName);
var dataRange = dataSheet.getDataRange().getValues();
return dataRange;
}
From one of the code snippets
// how to return showHtml result [list of users]
Try this:
<button onclick="getList('users')">show some html content</button>
<div id="users"></div>
<script>
function getList(users){
var listUsers = google.script.run
.withSuccessHandler((listUsers) => {
let list = '';
for (var i; i < listUsers.length; i++) {
list += `<div>${listUsers[i]}</div>\n`;
}
document.querySelector("#users").innerHTML = list;
})
.showHtml(users);
}
</script>
Changes done
Replaced "users" by 'users'
Added withSuccessHandler with an arrow function as callback.
The arrow function build a string using a for statement (because it was used in the original code) including a div tag using a template literal.

Updating or inserting data from a Spreadsheet into a Dialog box inside a dropdown

Goal: The purpose is that a sheet will contain information, this information is placed inside a namedrange, the namedrange will be dynamic (the entire column is given a namedrange).
I created a html popup which contains a dropdown list. This dropdown list must contain the list of information from the namedrange.
I am unable to understand how this is to be done. Here is the code below:
function fncOpenMyDialog() {
var htmlDlg = HtmlService.createHtmlOutputFromFile('HTML_myHtml')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(200)
.setHeight(150);
SpreadsheetApp.getUi()
.showModalDialog(htmlDlg, 'New File');
};
function onInstall(e) {
onOpen(e);
}
function onOpen(e) {
var ui = SpreadsheetApp.getUi();
ui.createMenu('New')
.addItem('New Save File Extension','fncOpenMyDialog')
.addToUi();
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<select name="nameYouWant" placeholde="File Type">
<option value="something">Word</option>
<option value="anything">MS Excel</option>
<option value="anything">MS Powerpoint</option>
<option value="anything">MS Slides</option>
</select>
<hr/>
<p>Choose a file, which will then be saved into your Google Drive.</p>
<button onmouseup="closeDia()">Close</button>
<button onmouseup="onOpen()">Save</button>
<script>
window.closeDia = function() {
google.script.host.close();
};
window.saveDia = function() {
onOpen();
};
</script>
</body>
</html>
As you can see in my html file, that the extensions are currently hardcoded.
I am trying to make this dynamic, how do I achieve this?
I believe your goal as follows.
You want to put the values to the dropdown list by retrieving from the named range of the Spreadsheet.
In this case, is the named range the same with this thread?
For this, how about this answer?
Modification points:
From google.script.host.close(), I understood that the HTML file of HTML_myHtml is included in the Google Apps Script project. By this, I would like to propose to achieve your goal using google.script.run.
If the named range is the same with your previous question, you can use it by modifying a little.
When above points are reflected to your script, it becomes as follows.
Modified script:
HTML and JavaScript side: HTML_myHtml
Please modify HTML_myHtml as follows.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<select id="select" name="nameYouWant" placeholde="File Type"></select>
<hr />
<p>Choose a file, which will then be saved into your Google Drive.</p>
<button onmouseup="closeDia()">Close</button>
<button onmouseup="onOpen()">Save</button>
<script>
google.script.run.withSuccessHandler(v => {
const obj = document.getElementById("select");
v.forEach(e => {
const option = document.createElement("option");
option.text = e;
option.value = e;
obj.appendChild(option);
});
}).readNamedRange();
window.closeDia = function() {
google.script.host.close();
};
window.saveDia = function() {
onOpen();
};
</script>
</body>
</html>
Google Apps Script side: Code.gs
At above HTML, readNamedRange() is used. So please put the following script. If you have the same function names, please modify them. In this script, the values are retrieved from the named range of listDown, and sent to HTML side using google.script.run.
function readNamedRange() {
var activeSheet = SpreadsheetApp.getActiveSheet();
var result = activeSheet.getRange("listDown").getValues();
var end = activeSheet.getLastRow();
var values = [];
for (var i = 0; i < end; i++) {
if (result[i][0] != "") {
values.push(result[i][0]);
}
}
return values;
}
Note:
About window.saveDia = function() {onOpen()};, unfortunately, I couldn't understand about what you want to do.
Reference:
Class google.script.run

Button Action to retrieve data from spreadsheet using google app script

How to retrieve a complete row from a spreadsheet based on a filter on an action such as a click of a button.
I read that GAS is server-side scripting and it is complex to gain access to a spreadsheet.
Is that so. Please guide me.
I have done till this:
$("#form-action")
.button()
.click(function() {
var ss = SpreadsheetApp.openById("");
var sheet = SpreadsheetApp.getActiveSpreadsheet();
SpreadsheetApp.setActiveSheet(sheet.getSheetByName('Test'));
SpreadsheetApp.getActiveSheet().getRange("D1").setFormula('Query(A:C,"SELECT A,B,C WHERE B="' + "mydata'" + ',1)');
SpreadsheetApp.getActiveSheet().getRange("E:J").getValues();
});
Gaining access to the spreadsheet is not difficult at all. You have to remember that while Google Apps Script runs on Google servers, the client-side code (e.g. HTML and JavaScript code you use in your UI templates) will be sent to your browser for rendering, so you can't really mix the two and write jQuery code in GAS(.gs) files or vice versa.
To clarify, commands like
var ss = SpreadsheetApp.openById("");
must be kept in .gs files. To use client-side HTML and JavaScript, you must create separate HTML files in your project (go to File - New - HTML file). Here's more information on serving HTML in GAS https://developers.google.com/apps-script/guides/html/
Luckily, Google provides the API that allows you to communicate between client and server sides by calling 'google.script.run.' followed by the name of the function in '.gs' file.
Example function in '.gs' file
function addRow() {
var sheet = SpreadsheetApp.getActive()
.getSheets()[0];
sheet.appendRow(['Calling', 'server', 'function']);
}
In your HTML template file, here's how you would call this function
<script>
google.script.run.addRow();
</script>
Consider the example that is more relevant to your situation. In my spreadsheet, the QUERY formula changes dynamically based on the value entered by the user. The form with input field is displayed in the sidebar.
Project structure
Code for 'sidebar.html' is below. Note that using the 'name' attribute of the <input> element is mandatory. On form submit, the value of the attribute ('filterBy') will be transformed into propetry of the form object that we can reference in our server function to get user input.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js">
</script>
</head>
<body>
<form id="myForm">
<input type="text" name="filterBy">
<input type="submit" value="submit">
</form>
<table id="myTable"></table>
<script>
$('document').ready(function(){
var form = $('#myForm');
var table = $('#myTable');
var runner = google.script.run;
form.on('submit', function(event){
event.preventDefault(); //prevents <form> redirecting to another page on submit
table.empty(); // clear the table
runner.withSuccessHandler(function(array){ //this callback function will be invoked after the 'retriveValues()' function below
for (var i = 0; i < array.length; i++) {
var item = '<tr><td>' + array[i] +'</td></tr>';
table.append(item);
}
})
.retrieveValues(this); //the function that will be called first. Here, 'this' refers to the form element
});
});
</script>
</body>
</html>
Code in '.gs' file:
var ss = SpreadsheetApp.getActive();
var sheet = ss.getSheets()[0];
function onOpen() {
var ui = SpreadsheetApp.getUi();
var htmlOutput = HtmlService.createTemplateFromFile('sidebar')
.evaluate();
ui.showSidebar(htmlOutput);
}
function retrieveValues(req) {
var res = [];
var filterBy = req.filterBy; //getting the value of the input field.
sheet.getRange(1, 2, 1, 1)
.setFormula("QUERY(A1:A, \"SELECT A WHERE A > " + filterBy + "\")");
sheet.getRange(1, 2, sheet.getLastRow(), 1)
.getValues()
.map(function(value){
if (value[0] != "") res = res.concat(value[0]); // get only the values that are not empty strings.
});
return res;
}
Here's the result of entering the value and submitting the form. The server-side function returns the array of values greater than 5. The callback function that we passed as parameter to 'withSuccessHandler' then receives this array and populates the table in the sidebar.
Finally, I'm not sure why you are using the QUERY formula. Instead of modifying 'SELECT' statement, you could simply take the values from the target range an filter them in GAS.

How to import Clipboard.js library into Google App Script?

Since manipulating clipboard is forbidden in Google App, I want to find a workaround by using Clipboard.js library.
My questions are:
1. How should I import a Clipboard.js library to Google App Script?
2. And how to call the functions in other pages (eg. trying to call the function calculateWeight() from BMI.gs in index.html?
What I've tried:
I've tried to paste the source code of the Clipboard.js into a file called Clipboard.js.html and put everything inside the tag.
What I want achieve:
Copy a text string with a click on the "COPY" button.
>>what I want to achieve
I've spent a few hours looking for solutions but still can't find related info. Any help would be greatly appreciated. Thank you!
Your script can have more than one html file, and per the HTML Services: Best Practices, you should have your HTML, CSS and (client side) Javascript in separate files. So in your case your index.html file will be all the HTML code and will have a couple lines added. It could start as shown below:
<!DOCTYPE html>
<html>
<head>
<script src="//cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.4.0/clipboard.min.js"></script>
<?!= include('myCSS'); ?>
<title>Give it a Title</title>
</head>
<body>
...
All the Body stuff
...
</body>
<?!= include('myScript'); ?>
</html>
At the top of this is a line to include clipboard JS from a hosted location. I found that via a web search for clipboard.js. This is where I get access to the clipboard.js library There is a line right underneath this:
<?!= include('myCSS'); ?>
In a server side file (.gs file) I have the following so that I can include other HTML files from the one I load in my doGet() function:
function include(filename) {
return HtmlService.createTemplateFromFile(filename).evaluate()
.getContent();
}
I am loading the HTML in my doGet using this code to use Templated HTML:
function doGet(passed) {
if(passed.parameter.festival && passed.parameter.year){
passedParameter = passed.parameter.festival + ' ' + passed.parameter.year;
}
var result=HtmlService.createTemplateFromFile('index').evaluate()
.setTitle('My Title')
.setWidth(1285)
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
return result;
}
Under the File pull-down you create a new HTML file called myCSS and add your CSS there:
<style>
h1 {
color: #0F6B5E;
font-size: 300%;
text-align:center;
vertical-align: middle;
font-family: 'Raleway', sans-serif;
font-weight:bold;
padding-top: 0.5em;
padding-bottom: 0.5em;
}
</style>
Create a new HTML file called myScript and add the screipt you want used in your HTML page here. This is the Client Side script as opposed to SErver Side script, which is all in the Script files. (HTML files will show the .html extension in the list of files while server side Script files will have .gs) If your calculateWeight() function is used to calculate and display items in the HTML page, then place it in this file:
<script>
//Script to load after the page has loaded
$(function() {
google.script.run.withSuccessHandler(showMenuYear).withFailureHandler(loadFailed).getDropDownContent();
});
calculateWeight() {
//code goes here
}
function showMenuYear(menuItems) {
var list = $('#optionListYear');
var desiredValue = '<?!= passedParameter ?>';
list.find('option').remove(); // remove existing contents
list.append('<option value="-1">Select a Festival and Year</option>');
for (var i = 0; i < menuItems.length ; i++) {
list.append('<option value=' + menuItems[i].sheetrow + '>' + menuItems[i].fullFestival + '</option>');
if (menuItems[i].fullFestival === desiredValue){
list.val(menuItems[i].sheetrow);
}
}
setFormList();
}
function setFormList() {
// alert('In setFormList ');
// alert($('#optionListYear').val());
var replacement = document.getElementById("OverallGrid");
replacement.innerHTML = "Retrieving Registrations...";
if ($('#optionListYear').val() === "-1") {
// if(passedData.year && passedData.festival){replacement.innerHTML = passedData.festival & " " & passedData.year;};
replacement.innerHTML = "Select a Festival/Year above.";
return;
}
google.script.run.withSuccessHandler(showRegistrationsTable).withFailureHandler(loadFailed).getValidRegistrations($('#optionListYear').val());
}
function loadFailed(error){
var replacement = document.getElementById("OverallGrid");
var displayMessage = "Error loading data: " + error.name + ' ' + error.message;
if (error.message.includes("is missing (perhaps it was deleted?)") ) {
displayMessage = "You do not have access to these registrations."
}
replacement.innerHTML = displayMessage;
}
</script>
In this code, the lines starting with google.script.run will run a Server Side function, passing a variable to the function if needed. If Successful, the Client side function defined in withSuccessHandler(successFunction) will be used with any returned data being passed. So in my example the showMenuYear(menuItems) function is run on the Client side with menuItems being set to the returned value from the Server side function getDropDownContent(). If the Server side returns an error, the loadFailed(error) function is executed. This all comes from the line:
google.script.run.withSuccessHandler(showMenuYear).withFailureHandler(loadFailed).getDropDownContent();

how to covert visualization table of app script to spread sheet google app script code

I have HTML web app where I have converted a spreadsheet to a HTML table. Now I would like to convert this HTML Table to a spreadsheet. Is it possible to convert it back to a spreadsheet?
You can say that I can directly make use of the spreadsheet but the problem is that I have applied some filters. Now whenever I apply a filter to a specific column, it will be displayed so now I want that column to be moved to the new spreadsheet using google app script
Here is my table, how can convert this table to spreadsheet using Google App Script
I use two sheets for this example one sheet is named sht2tbl and the other sheet is named tbl2sht. You need to have both ready to go when you run the code.
Here's sheet2table and table2sheet.gs:
function sheetToTable()//This produces a modeless dialog
{
var s='';
s+='<table width="100%">';
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getSheetByName('sht2tbl');
var rng=sht.getDataRange();
var rngA=rng.getValues();
for(var i=0;i<rngA.length;i++)
{
s+='<tr>';
for(var j=0;j<rngA[0].length;j++)
{
if(i==0)
{
s+='<th id="cell' + i + j + '">' + rngA[i][j] + '</th>';//put ids in each th
}
else
{
s+='<td id="cell' + i + j + '">' + rngA[i][j] + '</td>';//put ids in each td
}
}
s+='</tr>';
}
s+=' </body></html>'
var html=HtmlService.createHtmlOutputFromFile('html2body');//create output from file
html.append(s);//and append s for the rest
SpreadsheetApp.getUi().showModelessDialog(html, 'Sheet to Table')
}
function getParams()//this gives the client side array dimensions
{
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getSheetByName('sht2tbl');
var rng=sht.getDataRange();
var A=[];
A.push(rng.getWidth());
A.push(rng.getHeight());
return (A);//range width and height in an array
}
function putData(data)//this gets cell contents from the client side and displays them on another sheet named 'tbl2sht'
{
var ss=SpreadsheetApp.getActiveSpreadsheet();
var sht=ss.getSheetByName('tbl2sht');
var h=data.length;
var w=data[0].length;
var rng=sht.getRange(1,1,h,w);//create a range properly dimensioned
rng.setValues(data);//use setValues to load sheet
}
This is the file htmltobody.html. It's a lot easier to create javascript this way. But I like to integrate the data creation with server side google script.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
$(function() {
google.script.run
.withSuccessHandler(getCellValues)//returns to get values from client side
.getParams();//get width and height of data array
});
function getCellValues(A)
{
var w=A[0];
var h=A[1];
var data=[];
for(var i=0;i<h;i++)
{
data[i]=[];
for(var j=0;j<w;j++)
{
var s='#cell' + Number(i) + Number(j);
data[i][j]=$(s).text();//use jquery text to get th and td values
}
}
google.script.run
.putData(data);//send data to server side to load data in tbl2sht
}
console.log('My Code');//helps me to find code in chrome console
</script>
</head>
<body>
This is the sht2tbl which was use to create the modeless dialog:
This is the dialog that gets created:
And this is the data from the dialog displayed on a sheet named tbl2sht:

Categories

Resources