Add a row in Google Sheet using Google App Script - javascript

I am a beginner in google app script. I am creating resident payment system where if the user increases the number of paid by one I want to add the a new row in sales worksheet in google sheet with new invoice number and the address of the specific user (which means lets say the user's address is 16, Jalan Sanggul 4 so I want to add it to the worksheet under the address column). I have attached few images and link to my google appscript coding here to explain myself better. I really hope that you guys can help me with it. Thank you guys.
Link to google app script (There is few numbers of html there so give the link ) - https://script.google.com/d/1NvaCQBc1fZWT7Y5cdvSi_XVL2-ytRVDP41AgY-btOA_MYrd8vcQK4fb_/edit?usp=sharing
Link to google sheet - https://docs.google.com/spreadsheets/d/1GO_kQVuXBtBZSKreNSvYu_kTRQMuL7YN5VXd14zgMig/edit?usp=sharing
[Payment Data Image (1) - Google Sheet]1
[Payment Data Image (2)- Google Sheet]2
Code.gs
function doGet(request) {
return HtmlService.createTemplateFromFile('Index').evaluate()
.setTitle("Admin Login")
.addMetaTag('viewport', 'width=device-width, initial-scale=1')
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
//Check Login
function checkLogin(loginUsername, loginPassword) {
var url = 'https://docs.google.com/spreadsheets/d/1bM8l6JefFsPrlJnTWf56wOhnuSjdIwg3hMbY1tN1Zp8/edit#gid=1151242353';
var ss= SpreadsheetApp.openByUrl(url);
var webAppSheet = ss.getSheetByName("Admin Data");
var getLastRow = webAppSheet.getLastRow();
var found_record = '';
for(var i = 1; i <= getLastRow; i++)
{
if(webAppSheet.getRange(i, 1).getValue() == loginUsername &&
webAppSheet.getRange(i, 2).getValue() == loginPassword)
{
found_record = 'TRUE';
}
}
if(found_record == '')
{
found_record = 'FALSE';
}
return found_record;
}
/*--------------------------------------------------------------------------------------------------------
---------------GLOBAL VARIABLES---------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------
*/
function globalVariables(){
var varArray = {
spreadsheetId : '1bM8l6JefFsPrlJnTWf56wOhnuSjdIwg3hMbY1tN1Zp8', //** CHANGE !!!
admindataRage : 'Admin Data!A2:B', //** CHANGE !!!
adminidRange : 'Admin Data!A2:A', //** CHANGE !!!
adminlastCol : 'B', //** CHANGE !!!
admininsertRange : 'Admin Data!A1:B1', //** CHANGE !!!
adminsheetID : '1151242353',
dataRage : 'USERNAMES!A2:H', //** CHANGE !!!
idRange : 'USERNAMES!A2:A', //** CHANGE !!!
lastCol : 'H', //** CHANGE !!!
insertRange : 'USERNAMES!A1:H1', //** CHANGE !!!
sheetID : '0'
};
return varArray;
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------FUCNTION FOR ADMIN CRUD PART-----------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------
*/
/* PROCESS FORM */
function processAdminForm(formObject){
if(formObject.admin_uname && checkAdminID(formObject.admin_uname)){//Execute if form passes an ID and if is an existing ID
updateAdminData(getAdminFormValues(formObject),globalVariables().spreadsheetId,getAdminRangeByID(formObject.admin_uname)); // Update Data
}else{ //Execute if form does not pass an ID
appendAdminData(getAdminFormValues(formObject),globalVariables().spreadsheetId,globalVariables().admininsertRange); //Append Form Data
}
return getAdminLastTenRows();//Return last 10 rows
}
/* GET FORM VALUES AS AN ARRAY */
function getAdminFormValues(formObject){
/* ADD OR REMOVE VARIABLES ACCORDING TO YOUR FORM*/
if(formObject.admin_uname && checkAdminID(formObject.admin_uname)){
var values = [[
//formObject.username.toString(),
formObject.admin_uname,
formObject.admin_pw]];
}else{
var values = [[
//new Date().getTime().toString(),//https://webapps.stackexchange.com/a/51012/244121
formObject.admin_uname,
formObject.admin_pw]];
}
return values;
}
/* CREATE/ APPEND DATA */
function appendAdminData(values, spreadsheetId,range){
var valueRange = Sheets.newRowData();
valueRange.values = values;
var appendRequest = Sheets.newAppendCellsRequest();
appendRequest.adminsheetID = spreadsheetId;
appendRequest.rows = valueRange;
var results = Sheets.Spreadsheets.Values.append(valueRange, spreadsheetId, range,{valueInputOption: "RAW"});
}
/* READ DATA */
function readAdminData(spreadsheetId,range){
var result = Sheets.Spreadsheets.Values.get(spreadsheetId, range);
return result.values;
}
/* UPDATE DATA */
function updateAdminData(values,spreadsheetId,range){
var valueRange = Sheets.newValueRange();
valueRange.values = values;
var result = Sheets.Spreadsheets.Values.update(valueRange, spreadsheetId, range, {
valueInputOption: "RAW"});
}
/*DELETE DATA*/
function deleteAdminData(ID){
//https://developers.google.com/sheets/api/guides/batchupdate
//https://developers.google.com/sheets/api/samples/rowcolumn#delete_rows_or_columns
var startIndex = getAdminRowIndexByID(ID);
var deleteRange = {
"sheetId" : globalVariables().adminsheetID,
"dimension" : "ROWS",
"startIndex" : startIndex,
"endIndex" : startIndex+1
}
var deleteRequest= [{"deleteDimension":{"range":deleteRange}}];
Sheets.Spreadsheets.batchUpdate({"requests": deleteRequest}, globalVariables().spreadsheetId);
return getAdminLastTenRows();//Return last 10 rows
}
/* CHECK FOR EXISTING ID, RETURN BOOLEAN */
function checkAdminID(ID){
var idList = readAdminData(globalVariables().spreadsheetId,globalVariables().adminidRange,).reduce(function(a,b){return a.concat(b);});
return idList.includes(ID);
}
/* GET DATA RANGE A1 NOTATION FOR GIVEN ID */
function getAdminRangeByID(id){
if(id){
var idList = readAdminData(globalVariables().spreadsheetId,globalVariables().adminidRange);
for(var i=0;i<idList.length;i++){
if(id==idList[i][0]){
return 'Admin Data!A'+(i+2)+':'+globalVariables().adminlastCol+(i+2);
}
}
}
}
/* GET RECORD BY ID */
function getAdminRecordById(id){
if(id && checkAdminID(id)){
var result = readAdminData(globalVariables().spreadsheetId,getAdminRangeByID(id));
return result;
}
}
/* GET ROW NUMBER FOR GIVEN ID */
function getAdminRowIndexByID(id){
if(id){
var idList = readAdminData(globalVariables().spreadsheetId,globalVariables().adminidRange);
for(var i=0;i<idList.length;i++){
if(id==idList[i][0]){
var rowIndex = parseInt(i+1);
return rowIndex;
}
}
}
}
/*GET LAST 10 RECORDS */
function getAdminLastTenRows(){
var lastRow = readAdminData(globalVariables().spreadsheetId,globalVariables().admindataRage).length+1;
if(lastRow<=11){
var range = globalVariables().admindataRage;
}else{
var range = 'Admin Data!A'+(lastRow-9)+':'+globalVariables().adminlastCol;
}
var lastTenRows = readAdminData(globalVariables().spreadsheetId,range);
return lastTenRows;
}
/* GET ALL RECORDS */
function getAdminAllData(){
var data = readAdminData(globalVariables().spreadsheetId,globalVariables().admindataRage);
return data;
}
/*-------------------------------------------------------------------------------------------------------------------------------------------------------------
------------------FUCNTION FOR RESIDENT CRUD PART-----------------------------------------------------------------------------------------------------------------
---------------------------------------------------------------------------------------------------------------------------------------------------------------
*/
/* PROCESS FORM */
function processForm(formObject){
if(formObject.username && checkID(formObject.username)){//Execute if form passes an ID and if is an existing ID
updateData(getFormValues(formObject),globalVariables().spreadsheetId,getRangeByID(formObject.username)); // Update Data
}else{ //Execute if form does not pass an ID
appendData(getFormValues(formObject),globalVariables().spreadsheetId,globalVariables().insertRange); //Append Form Data
}
return getLastTenRows();//Return last 10 rows
}
/* GET FORM VALUES AS AN ARRAY */
function getFormValues(formObject){
/* ADD OR REMOVE VARIABLES ACCORDING TO YOUR FORM*/
if(formObject.username && checkID(formObject.username)){
var values = [[
//formObject.username.toString(),
formObject.username,
formObject.housenumber,
formObject.street,
formObject.firstname,
formObject.lastname,
formObject.noOfPaid,
formObject.password,
formObject.phone]];
}else{
var values = [[
//new Date().getTime().toString(),//https://webapps.stackexchange.com/a/51012/244121
formObject.username,
formObject.housenumber,
formObject.street,
formObject.firstname,
formObject.lastname,
formObject.noOfPaid,
formObject.password,
formObject.phone]];
}
return values;
}
/* CREATE/ APPEND DATA */
function appendData(values, spreadsheetId,range){
var valueRange = Sheets.newRowData();
valueRange.values = values;
var appendRequest = Sheets.newAppendCellsRequest();
appendRequest.sheetID = spreadsheetId;
appendRequest.rows = valueRange;
var results = Sheets.Spreadsheets.Values.append(valueRange, spreadsheetId, range,{valueInputOption: "RAW"});
}
/* READ DATA */
function readData(spreadsheetId,range){
var result = Sheets.Spreadsheets.Values.get(spreadsheetId, range);
return result.values;
}
/* UPDATE DATA */
function updateData(values,spreadsheetId,range){
var valueRange = Sheets.newValueRange();
valueRange.values = values;
var result = Sheets.Spreadsheets.Values.update(valueRange, spreadsheetId, range, {
valueInputOption: "RAW"});
}
/*DELETE DATA*/
function deleteData(ID){
//https://developers.google.com/sheets/api/guides/batchupdate
//https://developers.google.com/sheets/api/samples/rowcolumn#delete_rows_or_columns
var startIndex = getRowIndexByID(ID);
var deleteRange = {
"sheetId" : globalVariables().sheetID,
"dimension" : "ROWS",
"startIndex" : startIndex,
"endIndex" : startIndex+1
}
var deleteRequest= [{"deleteDimension":{"range":deleteRange}}];
Sheets.Spreadsheets.batchUpdate({"requests": deleteRequest}, globalVariables().spreadsheetId);
return getLastTenRows();//Return last 10 rows
}
/* CHECK FOR EXISTING ID, RETURN BOOLEAN */
function checkID(ID){
var idList = readData(globalVariables().spreadsheetId,globalVariables().idRange,).reduce(function(a,b){return a.concat(b);});
return idList.includes(ID);
}
/* GET DATA RANGE A1 NOTATION FOR GIVEN ID */
function getRangeByID(id){
if(id){
var idList = readData(globalVariables().spreadsheetId,globalVariables().idRange);
for(var i=0;i<idList.length;i++){
if(id==idList[i][0]){
return 'USERNAMES!A'+(i+2)+':'+globalVariables().lastCol+(i+2);
}
}
}
}
/* GET RECORD BY ID */
function getRecordById(id){
if(id && checkID(id)){
var result = readData(globalVariables().spreadsheetId,getRangeByID(id));
return result;
}
}
/* GET ROW NUMBER FOR GIVEN ID */
function getRowIndexByID(id){
if(id){
var idList = readData(globalVariables().spreadsheetId,globalVariables().idRange);
for(var i=0;i<idList.length;i++){
if(id==idList[i][0]){
var rowIndex = parseInt(i+1);
return rowIndex;
}
}
}
}
/*GET LAST 10 RECORDS */
function getLastTenRows(){
var lastRow = readData(globalVariables().spreadsheetId,globalVariables().dataRage).length+1;
if(lastRow<=11){
var range = globalVariables().dataRage;
}else{
var range = 'USERNAMES!A'+(lastRow-9)+':'+globalVariables().lastCol;
}
var lastTenRows = readData(globalVariables().spreadsheetId,range);
return lastTenRows;
}
/* GET ALL RECORDS */
function getAllData(){
var data = readData(globalVariables().spreadsheetId,globalVariables().dataRage);
return data;
}
/*GET DROPDOWN LIST */
function getDropdownList(range){
var list = readData(globalVariables().spreadsheetId,range);
return list;
}
//CODE FOR DATA SEARCH
function searchData(formObject){
var result = [];
if(formObject.searchtext){//Execute if form passes search text
var data = Sheets.Spreadsheets.Values.get(globalVariables().spreadsheetId, globalVariables().dataRage).values;
for(var i=0;i<data.length;i++){
for(var j=0;j<data[i].length;j++){
if(data[i][j].toLowerCase().search(formObject.searchtext.toLowerCase())!=-1){
result.push(data[i])
}
}
}
}
return result;
}
/* INCLUDE HTML PARTS, EG. JAVASCRIPT, CSS, OTHER HTML FILES */
function include(filename) {
return HtmlService.createHtmlOutputFromFile(filename)
.getContent();
}
function getScriptURL() {
var url = ScriptApp.getService().getUrl();
return url ;
}
Index.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.bundle.min.js" integrity="sha384-xrRywqdh3PHs8keKZN+8zzc5TX0GRTLCcmivcbNJWm2rs5C8PRhcEn3czEjhAO9o" crossorigin="anonymous"></script>
<!--<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
-->
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">
<!-- Bootstrap 3.3.6 -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<!-- Font Awesome -->
<link href="https://fonts.googleapis.com/css?family=Roboto" rel="stylesheet">
<link rel="stylesheet" href="path/to/font-awesome/css/font-awesome.min.css">
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.7/css/all.css">
<?!= include('JavaScript'); ?> <!-- See JavaScript.html file -->
<?!= include('CSS'); ?> <!-- See CSS.html file -->
</head>
<body onload="createStreetDropdown()">
<div id="loginDisplay" class="loginDisplay">
<?!= include('loginDisplay'); ?>
</div>
<div style="display:none" id="dataDisplay" >
<div>
<button type="button" class="btn btn-primary" onclick="LogOut()">
Log out
</button>
<!--<button type="button" class="btn btn-default btn-md" onclick="LogOut()">
<span class="glyphicon glyphicon-log-out"></span>Log out
</button>-->
</div>
<br>
<div>
<button type="button" class="btn btn-primary" onclick="">
Admin
</button>
<button type="button" class="btn btn-primary" onclick="">
Resident
</button>
</div>
<div class="container">
<div class="row">
<div class="col-lg-6">
<?!= include('AdminForm'); ?>
<br><br>
<div id="output"></div>
</div>
<div class="col-lg-6">
<?!= include('AdminDataTable'); ?>
</div>
<!--
<div class="col-lg-12">
<?!= include('AdminDataTable'); ?>
</div>
-->
</div>
<br><br>
<hr>
<div class="row">
<div class="col-lg-12">
<?!= include('Form'); ?>
<br><br>
<div id="output"></div>
</div>
<div class="col-lg-12">
<?!= include('DataTable'); ?>
</div>
</div>
</div>
</div>
</body>
</html>
JavaScript.html
<script>
//--------Login Page----------------------------------
function LoginUser()
{
var loginUsername = document.getElementById("loginUsername").value;
var loginPassword = document.getElementById("loginPassword").value;
google.script.run.withSuccessHandler(function(output)
{
if(output == 'TRUE')
{
document.getElementById("loginDisplay").style.display = "none";
document.getElementById("dataDisplay").style.display = "block";
}
else if(output == 'FALSE')
{
document.getElementById("errorMessage").innerHTML = "Failed to Login";
}
}).checkLogin(loginUsername, loginPassword);
}
//-------Log Out----------------------
function LogOut(){
google.script.run
.withSuccessHandler(function(url){window.open(url,"_top");})
.getScriptURL();
//var url=window.location.href
//window.open(url,'_top');
//window.open("https://script.google.com/macros/s/AKfycbyS5LJn4i6mJeMzjWWryW7TUUDeeAZtVteJdCd6lT0FPPEiCiVy/exec",'_top');
}
//----------------------------------------------------------
//---------Admin Part---------------------------------------
// Prevent forms from submitting.
function preventAdminFormSubmit() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
}
window.addEventListener("load", adminfunctionInit, true);
//INITIALIZE FUNCTIONS ONLOAD
function adminfunctionInit(){
preventAdminFormSubmit();
getAdminLastTenRows();
};
//HANDLE FORM SUBMISSION
function handleAdminFormSubmit(formObject) {
google.script.run.withSuccessHandler(createAdminTable).processAdminForm(formObject);
document.getElementById("adminForm").reset();
}
//GET LAST 10 ROWS
function getAdminLastTenRows (){
google.script.run.withSuccessHandler(createAdminTable).getAdminLastTenRows();
}
//GET ALL DATA
function getAdminAllData(){
//document.getElementById('adminDataTable').innerHTML = "";
google.script.run.withSuccessHandler(createAdminTable).getAdminAllData();
}
//CREATE THE DATA TABLE
function createAdminTable(dataArray) {
if(dataArray){
var result = "<table class='table table-sm' style='font-size:0.8em'>"+
"<thead style='white-space: nowrap'>"+
"<tr>"+ //Change table headings to match witht he Google Sheet
"<th scope='col'>Delete</th>"+
"<th scope='col'>Edit</th>"+
"<th scope='col'>Username</th>"+
"<th scope='col'>Password</th>"+
"</tr>"+
"</thead>";
for(var i=0; i<dataArray.length; i++) {
result += "<tr>";
result += "<td><button type='button' class='btn btn-danger btn-xs deleteBtn' onclick='deleteAdminData(this);'>Delete</button></td>";
result += "<td><button type='button' class='btn btn-warning btn-xs editBtn' onclick='editAdminData(this);'>Edit</button></td>";
for(var j=0; j<dataArray[i].length; j++){
result += "<td>"+dataArray[i][j]+"</td>";
}
result += "</tr>";
}
result += "</table>";
var div = document.getElementById('adminDataTable');
div.innerHTML = result;
document.getElementById("admin_message").innerHTML = "";
}else{
var div = document.getElementById('adminDataTable');
div.innerHTML = "Data not found!";
}
}
//DELETE DATA
function deleteAdminData(el) {
var result = confirm("Want to delete?");
if (result) {
var admin_uname = el.parentNode.parentNode.cells[2].innerHTML;
google.script.run.withSuccessHandler(createAdminTable).deleteAdminData(admin_uname);
}
}
//EDIT DATA
function editAdminData(el){
var admin_uname = el.parentNode.parentNode.cells[2].innerHTML; //https://stackoverflow.com/a/32377357/2391195
google.script.run.withSuccessHandler(populateAdminForm).getAdminRecordById(admin_uname);
}
//POPULATE FORM
function populateAdminForm(records){
document.getElementById('admin_uname').value = records[0][0];
document.getElementById('admin_pw').value = records[0][1];
document.getElementById("admin_message").innerHTML = "<div class='alert alert-warning' role='alert'>Update Record [ADMIN: "+records[0][0]+"]</div>";
}
//-----------------------------------------------------------------------
//----------------Resident Part------------------------------------------
// Prevent forms from submitting.
function preventFormSubmit() {
var forms = document.querySelectorAll('form');
for (var i = 0; i < forms.length; i++) {
forms[i].addEventListener('submit', function(event) {
event.preventDefault();
});
}
}
window.addEventListener("load", functionInit, true);
//INITIALIZE FUNCTIONS ONLOAD
function functionInit(){
preventFormSubmit();
getLastTenRows();
};
//HANDLE FORM SUBMISSION
function handleFormSubmit(formObject) {
google.script.run.withSuccessHandler(createTable).processForm(formObject);
document.getElementById("myForm").reset();
}
//GET LAST 10 ROWS
function getLastTenRows (){
google.script.run.withSuccessHandler(createTable).getLastTenRows();
}
//GET ALL DATA
function getAllData(){
//document.getElementById('dataTable').innerHTML = "";
google.script.run.withSuccessHandler(createTable).getAllData();
}
//CREATE THE DATA TABLE
function createTable(dataArray) {
if(dataArray){
var result = "<table class='table table-sm' style='font-size:0.8em'>"+
"<thead style='white-space: nowrap'>"+
"<tr>"+ //Change table headings to match witht he Google Sheet
"<th scope='col'>Delete</th>"+
"<th scope='col'>Edit</th>"+
//"<th scope='col'>ID</th>"+
"<th scope='col'>Username</th>"+
"<th scope='col'>House Number</th>"+
"<th scope='col'>Street</th>"+
"<th scope='col'>First Name</th>"+
"<th scope='col'>Last Name</th>"+
"<th scope='col'>No of Paid</th>"+
"<th scope='col'>Password</th>"+
"<th scope='col'>Phone</th>"+
"</tr>"+
"</thead>";
for(var i=0; i<dataArray.length; i++) {
result += "<tr>";
result += "<td><button type='button' class='btn btn-danger btn-xs deleteBtn' onclick='deleteData(this);'>Delete</button></td>";
result += "<td><button type='button' class='btn btn-warning btn-xs editBtn' onclick='editData(this);'>Edit</button></td>";
for(var j=0; j<dataArray[i].length; j++){
result += "<td>"+dataArray[i][j]+"</td>";
}
result += "</tr>";
}
result += "</table>";
var div = document.getElementById('dataTable');
div.innerHTML = result;
document.getElementById("message").innerHTML = "";
}else{
var div = document.getElementById('dataTable');
div.innerHTML = "Data not found!";
}
}
//DELETE DATA
function deleteData(el) {
var result = confirm("Want to delete?");
if (result) {
var username = el.parentNode.parentNode.cells[2].innerHTML;
google.script.run.withSuccessHandler(createTable).deleteData(username);
}
}
//EDIT DATA
function editData(el){
var username = el.parentNode.parentNode.cells[2].innerHTML; //https://stackoverflow.com/a/32377357/2391195
google.script.run.withSuccessHandler(populateForm).getRecordById(username);
}
//POPULATE FORM
function populateForm(records){
document.getElementById('username').value = records[0][0];
document.getElementById('housenumber').value = records[0][1];
document.getElementById('street').value = records[0][2];
document.getElementById('firstname').value = records[0][3];
document.getElementById('lastname').value = records[0][4];
document.getElementById('noOfPaid').value = records[0][5];
document.getElementById('password').value = records[0][6];
document.getElementById('phone').value = records[0][7];
document.getElementById("message").innerHTML = "<div class='alert alert-warning' role='alert'>Update Record [ID: "+records[0][0]+"]</div>";
}
//RETRIVE DATA FROM GOOGLE SHEET FOR STREET DROPDOWN
function createStreetDropdown() {
//SUBMIT YOUR DATA RANGE FOR DROPDOWN AS THE PARAMETER
google.script.run.withSuccessHandler(streetDropDown).getDropdownList("Configuration!A2:A11");
}
//POPULATE STREET DROPDOWNS
function streetDropDown(values) { //Ref: https://stackoverflow.com/a/53771955/2391195
var list = document.getElementById('street');
for (var i = 0; i < values.length; i++) {
var option = document.createElement("option");
option.value = values[i];
option.text = values[i];
list.appendChild(option);
}
}
//SEARCH DATA
function handleSearchForm(formObject) {
google.script.run.withSuccessHandler(createTable).searchData(formObject);
document.getElementById("search-form").reset();
}
</script>
AdminForm.html
<form id="adminForm" class="p-2 border border-light rounded bg-light" onsubmit="handleAdminFormSubmit(this)">
<p class="h4 mb-4 text-center">Admin Form</p>
<div id="admin_message"></div>
<input type="text" id="admin_message" name="admin_message" value="" style="display: none">
<div class="form-group">
<label for="admin_uname" >Username</label>
<input type="text" class="form-control" id="admin_uname" name="admin_uname" placeholder="Username" required>
</div>
<div class="form-group">
<label for="admin_pw" >Password</label>
<input type="password" class="form-control" id="admin_pw" name="admin_pw" placeholder="Password" required>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
<input class="btn btn-secondary" type="reset" value="Reset">
</form>

Related

Filter the tables in html part of Google App Script

I am beginner to appscript. I am developing a payment system where user can see their payment history and can pay their payment. But for now after I have made some changes to my code, after I select a year and filter it (for example if I select 2020) it says that the records are not available. I have included the link to my appscript and some images to explain my self better. Thank you so much.
Before filtering it
After filtering it
Code.gs
var url = "https://docs.google.com/spreadsheets/d/1bM8l6JefFsPrlJnTWf56wOhnuSjdIwg3hMbY1tN1Zp8/edit#gid=1775459006";
var streetSheetName = "JALAN SANGGUL 4";
function doGet(e) {
var streetSheetName = "JALAN SANGGUL 4"; // Added
PropertiesService.getScriptProperties().setProperty("streetSheetName", streetSheetName); // Added
return HtmlService.createHtmlOutputFromFile('WebAppLogin')
.setTitle("Resident Payment");
}
function checkLogin(username, password) {
var found_record = '';
var name = '';
var ss = SpreadsheetApp.openByUrl(url);
var webAppSheet = ss.getSheetByName("USERNAMES");
var getLastRow = webAppSheet.getLastRow();
for(var i = 2; i <= getLastRow; i++) {
if(webAppSheet.getRange(i, 1).getValue().toUpperCase() == username.toUpperCase() && webAppSheet.getRange(i, 7).getValue() == password) {
found_record = 'TRUE';
name = webAppSheet.getRange(i, 4).getValue().toUpperCase() + " " + webAppSheet.getRange(i, 5).getValue().toUpperCase();
streetSheetName = webAppSheet.getRange(i, 3).getValue().toUpperCase();
} else if (username.toUpperCase() == 'ADMIN' && password == 'ADMINPASSWORD') {
found_record = 'TRUE';
name = webAppSheet.getRange(i, 4).getValue().toUpperCase() + " " + webAppSheet.getRange(i, 5).getValue().toUpperCase();
streetSheetName = webAppSheet.getRange(i, 3).getValue().toUpperCase();
}
}
PropertiesService.getScriptProperties().setProperty("streetSheetName", streetSheetName); // Added
if(found_record == '') {
found_record = 'FALSE';
}
return [found_record, username,name];
}
function GetRecords(username,filter) {
var filteredDataRangeValues = GetUsernameAssociatedProperties(username);
var resultArray = GetPaymentRecords(filteredDataRangeValues,filter);
var resultFilter = getYears();
result = {
data: resultArray,
filter: resultFilter
};
return result;
}
function getYears() {
var ss= SpreadsheetApp.openByUrl(url);
var yearSheet = ss.getSheetByName("Configuration");
var getLastRow = yearSheet.getLastRow();
var return_array = [];
for(var i = 2; i <= getLastRow; i++)
{
if(return_array.indexOf(yearSheet.getRange(i, 2).getDisplayValue()) === -1) {
return_array.push(yearSheet.getRange(i, 2).getDisplayValue());
}
}
return return_array;
}
function changePassword(username, newPassword) {
var sheet = SpreadsheetApp.openByUrl(url).getSheetByName("USERNAMES");
var range = sheet.getRange("A2:A").createTextFinder(username).matchEntireCell(true).findNext();
if (range) {
range.offset(0, 6).setValue(newPassword);
}
}
function GetUsernameAssociatedProperties(username) {
var filteredDataRangeValues = '';
var ss = SpreadsheetApp.openByUrl(url);
var displaySheet = ss.getSheetByName("USERNAMES");
var dataRangeValues = displaySheet.getDataRange().getValues();
if (username.toUpperCase() == 'ADMIN') {
dataRangeValues.shift();
filteredDataRangeValues = dataRangeValues;
} else {
filteredDataRangeValues = dataRangeValues.filter(row => row[0].toUpperCase() == username.toUpperCase());
}
return filteredDataRangeValues;
}
function GetPaymentRecords(userProperties,filter) {
var streetSheetName = PropertiesService.getScriptProperties().getProperty("streetSheetName"); // Added
var transpose = m => m[0].map((_, i) => m.map(x => x[i]));
var resultArray = [];
var ss = SpreadsheetApp.openByUrl(url);
var displaySheet = ss.getSheetByName(streetSheetName);
var addressValues = displaySheet.getRange("B:C").getValues();
var paidMonthValues = displaySheet.getRange(1, 7, displaySheet.getLastRow(), displaySheet.getLastColumn() - 6).getValues();
//Logger.log(addressValues);
//Logger.log(transpose(paidMonthValues));
userProperties.forEach((v, i) => {
var userHouseNumber = v[1];
var userStreet = v[2];
var column = addressValues.reduce(function callbackFn(accumulator, currentValue, index, array) {
if (currentValue[0] == userHouseNumber && currentValue[1] == userStreet) {
return index
} else {
return accumulator
}
}, '');
//Logger.log(column);
Logger.log(filter)
Logger.log(paidMonthValues);
if(filter=="None"){
var result = transpose(paidMonthValues).map(function callbackFn(element, index, array) {
return [element[0], userHouseNumber, userStreet, element[column] || '']
});
}else{
var result = transpose(paidMonthValues).map(function callbackFn(element, index, array) {
if(element[0].includes(filter))return [element[0], userHouseNumber, userStreet, element[column] || '']
});
}
resultArray = resultArray.concat(result);
//Logger.log(resultArray);
})
//Remove null elements
resultArray = resultArray.filter(element=>{
Logger.log(element!=null)
return element != null;
});
return resultArray;
}
WebAppLogin.html
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"
integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script>
var username = ""; // Added
function GetRecords() {
var spin = "<span class=\"spinner-border spinner-border-sm\" role=\"status\" aria-hidden=\"true\"></span>";
spin += " Loading...";
document.getElementById("LoginButton").innerHTML = spin;
username = document.getElementById("username").value; // Modified
var password = document.getElementById("password").value;
var password = document.getElementById("password").value;
google.script.run.withSuccessHandler(function(output) {
console.log(output);
var username = output[1];
var name = output[2];
if(output[0] == 'TRUE') {
document.getElementById("loginDisplay").style.display = "none";
document.getElementById("dataDisplay").style.display = "block";
document.getElementById("errorMessage").innerHTML = "";
document.getElementById("currentUser").value = name; // CHANGE
google.script.run.withSuccessHandler(displayTable).GetRecords(username,"None");
} else if(output[0] == 'FALSE') {
document.getElementById("firstLastName").innerHTML = "";
document.getElementById("currentUser").value = "";
document.getElementById("myFilter").innerHTML = "";
document.getElementById("errorMessage").innerHTML = "Failed to Login";
document.getElementById("LoginButton").innerHTML = "Login";
}
}).checkLogin(username, password);
}
function filter(){
var filterStr = document.getElementById("filterYear").value;
var user = document.getElementById("currentUser").value;
google.script.run.withSuccessHandler(displayTable).GetRecords(user,filterStr);
}
function displayTable(result) {
var ar = result.data;
var filterString = result.filter;
ar = ar.sort((a, b) => new Date(a).getTime() > new Date(b).getTime() ? -1 : 1).splice(-12); // <--- Added
var name = document.getElementById("currentUser").value; // CHANGE
if(ar.length > 0) {
var displayTable = '<table class=\"table\" id=\"mainTable\" >';
displayTable += "<tr>";
displayTable += "<th>Month</th>";
displayTable += "<th>House Number</th>";
displayTable += "<th>Street</th>";
displayTable += "<th>Payment Status</th>";
displayTable += "</tr>";
ar.forEach(function(item, index) {
displayTable += "<tr>";
displayTable += "<td>"+item[0]+"</td>";
displayTable += "<td>"+item[1]+"</td>";
displayTable += "<td>"+item[2]+"</td>";
displayTable += "<td>"+item[3]+"</td>";
displayTable += "</tr>";
});
displayTable += "</table>";
} else {
var displayTable = "<span style=\"font-weight: bold\" >No Records Found</span>";
}
var filter = '';
if(filterString.length > 0) {
filter += '<label for="years" style="font-size: 20px">Select the Year</label><br><select class="form-control form-control-sm" id="filterYear" name="years" required><option value="" selected>Choose...</option>';
filterString.filter(String).forEach(str => {
filter += '<option value="'+str+'">'+str+'</option>';
});
filter += '</select><button class="btn btn-primary" type="button" id="FilterButton" onclick="filter()" >Submit</button>';
}
var today = new Date();
var year = today.getFullYear();
var month = today.getMonth();
if (!ar.some(([a,,,d]) => {
var t = new Date(a);
return year == t.getFullYear() && month == t.getMonth() && d.toUpperCase() == "PAID";
})) {
document.getElementById("digitalgoods-030521182921-1").style.display = "block";
}
document.getElementById("displayRecords").innerHTML = displayTable;
document.getElementById("firstLastName").innerHTML = "USER: " + name;
document.getElementById("myFilter").innerHTML = filter;
document.getElementById("LoginButton").innerHTML = "Login";
document.getElementById("username").value = '';
document.getElementById("password").value = '';
}
//change the link according to ur webapp latest version
function LogOut(){
window.open("https://script.google.com/macros/s/AKfycbwKa4sQ441WUIqmU40laBP0mfiqNMiN-NghEvwUnJY/dev",'_top');
}
function changePassword(){
var result = confirm("Want to Change Password?");
if (result) {
var newPassword = document.getElementById("newPassword").value;
google.script.run.withSuccessHandler(() => alert('Password changed')).changePassword(username, newPassword);
}
}
</script>
</head>
<body>
<h2> Resident Payment Status Portal</h2>
<div id="loginDisplay" style="padding: 10px;" >
<div class="form-row">
<div class="form-group col-md-3">
<label>User Name</label>
<input type="text" id="username" class="form-control" required/>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-3">
<label>Password</label><br>
<input type="password" id="password" class="form-control" required/>
</div>
</div>
<button class="btn btn-primary" type="button" id="LoginButton" onclick="GetRecords()" >
Login
</button>
<span id="errorMessage" style="color: red" ></span>
</div>
<hr>
<div style="display:none" id="dataDisplay" >
<div>
<h2 id="firstLastName"></h2>
</div>
<input type="hidden" id="currentUser" value=""/>
<div id ="myFilter" class="form-group"></div>
<div id="displayRecords" style="padding: 10px;" ></div>
<!----Paypal Button-------->
<hr>
<div id="digitalgoods-030521182921-1" style="display: none;"></div>
<script>(function (div, currency) {var item_total = {currency_code: currency,value: '50.00',},tax_total = {currency_code: currency,value: '0.00' },render = function () {window.paypal.Buttons({createOrder: function (data, actions) {return actions.order.create({application_context: {brand_name: "",landing_page: "BILLING",shipping_preference: "NO_SHIPPING",payment_method: {payee_preferred: "UNRESTRICTED"}},purchase_units: [{description: "",soft_descriptor: "digitalgoods",amount: {breakdown: {item_total: item_total,tax_total: tax_total},value: '50.00' },items: [{name: "Monthly Fees",quantity: 1,description: "",sku: "1",unit_amount: item_total,tax: tax_total}]}]});},onApprove: function (data, actions) {return actions.order.capture().then(function (details) {div.innerHTML = "Order completed. You\x27ll receive an email shortly!";});},onCancel: function (data) {},onError: function (err) {div.innerHTML = "<pre>" + err.toString()}}).render("#digitalgoods-030521182921-1");},init = function () {window.digitalgoods = window.digitalgoods || [];window.digitalgoods.push(render);var file = "https://www.paypal.com/sdk/js?client-id=AS-86gVX_DfakSkq6YZDJRdKZb4SMIziOd5c9DIKy4extQrpb0VFEprDleB_duKI4BJQQRewUdfliZEf\x26currency=MYR";var script = document.createElement("script");script.type = "text/javascript";script.src = file;script.onload = function() {var i = window.digitalgoods.length;while (i--) {window.digitalgoods[i]();}};div.appendChild(script);};init();})(document.getElementById("digitalgoods-030521182921-1"), "MYR");</script>
<!-----Change Password----------->
<div>
<!--<button type="button" class="btn btn-primary btn-md" onclick="changePassword()">Change Password</button>-->
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#exampleModalCenter">
Change Password
</button>
<!-- Modal -->
<div class="modal fade" id="exampleModalCenter" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h3 class="modal-title" id="exampleModalLongTitle">Change Password</h3>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label>Enter New Password</label><br>
<input type="password" id="newPassword" class="form-control" required/>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="button" class="btn btn-primary" onclick="changePassword()">Save changes</button>
</div>
</div>
</div>
</div>
</div>
<hr>
<!-----Log Out----------->
<div>
<button type="button" class="btn btn-default btn-md" onclick="LogOut()">
<span class="glyphicon glyphicon-log-out"></span> Log out
</button>
</div>
</div>
</body>
</html>
When I saw your script, I noticed that var user = document.getElementById("currentUser").value; is used at filter() in Javascript side,. And, at GetRecords in GAS side, it seems that the user name used at the login is required to be used. In this case, I thought that user of var user = document.getElementById("currentUser").value; might be different from the user name, and this might be the reason of your issue. So, how about the following modification?
From:
function filter(){
var filterStr = document.getElementById("filterYear").value;
var user = document.getElementById("currentUser").value;
google.script.run.withSuccessHandler(displayTable).GetRecords(user,filterStr);
}
To:
function filter(){
var filterStr = document.getElementById("filterYear").value;
google.script.run.withSuccessHandler(displayTable).GetRecords(username, filterStr);
}
username has already been declared as the global variable. I thought that this value might be required to be used for GetRecords at GAS side.

i want to paginate my fetched data so that first top 20 entries will be on first page and then next 20 values on next page on cliucking next button

I have fetched data from spreadsheet on html table in reverse order so that latest entry will be on top row. But it is showing all entries on a single page.I want to paginate it (make a subsequent calls using offset and limit ) so that first 20 entries will be on first page then next 20 on second page and so on.but i dont have any idea how to it. That would be great if anyone could help me out.thanks in advance..!
Below is my javascript code:
enter code here
$(document).ready(function () {
refreshTable();
setInterval(refreshTable, 5000);
});
function refreshTable() {
$.getJSON('https://spreadsheets.google.com/feeds/list/1f1GTmf6-73sgdrKux5DTSbCsI1ObygfWjmUNQIxMqc0/2/public/full?alt=json', function (data) {
var trHTML = '';
var latest = '';
var len = data.feed.entry.length;
for (var i = len-1; i > 0 ; --i)
{
var time = data.feed.entry[i].gsx$time.$t;
var date = data.feed.entry[i].gsx$date.$t;
var level = data.feed.entry[i].gsx$level.$t;
var citycode = data.feed.entry[i].gsx$citycode.$t;
var latest = data.feed.entry[len-1].gsx$level.$t;
if( citycode = "1001" )
{
var city = "nagpur";
}
var voltage = data.feed.entry[i].gsx$voltage.$t ;
trHTML += '<tr bgcolor="#e6f7ff"><th>' + time + '</th><td>' + date +
'</th><td>' + level + '</td><th>' + citycode + '</th><td>' + city + '</th><td>' + voltage + '</td></tr>';
}
console.log(trHTML);
$('#tableContent').html(trHTML);
var trHTML = '';
console.log(latest);
$('#tableContent1').html(latest);
var latest = '';
});
}
```
Actually when i mereged your code with my code.i got some issues.I tried a lot but unable to do it.can you fix it sir.so that it will work fine.
<html>
<head>
<title>Live Monitoring Of Water</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<!-- Linking custom css sheet -->
<link rel="stylesheet" href="main.css" type="text/css">
</head>
<body background="back.jpg">
<!-- page heading -->
<div class="div1" style="border-style: ridge">
<h1 style="color:red; text-align:center;"> FLOOD MONITORING</h1>
</div>
<!-- page navbar -->
<div class="navbar">
Graph
Map
Table
</div>
<hr style="height:3px;border-width:0;color:rgb(148, 96, 96);background-color:gray">
<!-- Current data table -->
<table id="currentDataTable" cellspacing='0' cellpadding='10'" border='1' , bgcolor='white' border-bottom: 2px solid #ddd;>
<h1 > Current Data </h1>
<tr bgcolor='gray' align=" right">
<th align="right">Real time water level value :-</th>
</tr>
<tbody style="font-weight:bold ; width: 100px ; height: 30px;" cellspacing='0' cellpadding='10' align="center"
id="currentDataTableBody"></tbody>
</table>
<!-- Live water level data table -->
<hr style="height:3px;border-width:0;color:rgb(148, 96, 96);background-color:gray">
<center>
<h1>Live Water Level Data</h1>
</center>
<center>
<table id="liveWaterLevelTable" cellspacing='0' cellpadding='10' border='1' , bgcolor='white' border-bottom: 1px
solid #ddd;>
<tr bgcolor='gray'>
<th>Sr</th>
<th>Time</th>
<th>Date</th>
<th>Water level</th>
<th>City code</th>
<th>Voltage</th>
</tr>
<tbody id="liveWaterLevelTableBody"></tbody>
</table>
<!-- pagination -->
<div class="pagination">
<button class="paginate-button" type="button" onclick="paginate(-1)"><</button>
<button class="paginate-button" type="button" onclick="paginate(1)">></button>
<select onchange="setPagiSize(this)"></select>
<input type="checkbox" id="chkReverse" onchange="setOrder(this)" />
<label for="chkReverse">Reverse order</label>
</div>
</center>
<hr style="height:3px;border-width: 1;color:gray; background-color:gray">
</body>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script>
$(document).ready(function () {
refreshTable();
setInterval(refreshTable, 5000);
});
// global variables
const
$pagination = $('.pagination'),
$tbody = $('#liveWaterLevelTableBody'),
pageSizeOptions = [10, 15, 25, 50, 100],
url = 'https://spreadsheets.google.com/feeds/list/1f1GTmf6-73sgdrKux5DTSbCsI1ObygfWjmUNQIxMqc0/2/public/full?alt=json';
let entry = [],
data = [],
page = 0,
pageSize = pageSizeOptions[1],
pageSizeMax = 1,
isReversed = false,
change = true;
function refreshTable() {
$.getJSON(url, function (response) {
entry = response.feed.entry;
data = entry;
pageSizeMax = Math.ceil(entry.length / pageSize);
if(change === true){
paginate(1);
change = false;
}
let option = '';
var trHTML = '';
var latest = '';
var len = response.feed.entry.length;
var latest = response.feed.entry[len - 1].gsx$level.$t;
// display page size options
$.each(pageSizeOptions, (_, o) => {
option += `<option value="${o}"${o === pageSize ? " selected" : ""}>${o}</option>`;
});
$pagination.find('select').html(option);
$('#currentDataTableBody').html(latest);
});
}
// function to apply pagination
function paginate(pageAdd) {
page += pageAdd;
if (page < 1) {
page = 1;
return false;
}
if (page > pageSizeMax) {
page = pageSizeMax;
return false;
}
fillTable();
}
// function to set order as reversed or not
function setOrder(e) {
isReversed = !isReversed;
data = entry.reverse();
page = 1;
fillTable();
}
// function to change page size
function setPagiSize(e) {
page = 1;
pageSize = $(e).val();
pageSizeMax = Math.ceil(entry.length / pageSize);
fillTable();
}
// function to fill table in each pagination
function fillTable() {
const
len = isReversed ? data.length + 1 : 0,
pageBase = (page - 1) * pageSize;
let tbody = '';
$.each(data.slice(pageBase, pageSize * page), (i, o) => {
tbody += `<tr>
<td>${Math.abs(len - ((i + 1) + pageBase))}</td>
<td>${o.gsx$time.$t}</td>
<td>${o.gsx$date.$t}</td>
<td>${o.gsx$level.$t}</td>
<td>${o.gsx$citycode.$t}</td>
<td>${o.gsx$voltage.$t}</td>
</tr>`;
});
$tbody.html(tbody)
}
</script>
</html>```

Need help updating dropdowns in HTML Web Apps using Google Apps Script

This is my first time posting here so please let me know if I need to edit anything.
I am working on a program that runs through data that is imported in google sheets, displays one "row" of data in an HTML web app where the user can then assign an account number (found in a dropdown list) to the item that is displayed, and move on to the next row in the data. Each item in the data has a ID number and based on this ID number and the description of the data, the user selects the appropriate account number in the list to assign to the data.
The problem is that there are hundreds of these account numbers and having the users scroll/search through these to find the correct account will be very tedious.
The good news is that only certain accounts can be assigned to an ID number. I can effectively sort the dropdown list to only show accounts that can be assigned to the current ID therefore making the user's job much easier and much quicker.
However, I have no idea how to update the dropdown after the item loads on the html page. I am able to get the current ID number and sort through the accounts, I just am not able to update the drop down.
I have pasted the code.gs and the html/javascript code.
I did not include all of the code in code.gs file as some of it has nothing to do with my problem.
I am using Materialize CSS.
Code.gs:
var url = "hidden";
var ss = SpreadsheetApp.openByUrl(url);
var masterWS = ss.getSheetByName("Master List");
var items = [];
var Route = {};
Route.path = function (route, callback){
Route[route] = callback;
}
function doGet(e) {
Route.path("summary", summaryPage);
Route.path("edit", editPage);
if(Route[e.parameters.v]){
return Route[e.parameters.v]();
} else {
return editPage();
}
}
function summaryPage(){
var tmp = HtmlService.createTemplateFromFile("summary");
var sumList = showSummary();
tmp.summaryList = sumList;
return tmp.evaluate();
}
function include(fileName){
return HtmlService.createHtmlOutputFromFile(fileName).getContent();
}
function editPage(){
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName("GLAccounts");
// Create drop down and populate with all account options
var SSassetList = ws.getRange(2,1, getLastRowSpecial("A", "GLAccounts"),1).getValues();
var htmlAssetList = SSassetList.map(function (r){return '<option>' + r[0] + '</option>';}).join('');
var tmp = HtmlService.createTemplateFromFile("page");
tmp.assetList = htmlAssetList;
return tmp.evaluate();
}
function calculateTotalEntries(){
//Logger.log("Done: " + done);
var lastRow = masterWS.getLastRow();
var totalEntries = 0;
var i = lastRow;
while (masterWS.getRange(i, 1).getValue() != "Transaction Date"){
i--;
totalEntries++;
}
masterWS.getRange("R1").setValue(totalEntries);
masterWS.getRange("R2").setValue(lastRow);
}
function userClicked(userInfo){
var r = masterWS.getRange("P1").getValue();
var GLAccount = userInfo.act;
var lastRow = masterWS.getRange("R2").getValue();
var totalEntries = masterWS.getRange("R1").getValue();
if(!(masterWS.getRange("P3").getValue())){
//Logger.log("Done parsing. Items length: " + items.length);
if(r <= totalEntries - 1 ){
masterWS.getRange("P4").setValue(lastRow - totalEntries + 1 + r);
if(masterWS.getRange("P1").getValue() != 0){
masterWS.getRange(lastRow - totalEntries + r, 8).setValue(GLAccount);
}
r = r + 1;
masterWS.getRange("P1").setValue(r);
} else {
//Logger.log("Last one");
masterWS.getRange("P3").setValue(true);
masterWS.getRange(lastRow, 8).setValue(GLAccount);
//return Error;
resetCounters();
calculateChange();
}
}
}
function showItem(){
var row = masterWS.getRange("P4").getValue();
return "Item: " + masterWS.getRange(row,5).getValue() + "; Date: " + slice(masterWS.getRange(row,1).getValue(), 13) + "; ID: "+ masterWS.getRange(row,6).getValue();
}
function getData(){
var row = masterWS.getRange("P4").getValue();
var id = "";
id = masterWS.getRange(row,6).getValue().toString();
var availAccounts = [];
var IDSheet = ss.getSheetByName("MerchantCodes");
var lastIDRow = IDSheet.getLastRow();
var lastIDCol = 0;
var currentRow = 0;
for(var i = 6; i < lastIDRow; i++){
if(IDSheet.getRange(i, 1).getValue().toString() == id){
currentRow = i;
break;
}
}
//Logger.log("ID: " + id + " # row " + i);
for( var j = 1; j < 10; j++){
if(IDSheet.getRange(currentRow,j).getValue() != ""){
lastIDCol = j;
}
}
//Logger.log("Last Column for row " + i + ": " + lastIDCol);
for(var r = lastIDCol - (lastIDCol - 3) + 1; r < lastIDCol+1; r++){
//Logger.log("Account: " + IDSheet.getRange(currentRow,r).getValue());
availAccounts.push(IDSheet.getRange(currentRow,r).getValue());
}
return availAccounts;
}
function resetCounters(){
masterWS.getRange("P1").setValue(0);
masterWS.getRange("P3").setValue(false);
masterWS.getRange("P4").setValue("");
masterWS.getRange("P5").setValue("");
masterWS.getRange("P6").setValue("");
}
function getLastRowSpecial(col, sheetName){
var ss = SpreadsheetApp.openByUrl(url);
var ws = ss.getSheetByName(sheetName);
var data = ws.getRange(col + "2:" + col).getValues();
var lastRowData = data.filter(String).length;
return lastRowData;
}
}
HTML:
The item that is displayed in the web app, which changes based on the data, is in the tags.
The dropdown list is populated using the tags. The data in those tags comes from the doGet()and editPage() functions in the code.gs file.
<!DOCTYPE html>
<html>
<head>
<base target="_top">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<?!= include("page-css"); ?>
</head>
<body>
<div class = "container"> <!-- Open container -->
<div> <!-- Open row -->
<label>Item</label>
<p><span id="current"></span></p>
</div> <!-- Close row -->
<div class ="row"> <!-- Open row -->
<button id="btn2" class="btn waves-effect waves-light red darken-3" type="submit" name="action">Start</button>
</div> <!-- Close row -->
<div class ="row"> <!-- Open row -->
<div class="input-field col s6">
<select id="glAcc">
<option disabled selected>Choose your GL Account</option>
<?!= assetList; ?>
</select>
<label>GL Account</label>
</div>
</div> <!-- Close row -->
<div class ="row"> <!-- Open row -->
<button id="updDrop" class="btn waves-effect waves-light red darken-3" type="submit" name="action">Update Dropdown
<i class="material-icons right">send</i>
</button>
</div> <!-- Close row -->
<div class ="row"> <!-- Open row -->
<button id="btn" class="btn waves-effect waves-light red darken-3" type="submit" name="action">Submit
<i class="material-icons right">send</i>
</button>
</div> <!-- Close row -->
<div class ="row"> <!-- Open row -->
<a href="<?= ScriptApp.getService().getUrl(); ?>?v=summary" id="summary" class="btn waves-effect waves-light red darken-3" type="submit" name="action">Go to Summary Page
<i class="material-icons right">arrow_forward</i>
</a>
</div> <!-- Close row -->
</div> <!-- Close container -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<?!= include("page-js"); ?>
</body>
</html>
HTML JS Code:
<script>
document.addEventListener('DOMContentLoaded', function(){
var elems = document.querySelectorAll('select');
var instances = M.FormSelect.init(elems);
});
document.addEventListener('DOMContentLoaded', reset);
document.getElementById("btn").addEventListener("click",doStuff);
document.getElementById("btn2").addEventListener("click",doStuff);
document.getElementById("sumBtn").addEventListener("click", summary);
document.getElementById("updDrop").addEventListener("click", updateDropdown);
function doStuff(){
var userInfo = {};
userInfo.act = document.getElementById("glAcc").value;
google.script.run.withSuccessHandler(findItem).userClicked(userInfo);
//findItem();
//google.script.run.getLength();
// Reset dropdown
var myApp = document.getElementById("glAcc");
myApp.selectedIndex = 0;
M.FormSelect.init(myApp);
}
function reset(){
google.script.run.resetCounters();
google.script.run.calculateTotalEntries();
document.getElementById("current").textContent = "Click the Start Button";
}
function updateDropdown(){
google.script.run.withSuccessHandler(updateSelect).getData();
}
function updateSelect(vA){
var select = document.getElementById("glAcc");
select.options.length = 0;
vA.unshift("");
for(var i = 1; i < vA.length; i++){
select.options[i] = new Option(vA[i], vA[i]);
}
}
function findItem(){
google.script.run.withSuccessHandler(changeItem).showItem();
}
function changeItem(item){
document.getElementById("current").textContent = item;
//document.getElementById("options"). = "<option>1</option><option>2</option>";
}
function summary(){
google.script.run.withSuccessHandler(findSummary).calculateChange();
}
function findSummary(){
google.script.run.withSuccessHandler(changeSummary).showSummary();
}
function changeSummary(summary){
document.getElementById("sumText").textContent = summary;
}
</script>
Basically to summarize, I want the dropdown options to update as the item displayed also updates. If it is not possible to update at the same time, I can add a button which will update the dropdown once clicked.
I do not want to share the whole code/spreadsheet to everyone, but if you want access please message me and I can share it to you.
Thank you.
welcome to the SO community.
I believe the problem is not in the Apps Script.
When you use Materialize Select you need to re-init it.
This is the function I found in my codebase, it should help you:
function fillMaterializeSelect(elSelect, data) {
elSelect.options.length = 0;
for (let i = 0; i < data.length; i++) {
const dataElement = data[i];
const option = document.createElement("option");
option.value = dataElement.value;
option.text = dataElement.text;
elSelect.add(option);
}
M.FormSelect.init(elSelect);
}
Here is a JavaScript function I use a lot for updating <select>.
function updateSelect(vA,id){
var id=id || 'sel1';
var select = document.getElementById(id);
select.options.length = 0;
vA.unshift("");
for(var i=1;i<vA.length;i++)
{
select.options[i] = new Option(vA[i],vA[i]);//one is the value and the other is the display value
}
}
You retrieve the data with a
gooogle.script.run
.withSuccessHandler(updateSelect)
.getData();

Push to a JSON file

Good morning, I tried to push a temporaly value to a JSON file with the comand "MyJSON.name.push" but it tells me: "Undefined its not an object". I tried some forms and with javascript arrays worked but I need to do it on external JSON file. The error only appears if I click some button. Someone can help me?
Thanks you.
html:
<!DOCTYPE html>
<html>
<head>
<title>SSL Checker</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
<script type="text/javascript" src="js/script.js"></script>
<script type="text/javascript" src="js/json.json" charset="utf-8"></script>
</head>
<body onLoad="start()">
<div id="title">
<h1>SSL Checker</h1>
</div>
<div id="data">
<form action="javascript:void(0);" method="POST" onsubmit="SSL.Add()">
<input type="text" id="add-name" placeholder="Name"></input>
<input type="text" id="add-link" placeholder="Link"></input>
<input type="submit" value="Add">
</form>
<div id="edit" role="aria-hidden">
<form action="javascript:void(0);" method="POST" id="saveEdit">
<input type="text" id="edit-name">
<input type="submit" value="Edit" /> <a onclick="CloseInput()" aria-label="Close">✖</a>
</form>
</div>
<p id="counter"></p>
</div>
<div id="table">
<table style="overflow-x:auto;">
<tr>
<th>Sites:</th>
</tr>
<tbody id="urls">
</tbody>
</table>
</div>
</body>
</html>
js:
function start() {
var SSL = new function() {
//List urls to check
this.el = document.getElementById('urls');
this.Count = function(data) {
var el = document.getElementById('counter');
var name = 'url';
if (data) {
if (data > 1) {
name = 'urls';
}
el.innerHTML = 'There are:' + ' ' + data + ' ' + name;
} else {
el.innerHTML = 'No ' + name;
}
};
//Buttons configuration
this.FetchAll = function() {
var data= '';
if (MyJSON.length > 0) {
for (i = 0; i < MyJSON.length; i++) {
data += '<tr>';
data += '<td>' + MyJSON[i].name+ '</td>';
data += '<td><button onclick="SSL.Edit(' + i + ')">Edit</button></td>';
data += '<td><button onclick="SSL.Delete(' + i + ')">Delete</button></td>';
data += '</tr>';
}
}
this.Count(MyJSON.length);
return this.el.innerHTML = data;
};
//Add name
this.Add = function() {
el = document.getElementById('add-name');
el1 = document.getElementById('add-link')
var url = el.value;
var url1 = el1.value;
if (url) {
if (url) MyJSON.push('{name:"url",url:"url1"}')
el.value = '';
this.FetchAll();
}
}
//Edit
this.Edit = function(item) {
var el = document.getElementById('edit-name');
el.value = MyJSON.name[item];
document.getElementById('edit').style.display = 'block';
self = this;
document.getElementById('saveEdit').onsubmit = function() {
var url = el.value;
if (url) {
self.name.splice(item, 1, url.trim());
self.FetchAll();
CloseInput();
}
}
};
//Delete
this.Delete = function(item) {
MyJSON.urls.splice(item, 1);
this.FetchAll();
};
};
SSL.FetchAll();
function CloseInput() {
document.getElementById('edit').style.display = 'none';
}
window.SSL= SSL;
}
JSON FILE(json.json):
var MyJSON = [{
name:"Google",
url: 'google.es',
},
{
name:"Yahoo",
url: 'yahoo.com',
}
]
Change your this.Add() function like this:
this.Add = function() {
el = document.getElementById('add-name');
el1 = document.getElementById('add-link')
var url = el.value;
var url1 = el1.value;
if (url) {
MyJSON.push({"name":url,"url":url1})
el.value = '';
this.FetchAll();
}
}

ERROR: Can't find variable SSL

I'm trying to pick a value from JSON and insert it on a diferents text boxes but it show the value "undefined". The objective is insert link on name space and link space and save it on LocalStorage and some statick values like google and yahoo. Please can someone help me? Thanks you so much.
EDIT: Now is solved, and now dont work the buttons, some one? Please
NEW PROBLEM:The error only appear if I press the buttons (it don't create the buttons).
ERROR: Can't find variable SSL
html:
<!DOCTYPE html>
<html>
<head>
<title>SSL Checker</title>
<link rel="stylesheet" type="text/css" href="css/style.css">
<script type="text/javascript" src="js/script.js"></script>
<script type="text/javascript" src="js/json.json" charset="utf-8"></script>
</head>
<body onLoad="start()">
<div id="title">
<h1>SSL Checker</h1>
</div>
<div id="data">
<form action="javascript:void(0);" method="POST" onsubmit="SSL.Add()">
<input type="text" id="add-name" placeholder="Name"></input>
<input type="text" id="add-link" placeholder="Link"></input>
<input type="submit" value="Add">
</form>
<div id="edit" role="aria-hidden">
<form action="javascript:void(0);" method="POST" id="saveEdit">
<input type="text" id="edit-name">
<input type="submit" value="Edit" /> <a onclick="CloseInput()" aria-label="Close">✖</a>
</form>
</div>
<p id="counter"></p>
</div>
<div id="table">
<table style="overflow-x:auto;">
<tr>
<th>Sites:</th>
</tr>
<tbody id="urls">
</tbody>
</table>
</div>
</body>
</html>
js:
function start() {
var SSL = new function() {
//List urls to check
this.el = document.getElementById('urls');
this.Count = function(data) {
var el = document.getElementById('counter');
var name = 'url';
if (data) {
if (data > 1) {
name = 'urls';
}
el.innerHTML = 'There are:' + ' ' + data + ' ' + name;
} else {
el.innerHTML = 'No ' + name;
}
};
//Buttons configuration
this.FetchAll = ss =function() {
var data= '';
if (MyJSON.length > 0) {
for (i = 0; i < MyJSON.length; i++) {
data += '<tr>';
data += '<td>' + MyJSON[i].name+ '</td>';
data += '<td><button onclick="SSL.Edit(' + i + ')">Edit</button></td>';
data += '<td><button onclick="SSL.Delete(' + i + ')">Delete</button></td>';
data += '</tr>';
}
}
this.Count(MyJSON.length);
return this.el.innerHTML = data;
};
//Add name
this.Add = function() {
el = document.getElementById('add-name');
el1 = document.getElementById('add-link')
var url = el.value;
var url1 = el1.value;
if (url) {
MyJSON.name.push(url.trim());
el.value = '';
this.FetchAll();
}
if (url) {
MyJSON.url.push(url1.trim());
el1.value = '';
this.FetchAll();
}
}
//Edit
this.Edit = function(item) {
var el = document.getElementById('edit-name');
el.value = MyJSON.name[item];
document.getElementById('edit').style.display = 'block';
self = this;
document.getElementById('saveEdit').onsubmit = function() {
var url = el.value;
if (url) {
self.urls.splice(item, 1, url.trim());
self.FetchAll();
CloseInput();
}
}
};
//Delete
this.Delete = function(item) {
MyJSON.name.splice(item, 1);
this.FetchAll();
};
}
SSL.FetchAll();
function CloseInput() {
document.getElementById('edit').style.display = 'none';
}
}

Categories