How to set i to 0 of the first item from a json criteria - ajax

I want to set i to 0 of the first item from a json criteria, eg. if the criteria is green in this case the i will start from 3... if criteria = blue it will start on 2... i need to set it to start from 0 or 1 whether it is.. also how to count total of a criteria, eg. green total is 2,, blue=1, red=2... thanks in advance!
var myBox_html ="";
var i = 0;
function createDiv(1x,2x,3x) {
A = '<something>'+1x;
B = '<something>'+2x;
C = '<something>'+3x;
myBox_html += '<something-more>'+A+B+C;
}
criteria // is a parameter from url, in this case means green
get_it = function(doc) {
var jsonData = eval('(' + doc + ')');
for (var i=0; i<jsonvar.name.length; i++) {
var 1x = jsonvar.name[i].1;
var 2x = jsonvar.name[i].2;
var 3x = jsonvar.name[i].3;
if (1x == criteria){
var Div = createDiv(1x,2x,3x);
} else {null}
}
document.getElementById("myBox").innerHTML = myBox_html;
}
get_it();
json should look like this:
var jsonvar = {"name":[{"1":"red","2":"round","3":"fruit"},{"1":"red","2":"squared","3":"box"},{"1":"blue","2":"squared","3":"box"},{"1":"green","2":"squared","3":"box"},{"1":"green","2":"pear","3":"fruit"}]};

Consider several solutions:
1: Generate criteria-grouped JSON response on the server-side. E.g.
var jsonvar = '{"name":{
"red": [{"1":"red","2":"round","3":"fruit"}, {"1":"red","2":"squared","3":"box"}],
"blue": [{"1":"blue","2":"squared","3":"box"}],
"green":[{"1":"green","2":"squared","3":"box"}, {"1":"green","2":"pear","3":"fruit"}]}}';
2: Convert you JSON array to criteria-grouped format as defined above. Here is sample routine for such a grouping:
function group_elements (arr) {
var result = {};
for (var i=0; i < arr.length; i++) {
if (!result[arr[i][1]]) {
result[arr[i][1]] = [];
}
result[arr[i][1]].push(arr[i]);
}
return result;
}
Both solutions allows you to iterate only filtered records and count length of group.

Related

Filter & Delete rows of data based off of column value fast! (Google Sheets)

Is there a way to filter the data in column Q off my google sheet faster then reading line one by one. There is daily about 400+ lines it needs to scan through and I need to delete every row of data if the data in column Q is less than 1 right now watching it, it takes about 10+ minutes.
function UpdateLog() {
var returnSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('CancelRawData');
var rowCount = returnSheet.getLastRow();
for (i = rowCount; i > 0; i--) {
var rrCell = 'Q' + i;
var cell = returnSheet.getRange(rrCell).getValue();
if (cell < 1 ){
returnSheet.deleteRow(i);
}
}
{
SpreadsheetApp.getUi().alert("🎉 Congratulations, your data has been updated", SpreadsheetApp.getUi().ButtonSet.OK);
}
}
Try it this way:
function UpdateLog() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0');
const vs = sh.getDataRange().getValues();
let d = 0;
vs.forEach((r, i) => {
if (!isNaN(r[16]) && r[16] < 1){
sh.deleteRow(i + 1 - d++);
}
});
}
This is a bit quicker
function UpdateLog() {
const ss = SpreadsheetApp.getActive();
const sh = ss.getSheetByName('Sheet0');
const vs = sh.getDataRange().getValues().filter(r => !isNaN(r[16]) && r[16] < 1);
sh.clearContents();
sh.getRange(1,1,vs.length,vs[0].length).setValues(vs);
}

Is there a way to speed up this for loop in Google Script?

I have a for loop which is working on my google sheet but it takes around 5 minutes to filter through the 2100 rows of data. I have read about using filters and getting rid of the for loop all together but I'm fairly new to coding in Google Script and haven't been able to get my head around the syntax for this. Any advice greatly appreciated.
Code below:
function Inspect() {a
var sSheet = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = sSheet.getSheetByName("Inventory");
var tarSheet = sSheet.getSheetByName("Inspections");
var lastRow = srcSheet.getLastRow();
for (var i = 2; i <= lastRow; i++) {
var cell = srcSheet.getRange("A" + i);
var val = cell.getValue();
if (val == true) {
var srcRange = srcSheet.getRange("B" + i + ":I" + i);
var clrRange = srcSheet.getRange("A" + i);
var tarRow = tarSheet.getLastRow();
tarSheet.insertRowAfter(tarRow);
var tarRange = tarSheet.getRange("A" + (tarRow+1) + ":H" + (tarRow+1));
var now = new Date();
var timeRange = tarSheet.getRange("I"+(tarRow+1));
timeRange.setValue(now);
srcRange.copyTo(tarRange);
clrRange.clear();
//tarRange.activate();
timeRange.offset(0, 1).activate();
}
}
};
Yes, to speed-up you will need to get all the values first and apply your logic to the obtained 2D-arrays instead of cells, at the end you will use setValues to update your sheet. I would go for something like this:
function Inspect() {
var sSheet = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = sSheet.getSheetByName("Inventory");
var tarSheet = sSheet.getSheetByName("Inspections");
var srcLastRow = srcSheet.getLastRow();
var tarLastRow = tarSheet.getLastRow();
var srcArray = srcSheet.getRange(1,1,srcLastRow,9).getValues();//(A1:I(lastrow))
var tarArray = tarSheet.getRange(1,1,tarLastRow,9).getValues();//(A1:I(lastrow))
for (var i = 1; i < srcArray.length; i++) {
var val = srcArray[i][0];
if (val == true) {
var copyValues = srcArray[i].slice(1);//Get all elements from the row excluding first column (srcSheet.getRange("B" + i + ":I" + i);)
var now = new Date();
copyValues[8]=now;//set the time on column 9 (array starts at position 0!)
var tarNewLine = copyValues;
tarArray.push(tarNewLine);
//clear values on source (except column A):
for(var j=1;j<srcArray[i].length;j++){
srcArray[i][j]="";
}
}
}
tarSheet.clear();
tarSheet.getRange(1, 1,tarArray.length,tarArray[0].length).setValues(tarArray);
srcSheet.clear();
srcSheet.getRange(1, 1,srcArray.length,srcArray[0].length).setValues(srcArray);
};
You cannot get around a loop, but you should reduce the number of calls to the SpreadsheetApp to a minimum, see Apps Script Best Practices
It is not the for loop, but those calls that make your code slow. Instead, work with arrays as much as you can. Loops become of a problem if they are nested - this is also something you should avoid.
Sample how to perform most calls to SpreadsheetApp outside of the loop and work with arrays:
function Inspect() {
var sSheet = SpreadsheetApp.getActiveSpreadsheet();
var srcSheet = sSheet.getSheetByName("Inventory");
var tarSheet = sSheet.getSheetByName("Inspections");
var lastRow = srcSheet.getLastRow();
var Acolumn = srcSheet.getRange("A2:A" + lastRow);
var Avalues = Acolumn.getValues();
var srcRange = srcSheet.getRange("B2:I" + lastRow);
var srcValues = srcRange.getValues();
var array = [];
var now = new Date();
for (var i = 0; i < lastRow-1; i++) {
var val = Avalues[i][0];
if (val == true) {
srcValues[i].push(now);
array.push(srcValues[i]);
var clrRange = Acolumn.getCell(i+1, 1);
clrRange.clear();
}
}
var tarRow = tarSheet.getLastRow();
tarSheet.insertRowAfter(tarRow);
if(array.length!=0){
var tarRange = tarSheet.getRange("A" + (tarRow+1) + ":I" + (tarRow + array.length));
tarRange.setValues(array);
}
};

JSLINQ - Distinct from multiple columns

I have a working JSFiddle demo
https://jsfiddle.net/u1fohjxw/
The idea is to create a unique list of items, based on multiple fields.
I know the way I've implemented it could be improved, but need advice on doing it in JSLINQ.
This filtered unique list I then manually loop and add again - this could be done in JSLINQ.
Please indicate how this should be done :
var myList = [
{FirstName:"Chris",LastName:"Pearson"},
{FirstName:"Chris",LastName:"Pearson"},
{FirstName:"Chris",LastName:"Sutherland"},
{FirstName:"John",LastName:"Ronald"},
{FirstName:"Steve",LastName:"Pinkerton"}
];
var exampleArray = JSLINQ(myList)
.Distinct(function(item){ return item.FirstName.concat(";",item.LastName)}).items
var newList = [];
for (var x = 0 ; x < exampleArray.length ; x++) {
var arraylist = exampleArray[x].split(";");
var y= new Object();
y.FirstName = arraylist[0];
y.LastName = arraylist[1];
newList.push(y);
};
how you doing? :)
Maybe something like this helps you out:
var myList = [
{FirstName:"Chris",LastName:"Pearson"},
{FirstName:"Chris",LastName:"Pearson"},
{FirstName:"Chris",LastName:"Sutherland"},
{FirstName:"John",LastName:"Ronald"},
{FirstName:"Steve",LastName:"Pinkerton"}
];
var resultList = myList.Distinct(function(x){
return {
FirstName: x.FirstName,
LastName: x.LastName
}
}).ToArray();
This will return an array of the object returned inside the distinct.
Edit:
Change the distinct method to this:
Distinct: function(clause) {
var item, dict = {}, retVal = [];
for (var i = 0; i < this.items.length; i++) {
item = clause.apply(this.items[i], [this.items[i]]);
if (dict[JSON.stringify(item)] === undefined) {
dict[JSON.stringify(item)] = true;
retVal.push(item);
}
}
dict = null;
return JSLINQ(retVal);
},
It's not stress tested, I don't know how much time will take to iterate through 10k+ objects, but it's something to study and improve! :)
There's another possible fix to this if you want to try.
Cheers!

Kendogrid population

I'm new to all this kendo stuff i need help in populating kendogrid from a csv file.
The csv data is stored in an array of strings returned by a service.
Data looks like :
0: "Module,LogLevel,LogType,LoggedTime,LogMessage"
1: "00D02D5A4B66 ,CommServer ,Level3 ,Information ,03/16/2015 00:32:57:5716 ,[ISOMMessageHandler::Initialize]-[EventCount:20,ObjectRetryCount:6]"
2: "00D02D5A4B66 ,CommServer ,Level1 ,Information ,03/16/2015 00:32:57:5716 ,ISOMProtocolHandler::HandleConnectGeneric] - Before UpdatePanelTouched - CommServerID : 1, ConnectionMode : 2"
3: "00D02D5A4B66 ,CommServer ,Level4 ,Information ,03/16/2015 00:32:57:5716 ,[PanelDataConfigurationHandler : UpdatePanelConnectionStatus] : CommServerID 1, CommMode : 2"
i need to display 0th indexed data as title of the columns
and rest in cells of the column.
My advice is to make a wrapper method yourself and get it into JSON.
needed wrapper as told by Thomas.
here is my wrapper function
function csvJSON(lines) {
var result = [];
var headers = lines[0].split(",");
headers.unshift("MAC");
for (var i = 1; i < lines.length; i++) {
var obj = {};
var currentline = lines[i].split(",");
for (var j = 0; j < headers.length; j++) {
obj[headers[j]] = currentline[j];
}
result.push(obj);
}
return result;
}

Google sheets, get range of rows, where column intersect cell is empty

Basically I want to use an auto-sorting script through the script editor in Google sheets, but I want it to smartly pick a range of rows, by only selecting those rows where a specific column has an empty cell.
All other rows that have that column's cell populated would stay put. Here is the sort code I've found.
/**
* Automatically sorts the 1st column (not the header row) Ascending.
*/
function onEdit(event){
var sheet = event.source.getActiveSheet();
var editedCell = sheet.getActiveCell();
var columnToSortBy = 1;
var tableRange = "A2:T99"; // What to sort.
if(editedCell.getColumn() == columnToSortBy){
var range = sheet.getRange(tableRange);
range.sort( { column : columnToSortBy, ascending: true } );
}
}
Thanks.
Note: this will only sort the values in the cells (metadata such as formats, notes etc will not be sorted, as they would with the GAS range.sort() method).
function onEdit(event)
{
var sheet = event.source.getActiveSheet();
var editedCell = sheet.getActiveCell();
var columnToSortBy = 0; // zero-based index
if (editedCell.getColumn() == columnToSortBy)
{
var columnToWatch = 5; // checking this column for blank cells (zero-based index)
var tableRange = "A2:T99"; // what to sort
var range = sheet.getRange(tableRange);
var data = range.getValues();
var dataCopy = data.slice();
dataCopy.sort(function(a, b) {return a[columnToSortBy] > b[columnToSortBy] ? 1 : (a[columnToSortBy] < b[columnToSortBy] ? -1 : 0);});
var j = -1;
for (var i = 0, length = data.length; i < length; i++)
{
if (data[i][columnToWatch].toString().length)
{
do j++; while (!dataCopy[j][columnToWatch].toString().length);
data[i] = dataCopy[j];
}
}
range.setValues(data);
}
}

Resources