I am trying to create an array that I can filter by in Google Apps Script. This works when the array is made of values I take from the columns using range.getValues(), but doesn't work when I create a similar multidimensional array using a loop.
I am trying to create the array myself as opposed to getting it from the sheet as the columns that I want are not consecutive: one is the 10th column, the next is the 1st, the next is the 3rd etc.
This works and returns the full multidimensional range filtered properly:
function RunReport(){
var errorSS = SpreadsheetApp.getActive();
var enterpriseSheet = errorSS.getSheetByName('Enterprise');
var destSheet = errorSS.getSheetByName('TestSheet');
var sheetData = [];
sheetData = enterpriseSheet.getRange(1, 1, 2000, 4).getValues();
var filtered = sheetData.filter(function(dataRow){
return dataRow[0] === 'Error';
});
Logger.log(filtered);
}
This 'works' but only returns the first 'column' of the array filtered by the 'Error value' but doesn't return the other parts of the array:
function RunReport(){
var errorSS = SpreadsheetApp.getActive();
var enterpriseSheet = errorSS.getSheetByName('Enterprise');
var destSheet = errorSS.getSheetByName('TestSheet');
var sheetData = [];
var col1 = enterpriseSheet.getRange(1, 1, enterpriseSheet.getLastRow()).getValues();
var col2 = enterpriseSheet.getRange(1, 10, enterpriseSheet.getLastRow()).getValues();
var col3 = enterpriseSheet.getRange(1, 2, enterpriseSheet.getLastRow()).getValues();
var col4 = enterpriseSheet.getRange(1, 3, enterpriseSheet.getLastRow()).getValues();
for (i = 0; i < col1.length; i++)
{
sheetData.push(col1[i],col2[i],col3[i],col4[i]) ;
}
var filtered = sheetData.filter(function(dataRow){
return dataRow[0] === 'Error';
});
Logger.log(filtered);
}
any ideas on what I am doing wrong?
Issue:
You're getting a 2D array.
You're pushing a four 1D arrays.
Solution:
You need to push 4 elements as a single array.
Modified Script:
push a single array with four elements
//sheetData.push(col1[i],col2[i],col3[i],col4[i]) ;
sheetData.push([col1[i][0],col2[i][0],col3[i][0],col4[i][0]]);
Alternatively, You can splice everything in col1:
//for(i=0 ; i<col1.length ; i++)
//{ sheetData.push(col1[i],col2[i],col3[i],col4[i]) ;}
col1.map(function(e,i){
e.splice(1,0,col2[i][0],col3[i][0],col4[i][0]);
return e;
});
Logger.log(col1);
References:
2D Array
Array#filter
Array#map
Array#Splice
Related
My current code grabs the values of the same range of data for Values, Notes, and Background Colors into 3 separate arrays. Then it filters the Values array by the first item in the nested array, returning only the items that matches the defined statArray array item. Now I want the other two array filters (Notes, Background) to be filtered by the indexes of the returned items from the filtered Value array. That way when I set the Backgrounds and Notes arrays they overlap correctly onto the values.
function moveAllNew() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var activeSheet = SpreadsheetApp.getActiveSheet();
var activeSheetName = activeSheet.getName();
var lastRow = activeSheet.getLastRow();
var lastColumn = activeSheet.getLastColumn();
var statArray = ["Captures Sent π©","QA In Progress π","Bagging in Progress 01 π","Bagging in Progress 02 π","Bag Sent π©","Bag Rejected β","Bag Accepted β
","Captured π·",""];
var rowHeaderCount = 3;
var rowStart = 4;
var columnFormulaB = 2;
var columnFormulaS = 19;
var columnFormulaAC = 29;
// gets the range of the current sheet
var activeRange = activeSheet.getRange(rowStart,1,lastColumn-rowHeaderCount,lastColumn);
var activeRangeFormulaB = activeSheet.getRange(rowStart,columnFormulaB,lastRow-rowHeaderCount);
var activeRangeFormulaS = activeSheet.getRange(rowStart,columnFormulaS,lastRow-rowHeaderCount);
var activeRangeFormulaAC = activeSheet.getRange(rowStart,columnFormulaAC,lastRow-rowHeaderCount);
// creates array of the active sheet (values, notes, backgrounds, and formula columns (B, S, AC))
var activeRangeValues = activeRange.getValues();
var activeRangeNotes = activeRange.getNotes();
var activeRangeBackgrounds = activeRange.getBackgrounds();
var activeRangeFormulaB = activeRangeFormulaB.getFormulasR1C1();
var activeRangeFormulaS = activeRangeFormulaS.getFormulasR1C1();
var activeRangeFormulaAC = activeRangeFormulaAC.getFormulasR1C1();
// filtered QA arrays
var qaSheet = ss.getSheetByName("QA π");
var qaRangeValues = activeRangeValues.filter(function(item){return item[0] === statArray[0] || item[0] === statArray[1];});
var qaRangeNotes = activeRangeNotes.filter(function(item){return item[0] === statArray[0] || item[0] === statArray[1];});
var qaRangeBackgrounds = activeRangeBackgrounds.filter(function(item){return item[0] === statArray[0] || item[0] === statArray[1];});
Logger.log(qaRangeValues);
Logger.log(qaRangeNotes);
Logger.log(qaRangeBackgrounds);
Currently the qaRangeValues and qaRangeNotes arrays would come back empty because the statArray item is never a color nor a note value.
Probably you meant to use lastRow instead of lastColumn when determining activeRange.
Anyway, you need to perform some operation that allows you to access the current indices, and while you have the indices, also operate on your other equal-sized arrays.
One example:
var qaData = {values: [], notes: [], bgs: [] };
activeRangeValues.forEach(function (row, idx) {
if (row[i] === statArray[0] || row[i] === statArray[1]) {
qaData.values.push(row);
qaData.notes.push(activeRangeNotes[idx]);
...
});
// Use the qaData object
I have a 2D array that looks like:
var example = [['Version', 'Number'], [ 'V1.0', 1 ], [ 'V2.0', 2 ]];
I'd like to iterate through the array and take out 'V1.0' and 'V2.0' and store them in their own new array, and do the same for '1' and '2'. I need to break the data up for use with Chart.js
My loop looks like this:
var labels = [];
var data = [];
for (var i=0; i<example.length; i++) {
labels.push = (example[i][0]);
}
for (var j=0; j<example.length; j++) {
data.push = (example[0][j]);
}
I don't know how to properly get either element into their own array for use later.
You can use map to do this, and shift the result in order to remove the first occurence.
var example = [
['Version', 'Number'],
['V1.0', 1],
['V2.0', 2]
];
var result = example.map(e => e[0])
console.log(result);
From what I saw into your example the first pair of elements are the keys for your data, into your example will include them into your final arrays.
This example will generate to a dictionary with the keys Number and Version containing the corresponding values from your array.
var example = [['Version', 'Number'], [ 'V1.0', 1 ], [ 'V2.0', 2 ]];
function extract(items) {
var keys = {},
version = items[0][0],
number = items[0][1];
keys[version] = [];
keys[number] = [];
return items.slice(1).reduce(function(acc, item) {
acc[version].push(item[0]);
acc[number].push(item[1]);
return acc;
}, keys);
}
var result = extract(example);
console.log(result);
From this point you can do something like:
var labels = result.Version;
var data = result.Number;
This looks like what you are trying to achieve:
for(var i=0; i<example.length; i++){
labels.push(example[i][0])
data.push(example[i][1])
}
What's the best way to convert this array of comma separated values
[ 'com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,on',
'com--fxtrimester,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,on' ]
Into three arrays?
[ 'com--test', [ LFutx9mQbTTyRo4A9Re5Ilsdf4cKN4q2', ['on',
'com--fxtrimester', SEzMpW3FxkSbzL7eo5MmlkdfqkPczCl2', 'on',
'com--fxtrimester' ] LFutksdfx9mQbTTyRo4A9Re5I4cKN4q2 ] 'on']
I was trying something like:
var indexToSplit = unique.indexOf(',');
var status = unique.slice(3, indexToSplit - 1);
var use = unique.slice(2, indexToSplit - 2);
var pros = unique.slice(0, indexToSplit - 3);
console.log(pros);
But I figured that is wrong ... any help is appreciated!
You will have to loop over array and use string.split to get seperate parts.
Once you have seperate parts, you can push them to necessary array;
var d = [ 'com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,on',
'com--fxtrimester,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,on'];
var result = [[],[],[]];
var len = 3;
d.forEach(function(str, i){
var _tmp = str.split(',');
for (var i = 0; i<len; i++){
result[i].push(_tmp[i])
}
})
console.log(result)
A little generic way.
Loop over data and split each string using comma(,)
Loop over split values and check if necessary array exists.
If not, initialise array, but you cannot do p[i] = [] as this will push to first value. You will have to also initialise all previous values. For this, you can use new Array(length). By default, if length is greater than 0, all indexes will be initialise to undefined.
Now push to necessary array. Position will be maintained.
var d = ['com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,on',
'com--fxtrimester,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,on,test'
];
var result = d.reduce(function(p, c, index) {
var _tmp = c.split(',');
for (var i = 0; i < _tmp.length; i++) {
// Check if position not defined.
if (p[i] === undefined)
// Initialize array and add default (undefined) to all elements before current element
p[i] = new Array(index);
p[i].push(_tmp[i])
}
return p;
}, [])
console.log(result)
With map this becomes:
for positions X out of 0, 1 and 2:
convert each item in the list into an array, and choose the Xth item
var start = [ 'com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,on',
'com--fxtrimester,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on',
'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,on' ]
var out = [0,1,2].map(i =>
start.map(x => x.split(',')[i]) )
console.log(out)
Since your question does not ask for a more general case, i am safely assuming it for 3 array. We can use forEach function on array below code can be one amongst the possible solutions
var arr1 = [];
var arr2 = [];
var arr3 = [];
var x = ['com--test,LFutx9mQbTTyRo4A9Re5ksjdnfsI4cKN4q2,on', 'com--fxtrimester,SEzlksdfMpW3FxkSbzL7eo5MmqkPczCl2,on', 'com--fxtrimester,LFutx9mQbTTyRoldksfns4A9Re5I4cKN4q2,on']
x.forEach(function(data) {
var dataArray = data.split(',');
arr1.push(dataArray[0]);
arr2.push(dataArray[1]);
arr3.push(dataArray[2]);
});
console.log(arr1)
console.log(arr2)
console.log(arr3)
I have this function:
flotLinea:function(tareas){
var self = this;
console.info(tareas);
var aTar = new Array();
for(var i = 0;i<tareas.length;i++){
var val = new Array(new Date(tareas[i].fecha_registro),tareas[i].porcentaje);
aTar.push(val);
}
console.info(aTar);
},
Using console.info(tareas); print this :
And using console.info(aTar); print :
(The data from tareas always is changing because the data comes from a dropdown)
I need create an new array for each id_usu using the same data , how can I do this?
For example in this case I need an array for id_usu = 4 ( are two id_usu = 4, so i need the data where id_usu = 4) , one array with id_usu = 6 and one array with id_usu = 9
I need do this , because this data are for a chart, so, after , each user ( id_usu ) will be a different color in that chart.
From whatever I have understood form your problem statement and the code you have provided, I've provided a solution below.
flotLinea:function(tareas){
var self = this;
console.info(tareas);
var aTar = new Array();
var idArray = [];
for(var i = 0;i<tareas.length;i++){
if(idArray.indexOf(tareas[i].id_usu) == -1){
var val = new Array(new Date(tareas[i].fecha_registro),
tareas[i].porcentaje);
idArray.push(tareas[i].id_usu);
aTar.push(val);
}
else{
for(var j = 0; j < aTar.length; j++){
if(tareas[i].id_usu == aTar[j][0].id_usu){
aTar[j].length = new Array(new Date(tareas[i].fecha_registro)
,tareas[i].porcentaje);
}
}
}
}
console.info(aTar);
}
I'm using Brute-Force kind of solution, performance can always be increased.
I've created on new array above as idArray to hold the unique id_usus, and am comparing if the current tareas[i].id_usu already is there in that array, if not push the new value to aTar array and tareas[i].id_usu to idArray, else loop over the aTar array and find the array which already has the object with the current tareas[i].id_usu and push the new values at aTar[j].length.
I have a JS array that's filled with data as follows:
var myarr = [[new Date("2011-12-01"), 389, 380.75, 382.54, 387.93],
[new Date("2011-11-30"), 382.28, 378.3, 381.29, 382.2]...]
Is there some way to only select the entire date column and the last number of each row? I'm looking for an output that's something like this:
[[new Date("2011-12-01"), 387.93],[new Date("2011-11-30"), 382.2]...]
var myCollapsedArr = [[myarr[0][0], myarr[0][myarr[0].length-1]], [myarr[1][0], myarr[1][myarr[1].length-1]];
Or in a for loop:
var myCollapsedArr = [];
for(var i = 0; i<myarr.length; i++) {
myCollapsedArr.push([myarr[i], [myarr[i][myarr[i].length-1]]);
}
Option 1 - Simple for Loop
// Create array to hold new values
var newArray = [];
// Loop through existing array and pull out data
for(var i = 0; i < myarr.length; i++) {
newArray.push([myarr[i][0], myarr[i][myarr[i].length - 1]]);
}
Here's a working fiddle to demonstrate.
Option 2 - ECMAScript 5 forEach()
// Create array to hold new values
var newArray = [];
// Loop through existing array and pull out data
myarr.forEach(function(obj) {
newArray.push([obj[0], obj[obj.length - 1]]);
});
βHere's a working fiddle to demonstrate.