How Load Images From Drop down button Google WebApp script? - javascript

I'm trying to load images from the drop-down button generated based on the Google Sheet's Folder ID
Google Sheet
Out Put
What I'm Trying To ACHIEVE is: I want to load the images on the front end display which is in a google drive folder based on the drop-down list on the front end of Web app.
THE PROBLEM
I'm unable to add the Folder ID into the getPictures() function and also I'm having issues connecting the Folder ID based on the dropdown.
Code.gs
function doGet(e) {
var htmlOutput = HtmlService.createTemplateFromFile('index');
var pictures = getPictures();
htmlOutput.pictures = pictures;
return htmlOutput.evaluate();
}
function getPictures()
{
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var idURL = sheet.getRange(1, 1, sheet.getLastRow(), 1).getValues();
var destination_id = '1GNBiddMQZTl3Ti_mKs9CUM541p-yaCnv'; // ID OF GOOGLE DRIVE DIRECTORY;
var destination = DriveApp.getFolderById(destination_id);
var files = destination.getFiles();
var file_array = [];
while (files.hasNext())
{
var file = files.next();
file_array.push(file.getId());
}
return file_array;
}
function getValuesFromSpreadsheet() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
return sheet.getRange(1, 1, sheet.getLastRow(), 1).getValues(); // Retrieve values and send to Javascript
}
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div class="dropdown">
<button onclick="loadpics()" class="dropbtn">Dropdown</button>
<div id="myDropdown" class="dropdown-content"></div>
</div>
<h1>Display Pictures</h1>
<table>
<?for(var i = 0; i < pictures.length; i++) { ?>
<tr><td><img src="https://drive.google.com/uc?export=view&id=<?= pictures[i] ?>" style="width:400px;height:auto;" ></td></tr>
<? } ?>
</table>
</body>
</html>
<script>
function loadpics() {
google.script.run.withSuccessHandler(function(ar) {
let select = document.createElement("select");
select.id = "select1";
select.setAttribute("onchange", "selected()");
document.getElementById("myDropdown").appendChild(select);
ar.forEach(function(e, i) {
let option = document.createElement("option");
option.value = i;
option.text = e;
document.getElementById("select1").appendChild(option);
});
}).getValuesFromSpreadsheet();
};
function selected() {
const value = document.getElementById("select1").value;
console.log(value);
}
</script>
COPY OF GOOGLE SHEET - Click here
I'm not a coder, Could you please help me to achieve my task. Thank in advance.

You can refer to this sample code:
Code.gs
function doGet(e) {
var htmlOutput = HtmlService.createTemplateFromFile('index');
var vehicle = getValuesFromSpreadsheet();
var pictures = getPictures("1"); //show 1st vehicle as default
htmlOutput.vehicle = vehicle;
htmlOutput.pictures = pictures;
return htmlOutput.evaluate();
}
//Get pictures based on the selected option
function getPictures(option)
{
var row = parseInt(option) + 1;
Logger.log("option: "+option+" row: "+row);
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
var destination_id = sheet.getRange(row, 2).getDisplayValue();
var file_array = [];
Logger.log(destination_id);
try{
var destination = DriveApp.getFolderById(destination_id);
var files = destination.getFiles();
while (files.hasNext())
{
var file = files.next();
file_array.push(file.getId());
}
}catch(err){
Logger.log(err.message);
}
Logger.log(file_array.length);
return file_array;
}
function getValuesFromSpreadsheet() {
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("Sheet1");
return sheet.getRange(1, 1, sheet.getLastRow(), 1).getValues().flat(); // Retrieve values and send to Javascript
}
index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div class="dropdown" >
<div id="myDropdown" class="dropdown-content" style="width:200px;">
<b>Vehicle Menu: </b>
<select id="select1" onchange="selected()">
<?for(var i = 1; i < vehicle.length; i++) { ?>
<option value=<?= i ?>><?= vehicle[i] ?></option>
<? } ?>
</select>
</div>
</div>
<h1>Display Pictures</h1>
<div id="defaultPictures">
<table>
<?for(var i = 0; i < pictures.length; i++) { ?>
<tr><td><img src="https://drive.google.com/uc?export=view&id=<?= pictures[i] ?>" style="width:400px;height:auto;" ></td></tr>
<? } ?>
</table>
</div>
<div id="displayPictures"></div>
</body>
</html>
<script>
function selected() {
//Hide default pictures
var defaultDiv = document.getElementById("defaultPictures");
defaultDiv.style.display = "none";
const value = document.getElementById("select1").value;
console.log(value);
//Update table from the selected option
google.script.run.withSuccessHandler(function(ids) {
//Create a html table string based on the picture ids
let tblHtml = '<table>';
//Create table rows from the picture ids
ids.forEach(id => {
tblHtml += '<tr><td><img src="https://drive.google.com/uc?export=view&id='+id+'" style="width:400px;height:auto;" ></td></tr>';
});
tblHtml += '</table>';
//update div to include the table
console.log(tblHtml);
document.getElementById("displayPictures").innerHTML = tblHtml;
}).getPictures(value);
}
</script>
What it does?
I removed the dropdown button. Instead, I updated the dropdown options using vehicle variable which was initialized in doGet()
I created 2 div which displays your images. <div id="defaultPictures"> displays the table of images initialized using pictures variable set in doGet() while <div id="displayPictures"></div> will display the pictures of the selected option in the dropdown menu.
I modified getPictures() to add option argument which is the option value selected in your dropdown menu. Note that the option value is in zero index. ("Prado" value is 1 while "Prado 2" value is 2)
When initializing pictures variable in your html, I used "Prado" with option value 1 as a default pictures to display.
When a dropdown menu is selected, it will call selected() in your hmtl. Hide the defaultPictures div and create a new table based on the selected option.
Sample Output:

Related

Display selected checkbox values in an HTML using javascript/ google script

I created a Select Element which creates Checkbox dropdown elements based on the items on the Google sheet.
Here is my HTML code:
<div class="form-row">
<div class="multiselect form-group">
<div class="selectBox" onclick="showCheckboxes()">
<select class="form-control" >
<option>Select an option</option>
</select>
<div class="overSelect" ></div>
</div>
<div id="checkboxes">
</div>
</div>
Here is my javascript code:
<script>
document.addEventListener("DOMContentLoaded", afterLoad);
document.getElementById("checkboxes").addEventListener("change", loadDisplayPos);
function afterLoad(){
google.script.run.withSuccessHandler(loadPosApp).checkPosApp();
}
function loadPosApp(postOpen){
postOpen.forEach(function(r){
var checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.value = r[0];
var label = document.createElement('label')
label.appendChild(checkbox);
label.appendChild(document.createTextNode(" " + r[0]));
var content = document.getElementById('checkboxes');
content .appendChild(label);
});
}
function loadDisplayPos(){
var contentCheck = document.getElementById('checkboxes').value;
console.log(contentCheck);
}
function showCheckboxes() {
var checkboxes = document.getElementById("checkboxes");
if (!expanded) {
checkboxes.style.display = "block";
expanded = true;
} else {
checkboxes.style.display = "none";
expanded = false;
}
}
</script>
Here is my Google Apps Script function:
function checkPosApp()
{
const ss = SpreadsheetApp.openByUrl(url);
const ws = ss.getSheetByName("VacantPositions_Data");
//const myDates = ws.getRange(2, 1, ws.getLastRow()-1, 1).getValues();
var postOpen = ws.getRange(2, 1, ws.getLastRow()-1, 1).getValues();
Logger.log(postOpen)
return postOpen;
}
Upon the load of the Web App, it will load the values from the Google sheet to the Web App as dropdown checkboxes. My problem is how to display the checked items to the Select Element as selected. I tried to get the value of the element ID "checkboxes" but it says undefined. Do you have any suggestions or advice? I am still trying to look for a solution. Thank you in advance for the help.
I got the idea on how to answer my problem in this link: https://www.dyn-web.com/tutorials/forms/checkbox/group.php. I just modified it in a way that I could get all the checked/ selected in an array then display it in the Web App
Here is the modified function in javascript.
function loadDisplayPos(){
var element = document.getElementById('checkboxes');
var tops = element.getElementsByTagName('input');
var tags = [];
for (var i=0, len=tops.length; i<len; i++) {
if ( tops[i].type === 'checkbox' ) {
if (tops[i].checked){
tags.push( tops[i].value);
}
}
}
var selectedPost = document.getElementById('posapp').innerHTML= tags;
}

csv does not seem to appear due to reference error

I am quite new to this all, so i am pretty sure this is a simple oversight on my part, but i cant get it to run.
When i deploy the code below and click on the button, it does not do anything. When i inspect the html in my browser, it says "userCodeAppPanel:1 Uncaught ReferenceError: csvHTML is not defined
at HTMLInputElement.onclick"
When i run the function csvHTML from Code.gs, I can see the expected results in my Logger.log, so it seems the problem does not lie in my code.gs
What i am trying to achieve is showing the csv results in html. When all works fine, i will want to work with the data in some other way.
Attached below is my code.
Index.html:
<!DOCTYPE html>
<!-- styles -->
<?!= HtmlService.createHtmlOutputFromFile("styles.css").getContent(); ?>
<div class="content">
<h1>csv representation</h1>
<input class="button" type="submit" onclick="html();" value="Refresh" id="refresh"><br>
<div id="tabel"></div>
<svg class="chart"></svg>
</div>
<!-- javascript -->
<script src="//d3js.org/d3.v3.min.js"></script>
<?!= HtmlService.createHtmlOutputFromFile("chart.js").getContent() ?>
<?!= HtmlService.createHtmlOutputFromFile("main.js").getContent() ?>
<script>
function html()
{
var aContainer = document.createElement('div');
aContainer.classList.add('loader_div');
aContainer.setAttribute('id', 'second');
aContainer.innerHTML = "<div class='loader_mesage'><center>Fetching csv list. Please be patient!<br /> <br /><img src='https://i.ibb.co/yy23DT3/Dual-Ring-1s-200px.gif' height='50px' align='center'></img></center></div>";
document.body.appendChild(aContainer);
google.script.run
.withSuccessHandler(showTable)
.csvHTML();
}
function showTable(tabel)
{
document.getElementById("tabel").innerHTML = tabel;
var element = document.getElementById("second");
element.parentNode.removeChild(element);
}
</script>
and Code.gs:
function doGet(e) {
return HtmlService.createTemplateFromFile("index.html")
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
// Fecth Data and make a csv output.
function csvHTML()
{
var query = "{ 'query': 'SELECT * FROM `<some table>` limit 1000;', 'useLegacySql': false }";
var job = BigQuery.Jobs.query(query, <projectName>);
var json = JSON.parse(job);
var tabel = json2csv(json);
Logger.log(tabel)
return tabel;
}
function json2csv(json, classes) {
var headerRow = '';
var bodyRows = '';
classes = classes || '';
json.schema.fields.forEach(function(col){
headerRow +=col.name+",";
})
json.rows.forEach(function(row){
row.f.forEach(function(cell){
bodyRows +=cell.v+",";
})
})
return headerRow + bodyRows }
So thanks to the suggestions by TheMaster, i rewritten it into the following:
index.html:
<!-- javascript -->
<script src="//d3js.org/d3.v3.min.js"></script>
<script>
function html()
{
var aContainer = document.createElement('div');
aContainer.classList.add('loader_div');
aContainer.setAttribute('id', 'second');
aContainer.innerHTML = "<div class='loader_mesage'><center>Fetching csv list. Please be patient!<br /> <br /><img src='https://i.ibb.co/yy23DT3/Dual-Ring-1s-200px.gif' height='50px' align='center'></img></center></div>";
document.body.appendChild(aContainer);
google.script.run
.withSuccessHandler(showTable)
.csvHTML();
}
function showTable(tabel)
{
document.getElementById("tabel").innerHTML = tabel;
var element = document.getElementById("second");
element.parentNode.removeChild(element);
}
</script>
<!DOCTYPE html>
<div class="content">
<h1>csv representation</h1>
<input class="button" type="submit" onclick="html();" value="Refresh" id="refresh"><br>
<div id="tabel"></div>
<svg class="chart"></svg>
</div>
Code.gs has not been modified.
It appears that the <?!= htmlService.createHtmlOutputFromFile("styles.css").getContent(); ?> and other createHtmlOutputFromFile were getting in the way. Eventually i need these, but I will figure out how to incorporate that at a later stage.
Thanks for all the advice and help!
Disclaimer: I have zero experience with Google Apps Script, so take this with a grain of salt.
Looking at their documentation for BigQuery, it seems you are not querying the database correctly. I am surprised by your claim that Logger.log() shows the correct output. It does not appear that it should work.
In case I am right, here is what I propose you change your Code.gs file to:
function doGet(e) {
return HtmlService.createTemplateFromFile("index.html")
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME);
}
// Fetch Data and make a csv output.
function csvHTML() {
var results = runQuery('SELECT * FROM `<some table>` limit 1000;');
var tabel = toCSV(results);
Logger.log(tabel);
return tabel;
}
/**
* Runs a BigQuery query and logs the results in a spreadsheet.
*/
function runQuery(sql) {
// Replace this value with the project ID listed in the Google
// Cloud Platform project.
var projectId = 'XXXXXXXX';
var request = {
query: sql,
useLegacySQL: false
};
var queryResults = BigQuery.Jobs.query(request, projectId);
var jobId = queryResults.jobReference.jobId;
// Check on status of the Query Job.
var sleepTimeMs = 500;
while (!queryResults.jobComplete) {
Utilities.sleep(sleepTimeMs);
sleepTimeMs *= 2;
queryResults = BigQuery.Jobs.getQueryResults(projectId, jobId);
}
// Get all the rows of results.
var rows = queryResults.rows;
while (queryResults.pageToken) {
queryResults = BigQuery.Jobs.getQueryResults(projectId, jobId, {
pageToken: queryResults.pageToken
});
rows = rows.concat(queryResults.rows);
}
var fields = queryResults.schema.fields.map(function(field) {
return field.name;
});
var data = [];
if (rows) {
data = new Array(rows.length);
for (var i = 0; i < rows.length; i++) {
var cols = rows[i].f;
data[i] = new Array(cols.length);
for (var j = 0; j < cols.length; j++) {
data[i][j] = cols[j].v;
}
}
}
return {
fields: fields,
rows: rows
};
}
function toCSV(results) {
var headerRow = results.fields.join(',');
var bodyRows = results.rows.map(function(rowData) {
return rowData.map(function(value) {
// for proper CSV format, if the value contains a ",
// we need to escape it and surround it with double quotes.
if (typeof value === 'string' && value.indexOf('"') > -1) {
return '"' + value.replace(/"/g, '\\"') + '"';
}
return value;
});
})
.join('\n'); // join the lines together with newline characters
return headerRow + '\n' + bodyRows;
}
Reminder: I have not tested this, I'm purely writing this based on my knowledge of Javascript and their documentation and sample code.

Inserting a Link of a Picture That Had been Added to Google Drive into a Google Sheet

This is a second part to the problem that had been resolved here: Insert Image Link from Google Drive into Google Sheets After Uploading an Image via Web App
I'm developing a web application where a user can upload a picture by clicking on a button. This action will upload pictures into a certain directory in my google drive with a unique folder and name.
Now, I'm trying to copy and paste the google drive link of a picture any time it has been uploaded.
With the help of #Tanaike, I was able to get the link of the url from google drive into the google sheet when I pre-assign a part of the folder name (fn) and the picture title (i) within the getFileUrl(fn,i) function in "Code.gs". But I get this "TypeError: Cannot call method "getFilesByName" of undefined." output whenever I try to pass the user-input "fn" and "i".
page.html
--This is the front end, where a user uploads the picture
<html>
<head>
<body>
<form action="#" method="post" enctype="multipart/form-data">
<div class="row">
<div class="file-field input-field">
<div class="waves-effect waves-light btn-small">
<i class="material-icons right">insert_photo</i>
<span>Import Picture</span>
<input id="files" type="file" name="image">
</div>
<div class="file-path-wrapper">
<input disabled selected type="text" class="file-path
validate" placeholder="Choose an image">
</div>
</div>
</div>
</form>
<?!= include("page-js"); ?>
</div> <!-- CLOSE CONTAINER-->
</body>
</html>
This is part of the javascript to put relevant info in an array, which will later be used to append a row in the google sheet
page-js.html
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<script src="https://gumroad.com/js/gumroad.js"></script>
document.getElementById("files").addEventListener("loadend",doStuff1);
document.getElementById("addAnother").addEventListener("click",doStuff1);
<script>
function doStuff1(){
num.picNum2=i;
var personName=document.getElementById("fn").value;
google.script.run.withSuccessHandler(doStuff2).getFileUrl("fn","i"); // Modified by Tanaike
var userInfo ={};
userInfo.firstName= document.getElementById("fn").value;
userInfo.number=i;
userInfo.fileUrl=fileId00;
num.picNum=i;
i++;
google.script.run.userClicked(userInfo);
}
// Added by Tanaike
function doStuff2(fileId00) {
var userInfo = {};
userInfo.firstName = document.getElementById("fn").value;
userInfo.number = i;
userInfo.fileUrl = "https://docs.google.com/document/d/"+fileId00 +"/";
i++;
google.script.run.userClicked(userInfo);
}
</script>
This is part of the javascript to upload picture file into the Google drive
(still part of page-js.html)
var file,
reader = new FileReader();
var today = new Date();
var date = today.getFullYear()+'-'+(today.getMonth()+1)+'- '+today.getDate();
reader.onloadend = function(e) {
if (e.target.error != null) {
showError("File " + file.name + " could not be read.");
return;
} else {
google.script.run
.withSuccessHandler(showSuccess)
.uploadFileToGoogleDrive(e.target.result,num.picNum,date,$('input#fn')
.val(),$('input#date').val());
}
};
function showSuccess(e) {
if (e === "OK") {
$('#forminner').hide();
$('#success').show();
} else {
showError(e);
}
}
function submitForm() {
var files = $('#files')[0].files;
if (files.length === 0) {
showError("Please select a image to upload");
return;
}
file = files[0];
if (file.size > 1024 * 1024 * 5) {
showError("The file size should be < 5 MB.");
return;
}
showMessage("Uploading file..");
reader.readAsDataURL(file);
}
function showError(e) {
$('#progress').addClass('red-text').html(e);
}
function showMessage(e) {
$('#progress').removeClass('red-text').html(e);
}
</script>
This part grabs the array "userInfo" and appends the content in a row within a designated google sheet. Any time, I click on the button in the front end, it creates a new row.
This is where if I set fn and i values within the getFileUrl function manually and have a correponding picture and a folder under the designated directory, I get a valid link back in my google sheet. However, if I leave the argument as variables that the user input in the web app, I get the aforementioned error in my link within the sheet.
Code.gs
//google sheet web script
var url="https://docs.google.com/spreadsheets/d/XXXXX";
function getFileUrl(fn,i){
try{
var today0 = new Date();
var date0 = today0.getFullYear()+'-'+(today0.getMonth()+1)+'-'
+today0.getDate();
var dropbox0 = "OE Audit Pictures";
var folder0,folders0 = DriveApp.getFoldersByName(dropbox0);
while (folders0.hasNext())
var folder0=folders0.next();
var dropbox20=[date0,fn].join(" ");
var folder20,folders20=folder0.getFoldersByName(dropbox20);
while (folders20.hasNext())
var folder20=folders20.next();
var file0, files0= folder20.getFilesByName(i);
while (files0.hasNext())
var file0=files0.next();
var fileId0=file0.getUrl();
return fileId0;
} catch(f){
return f.toString();
}
}
function userClicked(userInfo){
var ss= SpreadsheetApp.openByUrl(url);
var ws=ss.getSheetByName("Data");
ws.appendRow([userInfo.number,new Date(),
userInfo.firstName,userInfo.fileUrl]);
}
function include(filename){
return HtmlService.createHtmlOutputFromFile(filename).getContent();
}
function uploadFileToGoogleDrive(data, file, fn, date) {
try {
var dropbox = "OE Audit Pictures";
var folder, folders = DriveApp.getFoldersByName(dropbox);
if (folders.hasNext()) {
folder = folders.next();
} else {
folder = DriveApp.createFolder(dropbox);
}
var contentType = data.substring(5,data.indexOf(';')),
bytes =
Utilities.base64Decode(data.substr(data.indexOf('base64,')+7)),
blob=Utilities.newBlob(bytes, contentType, file)
var dropbox2=[fn,date].join(" ");
var folder2, folders2=folder.getFoldersByName(dropbox2)
if (folders2.hasNext()){
folder2=folders2.next().createFile(blob);
} else {
file = folder.createFolder([fn,date].join(" ")).createFile(blob);
}
return "OK";
} catch (f) {
return f.toString();
}
}
As #Jescanellas and #Tanaike commented, the better approach is to fix your code editing the function doStuff2 in page-js.html as this:
function doStuff2(fileId00) {
var userInfo = {};
userInfo.firstName = document.getElementById("fn").value;
userInfo.number = i;
userInfo.fileUrl = "https://docs.google.com/document/d/"+fileId00 +"/";
i++;
google.script.run.userClicked(userInfo);
}
About the error you're getting, you're not using the brackets in the whiles, this is causing the errors because only takes the first line after the while inside the loop. Code.gs:
while (folders0.hasNext()) {
var folder0=folders0.next();
var dropbox20=[date0,fn].join(" ");
var folder20,folders20=folder0.getFoldersByName(dropbox20);
while (folders20.hasNext()) {
var folder20=folders20.next();
var file0, files0= folder20.getFilesByName(i);
while (files0.hasNext()) {
var file0=files0.next();
var fileId0=file0.getUrl();
return fileId0;
}
}
}
Regarding your question about the file Id, you can get it easily after you create the file, because this will return you a File object from which you can get the ID using the getId method [1]:
file = folder.createFolder([fn,date].join(" ")).createFile(blob);
fileId = file.getId();
[1] https://developers.google.com/apps-script/reference/drive/file

Get second, third and so on values

I have this problem here
The problem has been solved, but my question is how can I get the second value from that, or the third one. The sheet will have many tables and at some point I will need a total for each table. Also, is there any solution to automatically find the the array number which contain date row for each table (instead defining this manually). Hope my explanation make sense.
Thank you!
Kind regards,
L.E. Test file
If I understood your question correctly, instead of breaking the loop when a match to "Total" is found do whatever is needed to be done within the loop like so...
var today = toDateFormat(new Date());
var todaysColumn =
values[5].map(toDateFormat).map(Number).indexOf(+today);
var emailDate = Utilities.formatDate(new Date(today),"GMT+1",
"dd/MM/yyyy");
for (var i=0; i<values.length; i++){
if (values[i][0]=='Total'){
nr = i;
Logger.log(nr);
var output = values[nr][todaysColumn];
// Do something with the output here I"m assuming you email it
}
}
The loop will keep going and find every "Total" and do the same thing. This answer assumes that the "Totals" are in the same column. You can get fancier with this if you only want certain tables to send and not others, but this should get you started.
I didn't quite understand the second part of your question...
"Also, is there any solution to automatically find the the array
number which contain date row for each table (instead defining this
manually). Hope my explanation make sense."
I'm guessing you want all the rows that contain "Total" in the specific column. You could instantiate a variable as an empty array like so, var totals = [];. Then instead of sending the email or whatever in the first loop you would push the row values to the array like so, totals.push(nr+1) . //adding 1 gives you the actual row number (rows count from 1 but arrays count from 0). You could then simply loop through the totals array and do whatever you wanted to do. Alternatively you could create an array of all the values instead of row numbers like totals.push(values[nr][todaysColumn]) and loop through that array. Lots of ways to solve this problem!
Ok based on our conversation below I've edited the "test" sheet and updated the code. Below are my edits
All edits have been made in your test sheet and verified working in Logger. Let me know if you have any questions.
Spreadsheet:
Added "Validation" Tab
Edited "Table" tab so the row with "Email Address" in Column A lines up with the desired lookup values (dates or categories)...this was only for the first two tables as all the others already had this criteria.
Code:
Create table/category selector...
In the editor go to File >> New >> HTMLfile
Name the file "inputHTML"
Copy and paste the following code into that file
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form class="notice_form" autocomplete="off" onsubmit="formSubmit(this)" target="hidden_iframe">
<select id="tables" onchange="hideunhideCatagory(this.value)" required></select>
<p></p>
<select id="categories" style="display:none"></select>
<hr/>
<button class="submit" type="submit">Get Total</button>
</form>
<script>
window.addEventListener('load', function() {
console.log('Page is loaded');
});
</script>
<script
src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script type="text/javascript">
// The code in this function runs when the page is loaded.
$(function() {
var tableRunner = google.script.run.withSuccessHandler(buildTableList);
var catagoryRunner = google.script.run.withSuccessHandler(buildCatagoryList);
tableRunner.getTables();
catagoryRunner.getCategories();
});
function buildTableList(tables) {
var list = $('#tables');
list.empty();
list.append('<option></option>');
for (var i = 0; i < tables.length; i++) {
if(tables[i]==''){break;}
list.append('<option>' + tables[i] + '</option>');
}
}
function buildCatagoryList(categories) {
var list = $('#categories');
list.empty();
list.append('<option></option>');
for (var i = 0; i < categories.length; i++) {
if(categories[i]==''){break;}
list.append('<option>' + categories[i] + '</option>');
}
}
function hideunhideCatagory(tableValue){
var catElem = document.getElementById("categories");
if(tableValue == "Total Calls By Date" || tableValue == "Total Appointments by Date"){
catElem.style.display = "none"
document.required = false;
}else{
catElem.style.display = "block"
document.required = true;
}
}
function formSubmit(argTheFormElement) {
var table = $("select[id=tables]").val(),
catagory = $("select[id=categories]").val();
console.log(table)
google.script.run
.withSuccessHandler(google.script.host.close)
.getTotal(table,catagory);
}
</script>
</body>
<div id="hiframe" style="display:block; visibility:hidden; float:right">
<iframe name="hidden_iframe" height="0px" width="0px" ></iframe>
</div>
</html>
Edits to Code.gs file
Replace code in Code.gs with this...
//This is a simple trigger that creates the menu item in your sheet
function onOpen() {
var ui = SpreadsheetApp.getUi();
ui.createMenu('Run Scripts Manually')
.addItem('Get Total','fncOpenMyDialog')
.addToUi();
}
//This function launches the dialog and is launched by the menu item
function fncOpenMyDialog() {
//Open a dialog
var htmlDlg = HtmlService.createHtmlOutputFromFile('inputHTML')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(200)
.setHeight(150);
SpreadsheetApp.getUi()
.showModalDialog(htmlDlg, 'Select table to get total for');
};
//main function called by clicking "Get Total" on the dialogue...variables are passed to this function from the formSubmit in the inputHTML javascript
function getTotal(table,catagory) {
function toDateFormat(date) {
try {return date.setHours(0,0,0,0);}
catch(e) {return;}
}
//get all values
var values = SpreadsheetApp
.openById("10pB0jDPG8HYolECQ3eg1lrOFjXQ6JRFwQ-llvdE2yuM")
.getSheetByName("Tables")
.getDataRange()
.getValues();
//declare/instantiate your variables
var tableHeaderRow, totalRow, tableFound = false;
//begin loop through column A in Tables Sheet
for (var i = 0; i<values.length; i++){
//test to see if values have already been found if so break the loop
if(tableFound == true){break;}
//check to see if value matches selected table
if (values[i][0]==table){
//start another loop immediately after the match row
for(var x=i+1; x<values.length; x++){
if(values[x][0] == "Email Address"){ //This header needs to consistantly denote the row that contains the headers
tableHeaderRow = x;
tableFound = true;
}else if(values[x][0] == "Total"){
totalRow = x;
break;
}
}
}
}
Logger.log("Header Row = "+tableHeaderRow)
Logger.log("Total Row = "+ totalRow)
var today = toDateFormat(new Date())
var columnToTotal;
if(catagory==''){
columnToTotal = values[tableHeaderRow].map(toDateFormat).map(Number).indexOf(+today);
}else{
columnToTotal = values[tableHeaderRow].indexOf(catagory);
}
var output = values[totalRow][columnToTotal];
Logger.log(output);
var emailDate = Utilities.formatDate(new Date(today),"GMT+1", "dd/MM/yyyy");
//here is where you would put your code to do something with the output
}
/** The functions below are used by the form to populate the selects **/
function getTables(){
var cFile = SpreadsheetApp.getActive();
var cSheet = cFile.getSheetByName('Validation');
var cSheetHeader = cSheet.getRange(1,1,cSheet.getLastRow(),cSheet.getLastColumn()).getValues().shift();
var tabelCol = (cSheetHeader.indexOf("Tables")+1);
var tables = cSheet.getRange(2,tabelCol,cSheet.getLastRow(),1).getValues();
return tables.filter(function (elem){
return elem != "";
});
}
function getCatagories(){
var cFile = SpreadsheetApp.getActive();
var cSheet = cFile.getSheetByName('Validation');
var cSheetHeader = cSheet.getRange(1,1,cSheet.getLastRow(),cSheet.getLastColumn()).getValues().shift();
var catagoriesCol = (cSheetHeader.indexOf("Catagory")+1);
var catagories = cSheet.getRange(2,catagoriesCol,cSheet.getLastRow(),1).getValues();
return catagories.filter(function (elem){
return elem != "";
});
}

Submit drop down values into google spreadsheet with google script

I have coded a script with help from several stackoverflow examples but I get stuck when trying to go a bit further.
It seems very straightforward but I cannot seem to work it out.
So here it is:
I have coded an HTML script that initiates a dialogbox with some drop down menus. The data in the drop down menus is dynamic and taken from a range in a spreadsheet. I want for users to open the spreadsheet, run the script and choose the options from the drop down values. These drop down values will be pasted on the same spreadsheet.
The bit I got working is that the code sees the values that need to go in the drop down box, illustrates that and that there is a submit box.
However, I cannot seem to submit the values onto the spreadsheet. Please could anyone help me out or point me in the right direction?
test.gs
function openInputDialog1() {
var html = HtmlService.createHtmlOutputFromFile('Test').setSandboxMode(HtmlService.SandboxMode.IFRAME);
SpreadsheetApp.getUi()
.showModalDialog(html, 'Add Item');
}
function getMenuListFromSheet() {
return SpreadsheetApp.getActive().getSheetByName('Part Names')
.getRange(1,5,6,1).getValues();
}
function getThicknessFromSheet(){
return SpreadsheetApp.getActive().getSheetByName('Part Names')
.getRange(1,5,6,1).getValues();
}
function itemadd(form) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Part Names');
var LastRow=sheet.getLastRow();
Logger.log(LastRow);
Logger.log(form);
sheet.getRange(LastRow+1,1,1,2).setValues(form);
return true;
}
Test.html
<!DOCTYPE html>
<html>
<p>List of parts:</p>
<select id="menu">
<option></option>
<option>Google Chrome</option>
<option>Firefox</option>
</select>
<select id="thickness">
<option></option>
<option>1</option>
<option>2</option>
</select>
<script
src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js">
</script>
<input type="submit" value="Submit" onclick="select()">
<script>
// The code in this function runs when the page is loaded.
$(function() {
google.script.run.withSuccessHandler(showMenu)
.getMenuListFromSheet();
google.script.run.withSuccessHandler(showThickness)
.getThicknessFromSheet();
});
/**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>');
}
}
function showThickness(menuThickness) {
var list = $('#thickness');
list.find('option').remove(); // remove existing contents
for (var i = 0; i < menuThickness.length; i++) {
list.append('<option>' + menuThickness[i] + '</option>');
}
}
</script>
<script>
function select(){
var x = document.getElementById('menu').value;
var y = document.getElementById('thickness').value;
google.script.run
.itemadd(x,y)
google.script.host.close();
</script>
</html>
I know that I am somewhere not making the connection between the script and the HTML side but fail to understand where.
Thanks,
Tim
Here's the lacking bits from your code:
<input type="submit" value="Submit" onclick="sheetConnect()">
In your .HTML file:
function sheetConnect(){
var e = document.getElementById('menu'); //choices are Google Chrome and Firefox
var name = e.options[e.selectedIndex].value; //get whatever the user selected
google.script.run.writeData(name); //pass the value to Code.gs
}
In your Code.gs
function writeData(name){
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Sheet1'); //whatever your sheet's name
var cell = sheet.getRange(1,8); //assign position to column H row 1
cell.setValue(name); // write selected data from Dropdown named 'menu'
}
result:
Use the knowledge here to complete your project :)
I haven't used gs before but from looking at other examples yours looks right, however, in the second line you have tml.Service instead of Html.Service, not sure if that will fix all your issues but that will break it.

Categories

Resources