Using Google Scripts to search and to match array - javascript

I want to build button with a dialog box to match the result using script. For example, I divided US into East, Middle and West. I have a text file named US 50 states name and abbreviation. When I type "NY" or Boston", the result would show "East". How can I achieve this in Google Spreadsheet.Thanks.

This is the script file:
function findSection(state)
{
var state =(typeof(state) != 'undefined')?state: '';
var found = "No Data Provided";
if(state)
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sht = ss.getSheetByName('StateSearch');
var rng = sht.getDataRange();
var rngA = rng.getValues();
found ='Not Found';
for(var i=1;i<rngA.length;i++)
{
if((state==rngA[i][0]) || (state == rngA[i][1]))
{
found = rngA[i][2];
break;
}
}
}
return found;
}
function searchSideBar()
{
var ui = HtmlService.createHtmlOutputFromFile('sectionSearchDialog').setTitle('State Search');
SpreadsheetApp.getUi().showSidebar(ui);
}
This is the HTML file for the sidebar:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
State:<input type="text" id="txt1" size="30" value=""/><br />
Section:<input type="text" id="txt2" size="30" value=""/><br />
Search:<input type="button" value="Search" onClick="sectionSearch();" />
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script>
console.log('here');
function sectionSearch()
{
var v = $('#txt1').val();
google.script.run
.withSuccessHandler(updateSection)
.findSection(v);
}
function updateSection(v)
{
$('#txt2').val(v);
}
</script>
</body>
</html>
This is what the Spreadsheet "StateSearch' looks like: you can put the state data here and in the third column you can add your section names if you wish. Adding the cities is left as an exercise for the reader.
A simple way to add some cities without Geo Location might be this way:
Same sidebar code: this script file:
function findSection(state)
{
var state =(typeof(state) != 'undefined')?state: '';
var found = "No Data Provided";
if(state)
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sht = ss.getSheetByName('StateSearch');
var rng = sht.getDataRange();
var rngA = rng.getValues();
found ='Not Found';
for(var i=1;i<rngA.length;i++)
{
if((state==rngA[i][0]) || (state == rngA[i][1]) || (isACity(state,rngA[i][3])>-1))
{
found = rngA[i][2];
break;
}
}
}
return found;
}
function searchSideBar()
{
var ui = HtmlService.createHtmlOutputFromFile('sectionSearchDialog').setTitle('State Search');
SpreadsheetApp.getUi().showSidebar(ui);
}
function isACity(city,cities)
{
var city = (typeof(city) != 'undefined')?city:'';
var cities = (typeof(cities) != 'undefined')?cities:'';
var r = -1;
if(city && cities)
{
var citiesA = String(cities).split(',');
r = citiesA.indexOf(city);
}
return r;
}
The spreadsheet looks like this:
You have to run the sidebar code to load it or you can do that in an onOpen().

Related

How to add conditionals to user input in App Scripts with while loops?

I made a selectBox which had its range of values from a Google Sheet Column. I also want to take an Integer input value from the user and then write this value in a specific cell according to option taken from selectBox. The html link does not show the integer response box. Is it possible to do the above plan in a while loop? Would appreciate any ideas and correction of code
function doGet() {
var ap = SpreadsheetApp.openByUrl("Gsheet URL here");
var ui = SpreadsheetApp.getUi();
var user = ui.prompt("Put down a number");
var result = result.getSelectedButton();
var sheet = ap.getSheetByName("lv");
var values = sheet.getRange("A2:A10").getValues();
var options = values.map(function(row)
{
#To show show the selected option??
var item = options.getSelecteditem();
if (item === A3)
{
var cell = SpreadsheetApp.getActiveSheet().getActiveCell();
var a1 = cell.getA3Notation();
var val = cell.getValue();
SpreadsheetApp.getUi().alert("Ur value is "+a1+" value is "+val);
}
{
return '<option value="' + row[0] + '">' + row[0] + '</option>';
});
var html = '<form onSubmit="handleSubmit(this)"> Type of Cuisine' + options.join('') + '</select></form>';
return HtmlService.createHtmlOutput(html);
}
Using an Html Dialog to Control User Inputs
Not sure what you wanted so here's a complete example I whipped up for you.
Code.gs:
function processInput(obj) {
Logger.log(JSON.stringify(obj));
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0');
const [min,max,locs] = sh.getRange('B1:B3').getValues().flat();
Logger.log('min: %s max: %s locs: %s',min,max,locs)
const lA = locs.split(',');
if(obj.int > max) {
obj.msg = "Too High Try Again";
return obj;
} else if (obj.int < min) {
obj.msg = "To Low Try Again";
return obj;
} else if (!~lA.indexOf(obj.loc)) {
obj.msg = "Invalid Location";
return obj;
} else {
sh.getRange(obj.loc).setValue(obj.int);
obj.msg = "Complete";
return obj;
}
}
Following function Launches the dialog:
function launchInputDialog() {
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutputFromFile('ah1'),"Enter Input");
}
html:
<!DOCTYPE html>
<html>
<head>
</head>
<style>input {margin: 2px 5px 2px 0;}</style>
<body>
<form>
<input type="text" id="in1" placeholder="Enter an integer" />
<br /><input type="text" id="in2" placeholder="Enter a location" />
<br /><input type="button" value="Process" onClick="processinput();" />
</form>
<div id="msg"></div>
<script>
function processinput() {
document.getElementById("msg").innerHTML = '';
let v1 = parseInt(document.getElementById('in1').value);
let v2 = document.getElementById('in2').value;
let obj = {int:v1,loc:v2,msg:''};
google.script.run
.withSuccessHandler(robj => {
console.log(JSON.stringify(robj))
if(robj.msg == "Complete") {
document.getElementById("msg").innerHTML = `Value: ${robj.int} Location: ${robj.loc} Try Again`;
document.getElementById("in1").value = '';
document.getElementById("in2").value = '';
} else {
document.getElementById("msg").innerHTML = robj.msg;
}
})
.processInput(obj);
}
</script>
</body>
</html>
Short Demo:
This version uses a <select> tag to allow the user to determine where the data will be loaded
GS:
function doPost(e) {
Logger.log(e.postData.contents);
Logger.log(e.postData.type);
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName("Sheet1");
let data = JSON.parse(e.postData.contents);
sh.getRange(data.loc).setValue(data.id)
}
function sendData(obj) {
const url = ScriptApp.getService().getUrl();
const params = { "contentType": "application/json", "payload": JSON.stringify(obj), "muteHttpExceptions": true, "method": "post", "headers": { "Authorization": "Bearer " + ScriptApp.getOAuthToken() } };
UrlFetchApp.fetch(url, params);
}
function displayError(msg) {
SpreadsheetApp.getUi().alert(msg);
}
function launchMyDialog() {
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutputFromFile('ah1'), 'My Dialog');
}
function getSelectOptions() {
var ss = SpreadsheetApp.getActive();
var sh = ss.getSheetByName('Options');
var rg = sh.getDataRange();
var vA = rg.getValues();
var options = [];
for (var i = 0; i < vA.length; i++) {
options.push(vA[i][0]);
}
return vA;
}
HTML:
<!DOCTYPE html>
<html>
<head>
<base target="_top">
</head>
<body>
<form>
<input type="text" id="txt1" name="id" placeholder="Enter Numbers only"/>
<select id="sel1" name="loc"></select>
<input type="button" value="submit" onClick="processForm(this.parentNode);" />
</form>
<script>
function processForm(obj) {
console.log(obj.id.value);
if(obj.id.value.match(/[A-Za-z]/)) {
google.script.run.displayError("Invalid Characters Found in id field");
} else {
google.script.run.sendData(obj);
}
}
window.onload = function() {
google.script.run
.withSuccessHandler(updateSelect)
.getSelectOptions();
}
function updateSelect(vA) {
var select = document.getElementById("sel1");
select.options.length = 0;
for(var i=0;i<vA.length;i++) {
select.options[i] = new Option(vA[i],vA[i]);
}
}
</script>
</body>
</html>
Demo:

Redirect if a value matches with any cell in a specific range - google sheets

.gs (updated)
function doGet() {
return HtmlService.createTemplateFromFile('Form.html').evaluate()
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
var scriptProp = PropertiesService.getScriptProperties();
function doPost (e) {
var lock = LockService.getScriptLock();
lock.tryLock(10 * 1000);
var doc = SpreadsheetApp.getActiveSpreadsheet();
var sh = doc.getSheetByName("Sheet1");
var values = sh.getRange(2, 12, sh.getLastRow()-1, 1).getValues();
// Logger.log(values);
try {
var sheet = doc.getSheetByName("OTP");
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var nextRow = sheet.getLastRow() + 1;
var newRow = headers.map(function(header) {
return header === 'Timestamp' ? new Date() : e.parameter[header]
});
sheet.getRange(nextRow, 1, 1, newRow.length).setValues([newRow]);
var value = newRow[1];
for (var i = 0; i < values.length; i++) {
if (values[i] == value) {
return HtmlService.createTemplateFromFile('Confirmation.html').evaluate()
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
} else {
return HtmlService.createTemplateFromFile('Error.html').evaluate()
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}}}
catch (e) {
return ContentService.createTextOutput(JSON.stringify({ 'result': 'error', 'error': e }))
.setMimeType(ContentService.MimeType.JSON)
}
finally {
lock.releaseLock()
}}
The purpose of the above code is to check if the value newRow[1] matches with any cell value in the range (L2:L) in Sheet1, then redirects to Confirmation.html, otherwise, to Error.html based on the if statement in the code
Now the problem is; only if newRow[1] == first/top value in the range (L2:L), the user is redirected to Confirmation and any other value below that in the range redirects the user to error
For example:
If we have 4 values in the range L2:L like that:
L2: John
L3: Mike
L4: Jenny
L5: Tom
If a user submits John as newRow[1], redirected to Confirmation and that is correct with no problem, but
If a user submits Mike or Jenny or tom, redirected to error and this wrong because the new submitted value is still in the range and should redirect the user to Confirmation as well
Any help is appreciated. Thanks in advance
Use Array.flat to flatten the data first before checking for the value instead of a for-loop:
if(values.flat().includes(value)){
return /*confirmation page*/
} else {
return /*error page*/
}
The for loop did not work, because the logic is amiss: Your code states that:
for each value in values
if this value(in loop) is equal to value, I'm checking
end this function and return confirmation html
else
end this function and return error html
Whatever the case, the function will end after checking the first value. The correct way to do such a for loop would be:
var isValueInColL = false;
for (var i = 0; i < values.length; i++) {
if (values[i][0] == value) {//added [0]
isValueInColL = true;
break;// no need to check rest of col L
}
}
var html = isValueInColL ? 'Confirmation' : 'Error';
return HtmlService.createTemplateFromFile(html).evaluate()
.setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
}
Try it this way:
function doGet() {
return HtmlService.createHtmlOutputFromFile('Form.html');
}
function doPost (e) {
Logger.log(JSON.stringify(e))
if(!e || !e.parameter) {
Browser.msgBox('No Parameters');
return;
}
var doc=SpreadsheetApp.getActive();
var sheet=doc.getSheetByName('OTP');
var headers=sheet.getRange(1,1,1,sheet.getLastColumn()).getValues()[0];
var nextRow=sheet.getLastRow() + 1;
var newRow=headers.map(function(header) {return (header=='Timestamp')?new Date():e.parameter[header];});
sheet.getRange(nextRow,1,1,newRow.length).setValues([newRow]);
var sheet1=doc.getSheetByName("Sheet1");
var values=sheet1.getRange(2,12,sheet1.getLastRow()-1,1).getValues();
var value=newRow[1];
for (var i=0;i<values.length; i++) {
if (values[i][0]==value) {
return HtmlService.createHtmlOutputFromFile('Confirmation');
}else {
return HtmlService.createHtmlOutputFromFile('Error');
}
}
}
Try your html this way:
<!DOCTYPE html>
<html lang="en">
<head>
<base target="_top">
<style>body {font-family: "Lato", sans-serif}</style>
</head>
<body>
<form action="script URL" target="_self" method="POST">
<input type="number" placeholder="Enter OTP" required name="OTP">
<button type="submit">Send</button>
</form>
</body>
</html>
Some of your html tags were out of place for example the body tag doesn't belong above the

Fetch data from excel sheet using Javascript

I am using following code to extract data from excel sheet using javascript. This is working good and after opening the HTML page, getting the data that I want and closing the page, I am unable to open and edit the excel sheet as it is throwing the exception, "File already held by the user and unable to be edited". Is there anyway to handle the closing of excel sheet at the end of the code? Please help me.
<!DOCTYPE html>
<html>
<body>
Enter Salomon account:<br>
<input type="text" id="myText" name="SalAccount">
<br>
<button onclick="myFunction()">Submit</button>
<p id="demo"></p>
<script language="javascript" >
function myFunction()
{
alert("hello");
var excel = new ActiveXObject("Excel.Application");
var excel_file = excel.Workbooks.Open("C:/Users/bv15457/Desktop/test1.xlsx");
var excel_sheet = excel.Worksheets("Sheet1");
var x = document.getElementById("myText").value;
var lo = 1;
var hi = 682220;
var mid;
var element;
var Flag = 0;
while(lo <= hi && Flag != 1)
{
mid = Math.floor((lo + hi) / 2, 10);
element = excel_sheet.Cells(mid,1).Value;
if (element < x)
{
lo = mid + 1;
}
else if (element > x)
{
hi = mid - 1;
}
else
{
document.getElementById("demo").innerHTML = excel_sheet.Cells(mid,2).Value;
Flag = 1;
}
}
if (Flag != 1)
{
alert("Account is not found in XREF file");
}
}
</script>
</body>
</html>

Push value to array onclick and loop to add array values. Javascript

So i am pretty new at this and want to be able to add a dollar to the "deposit" text box every time I click the button. I'm going to have to do this with a quarter, dime, and nickel, button as well. This is what I have so far.
<input type="button" value="Dollar" id="dollar" />
$<input type="text" id="deposit" />
And the javascript is:
var $ = function (id) { return document.getElementById(id); }
var item = [];
var total = 0;
for (i=0; i < item.length; i++){
total += item[i];
$("deposit").value = total;
}
$("dollar").onclick = item.push(1);
Whatever help you can give is much appreciated!
Don't you mean
Live Demo
var $ = function (id) { return document.getElementById(id); }
var add = function(fld,val) {
return (parseFloat(fld.value)+val).toFixed(2);
}
window.onload=function() {
$("dollar").onclick=function() {
$("deposit").value = add($("deposit"),1);
}
$("dime").onclick=function() {
$("deposit").value = add($("deposit"),.1);
}
$("nickel").onclick=function() {
$("deposit").value = add($("deposit"),.05);
}
$("refund").onclick = function() {
$("deposit").value = "0.00";
}
}
Try this:
HTML
<!DOCTYPE html>
<html>
<head>
<script data-require="jquery#1.9.1" data-semver="1.9.1" src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="script.js"></script>
</head>
<body>
<input type="button" value="Dollar" id="dollar" />
$ <input type="text" id="deposit" />
</body>
</html>
JavaScript:
$(function() {
var item = [];
$("#dollar").click(function() {
item.push(1);
var total = 0;
for (var i = 0; i < item.length; i++) {
total += item[i];
$("#deposit").val(total);
}
});
});
Plunker example

I have an issue to create dynamic fields with string count using Javascript OR Jquery

I have an issue to create dynamic fields with string count using JavaScript or jQuery.
Briefing
I want to create dynamic fields with the help of sting count, for example when I write some text on player textfield like this p1,p2,p3 they create three file fields on dynamicDiv or when I remove some text on player textfield like this p1,p2 in same time they create only two file fields that's all.
The whole scenario depend on keyup event
Code:
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
function commasperatedCount(){
var cs_count = $('#player').val();
var fields = cs_count.split(/,/);
var fieldsCount = fields.length;
for(var i=1;i<=fieldsCount;i++){
var element = document.createElement("input");
element.setAttribute("type", 'file');
element.setAttribute("value", '');
element.setAttribute("name", 'file_'+i);
var foo = document.getElementById("dynamicDiv");
foo.appendChild(element);
}
}
</script>
<form>
<label>CountPlayerData</label>
<input type="text" name="player" id="player" onkeyup="return commasperatedCount();" autocomplete="off" />
<div id="dynamicDiv"></div>
<input type="submit" />
</form>
var seed = false,
c = 0,
deleted = false;
$('#player').on('keyup', function(e) {
var val = this.value;
if ($.trim(this.value)) {
if (e.which == 188) {
seed = false;
}
if (e.which == 8 || e.which == 46) {
var commaCount = val.split(/,/g).length - 1;
if (commaCount < c - 1) {
deleted = true;
}
}
commasperatedCount();
} else {
c = 0;
deleted = false;
seed = false;
$('#dynamicDiv').empty();
}
});
function commasperatedCount() {
if (deleted) {
$('#dynamicDiv input:last').remove();
deleted = false;
c--;
return false;
}
if (!seed) {
c++;
var fields = '<input value="" type="file" name="file_' + c + '">';
$('#dynamicDiv').append(fields);
seed = true;
}
}​
DEMO
<script>
function create(playerList) {
try {
var player = playerList.split(/,/);
} catch(err) {
//
return false;
}
var str = "";
for(var i=0; i<player.length; i++) {
str += '<input type="file" id="player-' + i + '" name="players[]" />';
//you wont need id unless you are thinking of javascript validations here
}
if(playerList=="") {str="";} // just in case text field is empty ...
document.getElementById("dynamicDiv").innerHTML = str;
}
</script>
<input id="playerList" onKeyUp="create(this.value);" /><!-- change event can also be used here -->
<form>
<div id="dynamicDiv"></div>
</form>

Categories

Resources