I'm using a Google spreadsheet and want to create a sidebar menu with multiple check boxes and button. When selection 1 is selected or check box is clicked, and user presses Enter, the values from check boxes should display in the selected cell in the spreadsheet.
There is an input type of checkbox:
<form action="">
<input type="checkbox" name="myCategory" value="Yes">I like toast<br>
<input type="checkbox" name="myCategoryTwo" value="No">Don't like toast
</form>
gs Code
function onOpen() {
SpreadsheetApp.getUi()
.createMenu('Custom Menu')
.addItem('Show sidebar', 'showSidebar')
.addToUi();
};
gs Server code To Create Dialog
function showSidebar() {
Logger.log('showSidebar ran: ' );
var html = HtmlService.createTemplateFromFile('Dialog')
.evaluate()
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setTitle('My custom sidebar')
.setWidth(300);
SpreadsheetApp.getUi()
.showSidebar(html);
}
HTML
<div>
<form action="">
<input id="idYesChk" type="checkbox" name="myCategory" value="Yes">I like toast<br>
<input type="checkbox" name="myCategoryTwo" value="No">Don't like toast
</form>
<input type="text">
<input type='button' value="Update Spreadsheet" onclick='fncCallServerToDoSomething()'>
</div>
<script>
function fncCallServerToDoSomething() {
console.log('fncCallServerToDoSomething ran!');
var aReturnedValue = document.getElementById("idYesChk").value;
console.log("value of check box: " + aReturnedValue);
google.script.run
.withFailureHandler(onFailure)
.gsFunctionToRun(aReturnedValue);
//google.script.host.close();
};
function onFailure(error) {
console.log(error.message);
};
</script>
gs Code To write value to Spreadsheet
Puts Value Into Active Cell
function gsFunctionToRun(argValueRetrieved) {
Logger.log('argValueRetrieved: ' + argValueRetrieved);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var theSheet = ss.getActiveSheet();
var activeCell = ss.getActiveCell().getA1Notation();
var theRange = theSheet.getRange(activeCell);
theRange.setValue(argValueRetrieved);
};
Puts Value into Range (cell) Designated
function gsFunctionToRun(argValueRetrieved) {
Logger.log('argValueRetrieved: ' + argValueRetrieved);
var ss = SpreadsheetApp.getActiveSpreadsheet();
var theSheet = ss.getActiveSheet();
var theRange = theSheet.getRange("B4");
theRange.setValue(argValueRetrieved);
};
Related
I am working in apps script to build a scheduling assistant that draws data from and updates a google sheet. Essentially when the user wants to make an appointment an html sidebar opens. When the side bar opens the dropdown shows the correct options (available appointments based on values in the google sheet) however, once the selection has been made and the add appointment button clicked I want the dropdown to update its' options if the appointment slot is no longer available (in case the user wants to add more than one appointment per sitting, ideally not having to close the sidebar to make multiple appointments). Thanks for any help you can provide.
What I have tried:
Adding the loadAppt() functions to onclick for the button.
Adding the same code that originally populates the dropdown to the function that gets run when the addCustomerAppt button is clicked.
Closing the sidebar when the addCustomerAppt button is clicked
Refreshing the sidebar when the addCustomerAppt button is clicked
My code:
`
function onOpen() {
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.createMenu('Customer')
.addItem('Add', 'addCustomer')
.addToUi();
}
//function that displays a user input form. Used to enter customer information
function addCustomer() {
var active = SpreadsheetApp.getActiveSpreadsheet();
var ss = active.getSheetByName('Customer Data');
if (ss) {
var html = HtmlService.createHtmlOutputFromFile('testground').setTitle('Add Customer');//change to user
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.showSidebar(html);
}
else {
ss = active.insertSheet();
ss.setName('Customer Data');
var html = HtmlService.createHtmlOutputFromFile('testground').setTitle('Add Customer');
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.showSidebar(html);
var header = ['Date Time', 'First Name', 'Last Name', 'Email', 'Phone', 'Student'];
var range = ss.getRange("A1:F1");
range.setValues([header]).setFontWeight('bold').setBackground('cyan').setBorder(true, true, true, true, true, true);
}
}
//function to calculate available appointments by date and time.
//adds user friendly formatting depending on availability of appointment.
function calcAvailable() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
ss.getRange("E2").setFormula("=C2 - D2");
//get the last row to dynamically input the formula above
var lastRow = ss.getLastRow();
//why do I have to subtract one from last row? I don't seem to understand getLastRow()
var fillDownRange = ss.getRange(2, 5, lastRow - 1);
ss.getRange("E2").copyTo(fillDownRange);
//set rules for background colors
var rule = SpreadsheetApp.newConditionalFormatRule()
.whenNumberGreaterThan(0)
.setBackground("#90ee90")
.setRanges([fillDownRange])
.build();
var rule2 = SpreadsheetApp.newConditionalFormatRule()
.whenNumberLessThanOrEqualTo(0)
.setBackground("#ffcccb")
.setRanges([fillDownRange])
.build();
var rules = ss.getConditionalFormatRules();
rules.push(rule);
rules.push(rule2);
ss.setConditionalFormatRules(rules);
}
**function newAppointment(dateTime, first, last, email, phone) {
var values = [dateTime, first, last, email, phone];
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName('Customer Data');
sheet.appendRow(values);
//this section updates the available column after the apoinment is made
var apptSheet = ss.getSheetByName('Appointment View');
var lastRow = apptSheet.getLastRow();
var dataArray = apptSheet.getRange(2, 1, lastRow - 1, 2).getDisplayValues();
//must use split here as the date and time are passed as a single string;
var dtgArray = dateTime.split(',');
dataArray.forEach(function(item, index) {
if(item[0] == dtgArray[0] && item[1] == dtgArray[1]) {
var updateCol = apptSheet.getRange(index + 2, 4, 1, 1);
var currentAppt = updateCol.getValue();
updateCol.setValue(currentAppt += 1);
}
});
}**
function getList() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var apptSheet = ss.getSheetByName('Appointment View');
var lastRow = apptSheet.getLastRow();
//apps script cannot return any date object. Must use getDisplayValues() below and post process.
//var dataArray = apptSheet.getRange(2, 1, lastRow - 1, 2).getDisplayValues();
var dataArray = apptSheet.getRange(2, 1, lastRow - 1, 5).getDisplayValues();
var filterArr = dataArray.filter(apptBlock => apptBlock[4] > 0);
var listArr = [];
filterArr.forEach(function (block) {
listArr.push([block[0], block[1]]);
})
return listArr;
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script>
**function addCustomerAppt() {
//Add customer info from the form
var dateTime = document.getElementById('dateTime').value;
//var time = document.getElementById('time').value;
var firstName = document.getElementById('firstName').value;
var lastName = document.getElementById('lastName').value;
var email = document.getElementById('email').value;
var phone = document.getElementById('phone').value;
//pass the above variables to the app script function
google.script.run.newAppointment(dateTime, firstName, lastName, email, phone);
}**
//script to load appt into the dropdown menu. Limits choices to what is in appointment spreadsheet
**function loadAppt() {
google.script.run.withSuccessHandler(function(ar)
{
var apptSelect = document.getElementById("dateTime");
var option = document.createElement("option");
option.value = "";
option.text = "";
apptSelect.appendChild(option);
ar.forEach(function(item, index){
var option = document.createElement("option");
option.value = [item[0], item[1]];
option.text = [item[0], item[1]];
apptSelect.appendChild(option);
});
}).getList();
};**
</script>
</head>
<body>
<form>
<p>
**<label for="dateTime">Enter Appointment Date: </label>
<select id="dateTime" name="dateTime"></select>
</p>
<script>loadAppt();</script>**
<p>
<label for="firstName">Enter First Name: </label>
<input type="text" id="firstName" name="firstName">
</p>
<p>
<label for="lastName">Enter Last Name: </label>
<input type="text" id="lastName" name="lastName">
</p>
<p>
<label for="email">Enter Customer Email: </label>
<input type="email" id="email" name="email">
</p>
<p>
<label for="phone">Enter Customer Phone: </label>
<input type="text" id="phone" name="phone">
</p>
**<p>
<label for="addCustomerAppt"></label>
<input type="button" value="Add Customer" onclick="addCustomerAppt()">
</p>**
</body>
Your front-end function addCustomerAppt calls back-end function newAppointment.
Google Apps Script function newAppointment can return the result, updated available slots, after adding a new one. Try calculating that result and passing it as a function return value.
You can use that result on the front end. Log it to the console in your tests, then use it to repopulate the HTML select element.
I have a google spreadsheet that has menu for displaying a userform in html. The userform is a data entry form which enables you to add your input data to google spreadsheet. I added a button which should search an ID number in the Google Spreadsheet. Here is my html code for button and ID number:
html:
<div class="form-row">
<div class="form-group col-md-2">
<label for="idNum">ID Number</label>
<input type="text" class="form-control" id="idNum">
</div>
<button type="button" class="btn btn-outline-info" id="searchbtn">Search Profile</button>
</div>
and here is my script for button search:
<script>
//document.getElementById("addbtn").addEventListener("click", buttonAdd);
document.getElementById("searchbtn").addEventListener("click", searchProfile);
function searchProfile{
var appProfile = document.getElementById("idNum").value;
if(appProfile.length === 6){
google.script.run.withSuccessHandler(updateProfile).updateIdNum(appProfile);
}
//else{
//alert("invalid Profile Number");
}
}
function updateProfile(returnData){
document.getElementById("rnum").value = returnData[1];
console.log(retData);
}
</script>
I was able to search the ID number but the problem is I don't know how to reflect or populate the fields in html using the values in the rows of the spreadsheet.
Here is my .gs code:
function updateProfNum(appProfile){
//var appProfile = "101018"
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ws = ss.getSheetByName("Results");
var data = ws.getRange(1, 1, ws.getLastRow(), 1).getValues();
var dJoin = data.join().split(",");
vare myPnum = dJoin.indexOf(appProfile);
var dataRow = ws.getRange(myPnum + 1, 1, 1, ws.getLastColumn()).getValues();
if (myPnum > -1){
return dataRow[0];
} else {
Logger.log("unknown")
//return "unavailable";
}
}
By the way, here is the sample of my spreadsheet data:
ID Number | First Name | Last Name|
101018 | John | Doe |
101011 | Jane | Doe |
I'm trying to reflect this data in my html userform by searching for the ID number using the button and then by getting the values in its row. (For example I'm searching for 101018 and when I click the button search, it will reflect the data in the userform. I hope anyone can help. Thank you very much in advance.
Your code is mostly correct, it is just:
You are missing the element with the Id "rnum" to which you want to assign the output.
You can define e.g. <output id="rnum"></output>
You miss brackets () at function searchProfile and have some conflicts with function names.
Working code
Code.gs:
function updateIdNum(appProfile){
// var appProfile = "101018"
var ss = SpreadsheetApp.getActiveSpreadsheet();
var ws = ss.getSheetByName("Results");
var data = ws.getRange(1, 1, ws.getLastRow(), 1).getValues();
var dJoin = data.join().split(",");
var myPnum = dJoin.indexOf(appProfile);
var dataRow = ws.getRange(myPnum + 1, 1, 1, ws.getLastColumn()).getValues();
Logger.log(dataRow[0]);
if (myPnum > -1){
return dataRow[0];
} else {
Logger.log("unknown")
//return "unavailable";
}
}
function onOpen() {
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.createMenu('Custom Menu')
.addItem('Show sidebar', 'showSidebar')
.addToUi();
}
function showSidebar() {
var html = HtmlService.createHtmlOutputFromFile('index')
.setTitle('My custom sidebar')
.setWidth(300);
SpreadsheetApp.getUi() // Or DocumentApp or SlidesApp or FormApp.
.showSidebar(html);
}
index.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<div class="form-row">
<div class="form-group col-md-2">
<label for="idNum">ID Number</label>
<input type="text" class="form-control" id="idNum">
<output id="rnum"></output>
</div>
<button type="button" class="btn btn-outline-info" id="searchbtn">Search Profile</button>
</div>
<script>
document.getElementById("searchbtn").addEventListener("click", searchProfile);
function searchProfile(){
var appProfile = document.getElementById("idNum").value;
if(appProfile.length === 6){
google.script.run.withSuccessHandler(updateProfile).updateIdNum(appProfile);
}
//else{
//alert("invalid Profile Number");
}
function updateProfile(returnData){
document.getElementById("rnum").value = returnData[1];
}
</script>
</body>
</html>
I'm new to the scripting, but from what I have learned from this website, I have put together a check book balancesheet in google sheets.
I have a function "AddCheck" attached to the button on one of the cell. What it does is - opens a dialog box where I enter check details, like Date, Invoice number, amount and vendor's name. Then I click the submit button and Google sheets creates a row and adds those values.
My Question is how do I add a button next to the submit button that will allow me to add the New check details without leaving the dialog box. So that it will add the values to the cells and will clear the dialog box for another Entry.
This is my AddCheck function
function AddCheck() {
var spreadsheet = SpreadsheetApp.getActive();
spreadsheet.getRange('3:3').activate();
spreadsheet.getActiveSheet().insertRowsBefore(spreadsheet.getActiveRange().getRow(), 1);
spreadsheet.getActiveRange().offset(0, 0, 1, spreadsheet.getActiveRange().getNumColumns()).activate();
spreadsheet.getRange('A3').activate();
spreadsheet.getCurrentCell().setFormula('=A4+1');
spreadsheet.getRange('G3').activate();
spreadsheet.getCurrentCell().setValue('Pending');
spreadsheet.getRange('B3').activate();
fncOpenMyDialog()
};
This is my HTML dialog file
<!DOCTYPE html>
<html>
<body>
<form>
<label for="Date">Date :</label>
<input type='date' name='Date' id="Date" required="required"/>
<br>
<label for="Invoice">Invoice</label>
<input type='text' name='Invoice' id="Invoice" required="required"/>
<label for="Amount">Amount</label>
<input type='text' name='Amount' id="Amount" required="required"/>
<label for="Company">Company</label>
<select name="Class" id="vendor-selector" autofocus="autofocus" autocorrect="off" autocomplete="off">
<script>
(function () {
google.script.run.withSuccessHandler(
function (selectList) {
var select = document.getElementById("vendor-selector");
for( var i=0; i<selectList.length; i++ ) {
var option = document.createElement("option");
option.text = selectList[i][0];
select.add(option);
}
}
).getSelectList();
}());
</script>
</select>
<input type="submit" value="Submit" onclick="myFunction(this.parentNode)">
</form>
<p id="CompanyName"></p>
<script>
function myFunction(obj) {
var x = document.getElementById("vendor-selector").value;
document.getElementById("CompanyName").innerHTML = x;
google.script.run
.withSuccessHandler(() => google.script.host.close())
.functionToRunOnFormSubmit(obj);
}
</script>
</body>
</html>
This Function calls the Dialog
function fncOpenMyDialog() {
//Open a dialog
var htmlDlg = HtmlService.createHtmlOutputFromFile('CheckDetails')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(200)
.setHeight(250);
SpreadsheetApp.getUi()
.showModalDialog(htmlDlg, 'Check Details');
};
function functionToRunOnFormSubmit(fromInputForm) {
Logger.log(fromInputForm);
var ss = SpreadsheetApp.getActive();
ss.getSheetByName("Checks").getRange(3,3).setValues([[fromInputForm.Class]]);
ss.getSheetByName("Checks").getRange(3,2).setValues([[fromInputForm.Date]]);
ss.getSheetByName("Checks").getRange(3,4).setValues([[fromInputForm.Invoice]]);
ss.getSheetByName("Checks").getRange(3,6).setValues([[fromInputForm.Amount]]);
};
and this Function gets the List of vendors from Sheet2
function getSelectList()
{
var sheet = SpreadsheetApp.openById("141mlnxJBjepKxYCGXHFhz5IIEVnp6T2DDsb_uRgnZzY").getSheetByName('Sheet2');
var lastRow = sheet.getLastRow();
var myRange = sheet.getRange("A2:A" + lastRow);
var data = myRange.getValues();
Logger.log("Data = " + data);
return data;
};
function doGet()
{
return HtmlService.createHtmlOutputFromFile('CheckDetails');
}
Thank you for your help.
In order to implement this "Submit & Continue" feature, you only need to change the front-end code so that:
There is a new button.
Upon clicking the new button, the same back-end (GAS) code gets executed.
The dialog does not get closed after the GAS code execution, but the input elements are reset.
Code modifications
Add an id to the form tag so that it may be easily selected.
<form id="CheckDetailsForm">
Create a "Submit & Continue" button in your HTML. Assign an id to it so that it may be easily selected.
<input type="submit" value="Submit and continue" id="SubmitAndContinueInput" />
Within the script tag, add an event listener to the newly created button.
document.getElementById("SubmitAndContinueInput").addEventListener("click", myFunctionContinue);
Add the handler function for the newly created button's onclick event. This function will be very similar as the one you are using but: It will use the preventDefault to avoid the form being incorrectly sent and will clear the form data upon submission.
function clearForm() {
document.getElementById('Date').value = "";
document.getElementById('Invoice').value = "";
document.getElementById('Amount').value = "";
}
function myFunctionContinue(e) {
e.preventDefault();
var obj = document.getElementById("CheckDetailsForm");
var x = document.getElementById("vendor-selector").value;
document.getElementById("CompanyName").innerHTML = x;
google.script.run
.withSuccessHandler(clearForm)
.functionToRunOnFormSubmit(obj);
}
Example dialog:
Edit
Handling "submit and continue" new rows:
Remove the row-insertion functionality from AddCheck(). We will handle this logic afterwards:
function AddCheck() {
fncOpenMyDialog();
}
Modify the functionToRunOnFormSubmit() function so that it handles the row-insertion logic. I have also cleaned up the code a little bit. It would look like the following:
function functionToRunOnFormSubmit(fromInputForm) {
Logger.log(fromInputForm);
var sheet = SpreadsheetApp.getActive().getSheetByName("Checks");
sheet.insertRowBefore(3);
sheet.getRange("A3").setFormula("=A4+1");
sheet.getRange("B3").setValue(fromInputForm.Date);
sheet.getRange("C3").setValue(fromInputForm.Class);
sheet.getRange("D3").setValue(fromInputForm.Invoice);
sheet.getRange("F3").setValue(fromInputForm.Amount);
sheet.getRange("G3").setValue("Pending");
}
Full code
CheckDetails.html
<!DOCTYPE html>
<html>
<body>
<form id="CheckDetailsForm">
<label for="Date">Date :</label>
<input type='date' name='Date' id="Date" required="required"/>
<br>
<label for="Invoice">Invoice</label>
<input type='text' name='Invoice' id="Invoice" required="required"/>
<label for="Amount">Amount</label>
<input type='text' name='Amount' id="Amount" required="required"/>
<label for="Company">Company</label>
<select name="Class" id="vendor-selector" autofocus="autofocus" autocorrect="off" autocomplete="off">
<script>
(function () {
google.script.run.withSuccessHandler(
function (selectList) {
var select = document.getElementById("vendor-selector");
for( var i=0; i<selectList.length; i++ ) {
var option = document.createElement("option");
option.text = selectList[i][0];
select.add(option);
}
}
).getSelectList();
}());
</script>
</select>
<input type="submit" value="Submit" id="SubmitInput" />
<input type="submit" value="Submit and continue" id="SubmitAndContinueInput" />
</form>
<p id="CompanyName"></p>
<script>
document.getElementById("SubmitInput").addEventListener("click", myFunction);
document.getElementById("SubmitAndContinueInput").addEventListener("click", myFunctionContinue);
function clearForm() {
document.getElementById('Date').value = "";
document.getElementById('Invoice').value = "";
document.getElementById('Amount').value = "";
}
function myFunction(e) {
e.preventDefault();
var obj = document.getElementById("CheckDetailsForm");
var x = document.getElementById("vendor-selector").value;
document.getElementById("CompanyName").innerHTML = x;
google.script.run
.withSuccessHandler(() => google.script.host.close())
.functionToRunOnFormSubmit(obj);
}
function myFunctionContinue(e) {
e.preventDefault();
var obj = document.getElementById("CheckDetailsForm");
var x = document.getElementById("vendor-selector").value;
document.getElementById("CompanyName").innerHTML = x;
google.script.run
.withSuccessHandler(clearForm)
.functionToRunOnFormSubmit(obj);
}
</script>
</body>
</html>
Code.gs
function AddCheck() {
fncOpenMyDialog()
}
function fncOpenMyDialog() {
//Open a dialog
var htmlDlg = HtmlService.createHtmlOutputFromFile('CheckDetails')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setWidth(200)
.setHeight(250);
SpreadsheetApp.getUi()
.showModalDialog(htmlDlg, 'Check Details');
}
function functionToRunOnFormSubmit(fromInputForm) {
Logger.log(fromInputForm);
var sheet = SpreadsheetApp.getActive().getSheetByName("Checks");
sheet.insertRowBefore(3);
sheet.getRange("A3").setFormula("=A4+1");
sheet.getRange("B3").setValue(fromInputForm.Date);
sheet.getRange("C3").setValue(fromInputForm.Class);
sheet.getRange("D3").setValue(fromInputForm.Invoice);
sheet.getRange("F3").setValue(fromInputForm.Amount);
sheet.getRange("G3").setValue("Pending");
}
function getSelectList() {
var sheet = SpreadsheetApp.openById("141mlnxJBjepKxYCGXHFhz5IIEVnp6T2DDsb_uRgnZzY").getSheetByName('Sheet2');
var lastRow = sheet.getLastRow();
var myRange = sheet.getRange("A2:A" + lastRow);
var data = myRange.getValues();
Logger.log("Data = " + data);
return data;
}
function doGet() {
return HtmlService.createHtmlOutputFromFile('CheckDetails');
}
I need to publish exam result from a Google sheet. The search button shows the marks obtained perfectly if roll no is provided at the box but I need to omit the fields with no value like Subject 3, 5 etc. with their textbox from the html page
Here is the sheet I'm using and the code I'm using ...
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('index')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
//Search for the id and return the array for that row
function search(id) {
var ss = SpreadsheetApp.openByUrl("https://docs.google.com/spreadsheets/d/16IH3yKJjLwM9XA0c4_BN5MVQSKh8hV7gR6_kLLfe8to/edit#gid=0");
var sheet = ss.getSheetByName("Sheet1");
var values = sheet
.getDataRange()
.getValues()
.filter(function(row) {
return row[0] == id;
});
return values[0];
}
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<style>
.hidden {
display:none;
}
</style>
</head>
<body>
<input type="text" id="txtName"/>
<button id="show">SHOW</button>
<h1>FMATS</h1>
Name <input type="text" id="name"/><br>
Roll <input type="text" id="roll"/><br>
Subject 1 <input type="text" id="sub1"/><br>
Subject 2 <input type="text" id="sub2"/><br>
Subject 3 <input type="text" id="sub3"/><br>
Subject 4 <input type="text" id="sub4"/><br>
Subject 5 <input type="text" id="sub5"/><br>
</body>
<script>
//When click on show button it will run search function
window.onload = function(e){
document.getElementById('show')
.addEventListener('click', search);
}
//Get the value for txtName input and run search function in code.gs
function search() {
var txtName = document.getElementById('txtName').value;
google.script.run.withSuccessHandler(fillInfo).withFailureHandler(function (e) { console.log(e) }).search(txtName);
}
//It will run when a success response comes from search function in code.gs and updates the input with the sheet info
function fillInfo(values) {
document.getElementById('name').value = values[1];
document.getElementById('roll').value = values[0];
for (var i=0;i<values.length-2;i++) {
if (values[i+2]==null) {
toggleElement("sub"+i);
} else {
document.getElementById("sub"+i).value = values[i+2];
}
}
//rest of the code here
document.getElementById('name').value = values[1];
document.getElementById('roll').value = values[0];
document.getElementById('sub1').value = values[2];
document.getElementById('sub2').value = values[3];
document.getElementById('sub3').value = values[4];
document.getElementById('sub4').value = values[5];
document.getElementById('sub5').value = values[6];
}
</script>
</html>
I need to omit the Subject name and the text box with no value from the HTML page. And "Nothing Found" should be shown if a roll searched which is not in the table. It's not required but will be good if the Subject names come from sheet's row 1.
What should I do?
There are two ways to go about this:
Create your HTML on the server side (as #Cooper said)
Manipulate your HTML with JavaScript
To create your HTML on the server side you can use string and "write" the html automatically.
Then your functions will be something like this:
//It will run when a success response comes from search function in code.gs and updates the input with the sheet info
function fillInfo(response) {
document.getElementById("divid").innerHTML=html
});
If you absolutely want to manipulate the HTML on the client-side, you will use something like this:
function toggleElement(id) {
var td = document.getElementById(id).parentElement;
var tr = td.parentElement;
tr.classList.toggle("hidden");
}
the usage is like so:
function fillInfo(values) {
document.getElementById('name').value = values[1];
document.getElementById('roll').value = values[0];
for (var i=0;i<values.length-2;i++) {
if (values[i+2]==null) {
toggleElement("sub"+i);
} else {
document.getElementById("sub"+i).value = values[i+2];
}
}
//rest of the code here
}
and then you will have some css that does this:
.hidden {
display:none;
}
Edit:
This is how you implement the first solution:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<input type="text" id="txtName"/>
<button id="show">SHOW</button>
<h1>FMATS</h1>
<div id="dataDiv"></div>
</body>
<script>
//When click on show button it will run search function
window.onload = function(e){
document.getElementById('show')
.addEventListener('click', search);
}
//Get the value for txtName input and run search function in code.gs
function search() {
var txtName = document.getElementById('txtName').value;
google.script.run.withSuccessHandler(fillInfo).withFailureHandler(function (e) { console.log(e) }).search(txtName);
}
//It will run when a success response comes from search function in code.gs and updates the input with the sheet info
function fillInfo(values) {
console.log(values);
document.getElementById("dataDiv").innerHTML=values
}
</script>
</html>
function doGet(e) {
return HtmlService.createHtmlOutputFromFile('index')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
//Search for the id and return the array for that row
function search(id) {
var ss = SpreadsheetApp.openByUrl("SHEETS URL");
var sheet = ss.getSheetByName("Sheet1");
var values = sheet
.getDataRange()
.getValues()
.filter(function(row) {
return row[0] == id;
})[0];
var legends = sheet.getRange(1,1,1,sheet.getMaxColumns()).getValues()[0];
return createHTML(legends, values);
}
function createHTML(legends, values) {
Logger.log(legends);
var htmlResult = "";
for (var i=0; i<values.length; i++) {
if (values[i]!=null && values[i]!=="") {
htmlResult += '<div class="field">' + (legends[i]+"").replace("Sub", "Subject ") + '<input type="text" id="sub1" value="'+values[i]+'"></div>';
}
}
return htmlResult;
}
Hope this helps!
Here's a simple example of a complete solution of your problem done mostly server side.
I like do it this way because I like to be able to use Utilities.formatString().
Server Functions:
File: aq3.gs:
function search(sObj) {
var ss=SpreadsheetApp.getActive();
var sh=ss.getSheetByName('Sheet1');
var rg=sh.getDataRange();
var vA=rg.getValues();
var hA=vA[0];
var dObj={dA:[]};
for(var i=1;i<vA.length;i++) {
if(vA[i][0]==sObj.roll) {
var row=vA[i];
for(var j=0;j<hA.length;j++) {
dObj[hA[j]]=row[j];
}
break;
}
}
var html="<style>input{margin:2px 5px 0 2px}</style>";
for(var i=0;i<row.length;i++) {
if(dObj[hA[i]]) {
html+=Utilities.formatString('<br /><input id="txt-%s" type="text" value="%s" /><label for="txt-%s">%s</label>',i,dObj[hA[i]],i,hA[i]);
}
}
sObj['results']=html;
return sObj;
}
Run the below function to get the dialog running. The enter the roll you wish to see in the search box and click the search button. You will get only the boxes that have data.
function launchExamResultsSearchDialog() {
var userInterface=HtmlService.createHtmlOutputFromFile('aq5');
SpreadsheetApp.getUi().showModelessDialog(userInterface, "Exam Results");
}
The html:
File: aq5.html:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<script>
function search() {
var text=$('#srchtext').val();
google.script.run
.withSuccessHandler(function(sObj) {
document.getElementById("results").innerHTML=sObj.results;
})
.search({roll:text});
}
console.log("My Code");
</script>
</head>
<body>
<input type="text" id="srchtext" /><input type="button" value="Search" onClick="search();" />
<div id="results"></div>
</body>
</html>
This is what the dialog looks like:
You can just keep changing the search roll number and the dialog will replace the data with the new data. You can control the subjects by changing the headers.
Client To Server Communication
Utilities.formatString()
I really need help I almost finish my google script but I am in trouble I do not how to get the selected option(month selected) from the downlist (html) and storage in a "var", I really appreciate your help.
I tried with getElementById without success.
Thank You.
Document Code.gs
/*** Retrieves all the rows in the active spreadsheet that contain data and logs the values for each row.
* For more information on using the Spreadsheet API, see
* https://developers.google.com/apps-script/service_spreadsheet*/
function Menu() {
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.createMenu("Christian's Menu")
.addItem('Side Bar Comites', 'showSidebar')
.addToUi();
}
function showSidebar() {
var html = HtmlService.createHtmlOutputFromFile('Page')
.setSandboxMode(HtmlService.SandboxMode.IFRAME)
.setTitle('Sedesol - Captura de Entregas')
.setWidth(250);
SpreadsheetApp.getUi() // Or DocumentApp or FormApp.
.showSidebar(html);
}
function autowritemonthday(form){
var storeMonth = getElementById('monthlist').value; /*Does not work i dont know why*/
Browser.msgBox(storeMonth); /*tried to view the value from var storeMonth*/
/*I put this as comment because does not work either
var e = document.getElementById('monthlist');
var val = e.options[e.selectedIndex].text;*/
/*I need Storage the selected value from the downlist here before the onSeach(form)*/
onSearch(form); /*call the function to search the input text and put the cursor in the right Cell*/
var hoja = SpreadsheetApp.getActiveSpreadsheet();
var sheet = hoja.getSheets()[0];
var rows = sheet.getDataRange();
var ss = hoja.getActiveCell()
var selectedrow = ss.getRow();
var selectedcol = ss.getColumn();
var monthpos = sheet.getRange(selectedrow, 7); /* get the cell position for example monthpost(5,7)*/
var daypos = sheet.getRange(selectedrow, 8);
var tempm = form.mesinini; /*get the value of the inputbox by NAME*/
var tempd = form.dias;
var remspacestxtmonth = tempm.trim(); /*remove blank spaces*/
var uppertxtmonth = remspacestxtmonth.toUpperCase();/*conv. to uppercase*/
var remspacestxtday = tempd.trim(); /*remove blank spaces*/
monthpos.setValue(uppertxtmonth); /*write the var value in the selected cell preview positioned by the function onSearch*/
daypos.setValue(remspacestxtday);
}
function doGet() {
return HtmlService.createHtmlOutputFromFile("Page");
}
function onSearch(form){
var tempc = form.comites;
var comite = tempc.trim();
/*Browser.msgBox(comite);*/
var searchString = comite;
var sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("REYNOSA");
var column =4; //column Index - where i am going to search the value of the var comite
var columnValues = sheet.getRange(2, column, sheet.getLastRow()).getValues(); //1st cell Titles
var searchResult = columnValues.findIndex(searchString); //Cell Index - 2
if(searchResult != -1)
{
//searchResult + 2 is row index.
SpreadsheetApp.getActiveSpreadsheet().setActiveRange(sheet.getRange(searchResult + 2, 1))
}
}
Array.prototype.findIndex = function(search){
if(search == "") return false;
for (var i=0; i<this.length; i++)
if (this[i] == search) return i;
return -1;
}
Array.prototype.findIndex = function(search){
if(search == "") return false;
for (var i=0; i<this.length; i++)
if (this[i] == search) return i;
return -1;
}
page.html
<head>
<title>Page</title>
</head>
<body>
<div>
<form>
INGRESA LA FECHA DE ENTREGA QUE DESEAS UTILIZAR PARA LOS COMITES... /EN/...WRITE THE DATE YOU ARE GOING TO USE TO CAPTURE THE RECEIPTS
<br><br/>
<select id="monthlist" name="monthlist">
<option value="enero">JANUARY</option>
<option value="febrero">FEBRUARY</option>
<option value="marzo">MARCH</option>
<option value="abril">APRIL</option>
<option value="mayo">MAY</option>
<option value="Junio">JUNE</option>
<option value="julio">JULY</option>
<option value="agosto">AUGUST</option>
<option value="septiembre">SEPTEMBER</option>
<option value="octubre">OCTOBER</option>
<option value="noviembre">NOVEMBER</option>
<option value="diciembre">DECEMBER</option>
</select>
<br><br/>
Ingresa el MES [EJEMPLO: MARZO]: /EN/WRITE THE MONTH <input id="resp" type="text" value="" name="mesinini" />
<br><br/>
Ingresa el DIA /EN/WRITE THE DAY OF THE MONTH [EJEMPLO: 14]: <input id="resp" type="text" value="" name="dias" />
<br><br/>
CAPTURA EL COMITE. /EN/ CAPTURE THE RECEIPT NUMBER
<br><br/>
Ingresa el Comite: /EN/ WRITE THE RECEIPT NUMBER <input id="resp" type="text" value="" name="comites" />
<br><br/>
<input type="button" onclick="formautomd()" value="Capturar Entrega del Comite"/> /*THIS BUTTON*/
<br><br/>
<input type="button" onclick="formonSearch()" value="Buscar Comite"/>
<br><br/>
<input type="button" onclick="formexit()" value="Salir del Menu"/>
</form>
</div>
</body>
<script type="text/javascript">
function formonSearch() {
/////even tried to put the getElementbyId here and same result.
google.script.run.onSearch(document.forms[0]);
}
function formautomd() {
google.script.run.autowritemonthday(document.forms[0]);
} /* IT NEED BE STORAGED WHEN I PRESS THIS BUTTON*/
function formexit(){
google.script.host.close();
}
</script>
getElementById() can not be used in .gs server code. The .gs script runs on Google's servers. getElementById() only works in the browser. Your function:
function autowritemonthday(form){
var storeMonth = getElementById('monthlist').value;
/*Does not work i dont know why*/
Is in the .gs code. getElementById() only works in a <script> tag in HTML.
The data you want must come from the 'form' object.
This is what you need to use:
var storeMonth = form["monthlist"];
To see what is in your form object, iterate through the form object like this:
function autowritemonthday(form){
Logger.log('form: ' + form);
for (var key in form) {
Logger.log('the key is: ' + key);
Logger.log('the value is: ' + form[key]);
};
return;
};
Submit the form, then in the code editor, choose the VIEW menu, and then LOGS.
My original answer:
Did you try something like this:
function formautomyd() {
var storeMonth = getElementById('monthlist').value;
google.script.run.autofechaydia(document.forms[0]);
}
You stated that you used:
getElementByID
But didn't show the code. The letter "D" on the end can't be capitalized. Must be lower case. getElementById()