I'm in the making of a google sheets app script where I want to check if a value from one cell is in an array of values, then find what the index is so I can direct my function to that cell.
I'm at the point where I have my array in a variable called distArray, and I want to check if "id" is in that array.
Here's the code to better visualize:
function logs() {
let app = SpreadsheetApp
let dest = app.getActiveSpreadsheet().getSheetByName("Baza Danych");
let lastrow = dest.getLastRow();
let destArr = dest.getRange(2, 1, lastrow).getValues();
let id = app.getActiveSpreadsheet().getSheetByName("Zgloszenia").getRange(6, 2).getValue();
let position = destArr.indexOf(id);
Logger.log(id)
Logger.log(destArr)
Logger.log(position)
}
And here is the output I get.
My problem is that no matter what the value of "id" is, the index is either -1 or 0 meaning the value either is not in the array or is in the first cell.
Try to add .flat() at the end of the line:
let destArr = dest.getRange(2, 1, lastrow).getValues();
This way:
let destArr = dest.getRange(2, 1, lastrow).getValues().flat();
Explanation:
The method getValues() gives you a 2d array [[1],[2],[3],...].
The flat() method converts a 2d array into an ordinary flat array [1,2,3,...].
After that you will able to use array.indexOf(element) to get an index of the element in the array.
Description
Yuri's solution is a good example if you don't want to know which element of the array contains the value your looking for. But if you need to know which row of the array contains the value the following example shows how to search a 2D array.
Script
function find() {
try {
let a = [['a','b'],['c','d'],['e','f'],['g','h']];
let b = "f";
let c = a.findIndex( d => d.indexOf(b) >= 0 );
console.log("c = "+c);
}
catch(err) {
console.log(err);
}
}
7:51:23 AM Notice Execution started
7:51:24 AM Info c = 2
7:51:23 AM Notice Execution completed
Reference
Array.findIndex()
Array.indexOf()
Related
I'm trying to push a value into a 2d array but I'm getting the error:
Cannot read property 'push' of undefined
Here's a MWE of my code:
var saida = new Array()
for (i in dbInfo){
saida[i].push(i)
}
Where dbInfo is a range in my sheet, but can be replaced by any other range for this example. I need the output to be a 2d array so I can work out the values into the sheet.
If you just created the array the array is empty. So saida[n] will be undefined no matter what value n has.
You need to first create it. Then you can push into it.
Maybe something like this? Not sure what you need.
var saida = new Array()
for (i in dbInfo){
saida[i]=[]
saida[i].push(i)
}
If dbInfo is an object of type Range from the Sheet, then the returned array after using getValues is already a 2D array so a simple assignment will suffice:
function addData() {
// your other code
let dbInfoVals = dbInfo.getValues();
let saida = dbInfoVals;
console.log(saida)
}
However, if dbInfo is a 1D array, transforming into a 2D one can be done by using the splice method in JavaScript:
function addData() {
// your other code
let saida = [];
while (dbInfo.length){
saida.push(dbInfo.splice(0, 2));
}
console.log(saida);
}
The second parameter of splice will give you the number of columns, so you might need to adjust this to match your range accordingly.
Reference
Range Class - getValues();
Array.prototype.splice().
You will need to define your array to 2d
Eg: int[,] arr= new string[3, 2];
You will need to iterate twice.
for(int col1 = 0; col1 < arr.GetLength(0); col1++){
for(int row1 = 0; row1 < arr.GetLength(1); row1++)
{
arr[col1,row1] = 2;
}
}
I am using google sheets quite a lot, but now I am trying to use google apps script to get and update dynamic data retrieved from formulas into a static table.
So, I have a sheet called 'dynamique', with formulas retrieving, filtering and sorting data from other spreadsheets.
I want to be able to work on this data, so I am trying to create a button which would copy all the values from the 'dynamique' sheet into another sheet called 'statique'. That is, I want a formula which would check if the values from the column C of the 'dynamique' sheet are in the column C of the 'statique' sheet. And if the values aren't there, I want the script to copy them. (columns A and B are empty)
I've managed to get my script to work for one column, but now, I want to copy the whole line.
For example, if the value in dynamique!C10 can't be found in statique!C:C, my script writes the value of dynamique!C10 in the first empty cell of the column statique!C:C. But I want it to write dynamique!C10:J10 into my destination sheet (say it's going to be maybe statique!C8:J8).
Here is my code, working for only one cell.
function dynamicToStatic() {
var dynSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("dynamique");
var staSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("statique");
var dynLength = dynSheet.getRange("C1:C").getValues().filter(String).length;//.getLastRow();
var staLength = staSheet.getRange("C1:C").getValues().filter(String).length;
var staRange = staSheet.getRange(6,3,staLength-1);
var staValues = staRange.getValues();
var rangeToCheck = dynSheet.getRange(6,3,dynLength-1,8);
var valuesToCheck = rangeToCheck.getValues();
var numRows = rangeToCheck.getNumRows();
var staNumRows = staRange.getNumRows();
for (i = 0; i<= numRows; i++) {
var row = valuesToCheck[i];
var index = ArrayLib.indexOf(staValues , -1 , row);
if (index == -1) {
//if (staValues.indexOf(row) != -1) {
staSheet.getRange(i+6,3,1,8).setValues(row);
}
}
var timestamp = new Date();
staSheet.getRange(4,3).setValue('List updated on the: '+timestamp);
}
Now I can't manage to retrieve the whole line of the array, so as to be able to copy it using range.setValues(). I always get error messages.
Any help would be more than appreciated...
function gettingFullRows() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName('Sheet1');
const shsr=2;//data startrow
const vA=sh.getRange(shsr,1,sh.getLastRow()-shsr+1,sh.getLastColumn()).getValues();
let html='';
vA.forEach((r,i)=>{
html+=Utilities.formatString('<br />Row:%s is %s',i+shsr,r.join(','));
});
SpreadsheetApp.getUi().showModelessDialog(HtmlService.createHtmlOutput(html), "Row");
}
So i did some re-writing to your code and made some comments in there. I hope this will make some things clear.
Array's are 0 indexed. So if the value is NOT found in the .indexOf then it would return -1. Also (for speed) i first push all the result to a array and then set the array in one "action" this saves a lot of time. The calls to and from a sheet takes the most time.
For the conversion to a 1d array i used spread operator
See this link for difference in const / var / let
The timestamp string i updated with the use of Template literals
If you have some questions, shoot! (also i did not test this ofcourse)
function dynamicToStatic() {
const dynSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("dynamique");
const staSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("statique");
const dynValues = dynSheet.getRange(1,3,dynSheet.getLastRow(),8).getValues();
//This is a 2d array
const staRaw = staSheet.getRange(6, 3, staSheet.getLastRow()).getValues();
//Convert to 1d array, for the indexoff later on, this way it is easier.
const staValues = [].concat(...staRaw);
//to store the output, as a 2d array, inside the if you see i push it in as array so you have the 2d array for the setValues.
const output = [];
for (let i = 0; i < dynValues.length; i++){
//i = the index of the array (row) inside the array of rows, the 0 would be the values of column C.
if (staValues.indexOf(dynValues[i][0]) >= 0){
output.push([dynValues[i]]);
}
}
//Start by the lastrow + 1, column C(3), ouput is a array of arrays(rows), then get the [0].lengt for the columns inside the row array.
staSheet.getRange(staSheet.getLastRow()+1, 3, output.length, output[0].lenght).setValues(output);
const timestamp = new Date();
staSheet.getRange(4,3).setValue(`List updated on the: ${timestamp}`);
}
I wanted to know how can we get every alternate object in a array. For EG -
arr = ["foo","bar","foo1","bar1"]
I Need The values -
fir_alt = ["foo","foo1"]
sec_alt = ["bar","bar1"]
If This Helps This Is My Intention -
I am trying to link localstorage and firestore using the js-sdk.. Data is in array and have to take the array to store it back in localstorage.fir_alt would be the keys and sec_alt would be values. So I Can Make it Much More Multi-Device..
Thanks In Advance
You can use the filter function to filter out even and odd index's.
arr = ["foo","bar","foo1","bar1"]
fir_alt = arr.filter((element, index) => index % 2 == 0);
sec_alt = arr.filter((element, index) => index % 2 == 1);
console.log('fir_alt', fir_alt)
console.log('sec_alt', sec_alt)
I'd use an index variable and a loop(for/next or your fav). Examine the index on each iteration of the loop, and determine if the index is odd or even(or 0), then take the appropriate action to capture the desired values.
If I know what you mean... We can be reasoned with odd and even index.
In this way:
let arr = ["foo","bar","foo1", "bar1"],
fir_alt = [],
sec_alt = [];
for (let i=0;i<arr.length;i++){
if ((i+2)%2==0) {
sec_alt.push(arr[i]);
}
else {
fir_alt.push(arr[i]);
}
}
Very close but slightly more complex than this question I have an array and I want to obtain the index of the array of the first occurrence of a value of a given object of this array.
My array has several objects of integer and text, and has an id object of integers (which I call with this instruction wup[i].id).
[edit] The array comes from reading a csv file with header with papaparse.
wup = ["id", "cityName", etc ... ]
[20002, "Tokyo", etc ... ]
[20003, "GoiĆ¢nia", etc ... ]
It is in this id object only that I want to find the input value and finally get the index of this input value. This is certainly using indexOf but how to focus the search only in the id object?
[edit] the instruction that fails is the following (try to find the occurrence of tn[iter].idOri in the array wup, that I expect to retrieve in the variable iOri):
var iOri = wup.indexOf(tn[iter].idOri);
Hoping it is clear enough.
There are lots of ways to do this, map your array down to a flat array of ids:
var myId = 3;
var ids = array.map(function(obj) {
return obj.id;
});
var index = ids.indexOf(myId);
A more succinct (and better - because it only requires one iteration) method would be to use Array.findIndex:
var myId = 3;
var index = array.findIndex(function(obj) {
return obj.id === myId;
});
With es6:
var myId = 3;
var index = array.map(obj => obj.id).indexOf(myId);
or
var myId = 3;
var index = array.findIndex(obj => obj.id === myId);
Seen this question a lot, but cannot find something that's what i'm looking for.
onClick I push an item to an array I have, however, if there's 3 items in my array I don't want to be able to push items anymore.
var selectedData = [];
I set my empty variable.
var index = selectedData.indexOf(3);
I then get the index of my array which is 3
if (index > 3) {
selectedData.splice(index, 1);
}
Then within my if statement I say, if my index which is 3, is bigger then 3, then splice at index and remove one.
selectedData.push(TheThing);
I then push TheThing to my array if the if statement above isn't true.
However, I have a variable var arrayLength = selectedData.length; that grabs the length, and when I console log it, it starts at 0 and splices items anything after 4. Not 3.
Any idea what i've done wrong or misunderstood?
Thanks
More full example of my code
var selectedData = [];
myElement.on('click', function() {
var index = selectedData.indexOf(3);
if (index > 3) {
selectedData.splice(index, 1);
}
var arrayLength = selectedData.length;
console.log(arrayLength, 'the length');
});
So in short, onClick check my array and remove anything after the third that gets added into my array.
Do you want this to behave as a stack or a queue?
So your code here:
var index = selectedData.indexOf(3);
Is not grabbing the 3rd index - its grabbing the first index where it sees 3, or -1 if it doesn't. Replace your if statement with,
if (selectedData.length > 3) {
selectedData.pop() // removes last element (stack)
// or
selectedData = selectedData.slice(1) //remove first element (queue)
}
I think you need to try var arrayLength = selectedData.length -1;
You start at 0 like a normal array, but don't you start with an empty array?
Plus when you use .length, it returns the true count of the array or collection not a 0 index.
`
you can override push() method of your array like this:
var a = [];
a.push = function(){}
or like this
a.push = function (newEl){
if(this.length <3){
Array.prototype.push.call(this, newEl)
}
}
This is not complete example because push() can take many arguments and you should to handle this case too
var index = selectedData.indexOf(3); simply give you the index of the element of the array that has value 3
Example
selectedData = [ 0, 3 , 2];
alert( selectedData.indexOf( 3 ) ); // this will alert "1" that is the index of the element with value "3"
you can use this scenario
var selectedData = [];
myElement.on('click', function() {
//if selectedData length is less than 3, push items
});
This could work.
myElement.on('click', function() {
if(selectedData.length > 3){
selectedData = selectedData.splice(0, 3);
}
console.log(selectedData.length, 'the length');
});