Issues with indexOf in Javascript - javascript

I am having issues with indexOf in Javascript. It seems IndexOf fails to find a string when the it is obtained using .getValues() from a spreadsheet.
For example, the function below works fine.
function Narek() {
var array = ["Armine", "Narek", "Suren"]
var ggg = array.indexOf("Armine");
}
But this function, which gets the same names from the googlesheets returns -1.
function Narek() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("HL rota");
var array = ss.getRange(45,1,3,1).getValues();
var pickedHLM = ss.getRange(49,1,1,1).getValue();
var ggg = array.indexOf(pickedHLM);
Logger.log(pickedHLM)
Logger.log(ggg);
}
Any one can help?

While Range#getValue() returns the top-left cell content (in this case the value inside A49), #getValues() returns a two-dimensional array of the cell contents of the whole range (ie A45:A47). Each inner array holds the row's values.
So perhaps more similar to:
var values = [["Armine"], ["Narek"], ["Suren"]];
This can be transformed into your expectation of a flat array.
var array = values.map(function(row) { return row[0]; });
// ["Armine", "Narek", "Suren"]

Related

Automate Hyperlink Creations

I'm trying to automate hyperlink creations on my GSheet.
Here's my script:
function ticketURLGenerator() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Data");
var range = sheet.getRange("C2:C");
var ticketID = range.getValue();
Logger.log(ticketID);
for(i = 0; i < ticketID.length; i++){
if(ticketID.length === 0){
ticketID.setValue('')
} else if(ticketID.length > 4){
ticketID.setValue('=HYPERLINK' + '("https://mylink.com/'+ticketID+'";'+ticketID+')');
}
}
}
It does nothing but when I change ticketID.setValue by sheet.getRange("C2:C").setValue it put the whole range in the url. We can see with Logger.log(ticketID) that the whole range is selected.
So according to this result, i'm missing how to get the value of each cell individualy in the range and then check if they are long enought to create an individual url. Do I need to use something like range[i] somewhere? I'm lost.
I believe your goal as follows.
You want to retrieve the values from the cells "C2:C".
When the length of value is more than 4, you want to create a formula of HYPERLINK.
When the length of value is less than 4, you don't want to put the formula.
You want to put the formulas to the cells "C2:C".
Modification points:
When range of var range = sheet.getRange("C2:C") is used, the value of var ticketID = range.getValue() is the value of cell "C2". When you want to retrieve values from the cells "C2:C", please use getValues instead of getValue.
In this case, the retrieved value is 2 dimensional array.
When range.getValue() is the string value, ticketID of var ticketID = range.getValue() is also the string. So I think that when ticketID.setValue('##') is run, an error occurs.
In your script, setValue is used in a loop. In this case, the process cost will become high.
And, when sheet.getRange("C2:C" + sheet.getLastRow()) is used instead of sheet.getRange("C2:C"), the process cost will become low a little.
When above points are reflected to your script, it becomes as follows.
Modified script:
function ticketURLGenerator() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName("Data");
var range = sheet.getRange("C2:C" + sheet.getLastRow());
var ticketIDs = range.getValues();
var values = ticketIDs.map(([c]) => [c.toString().length > 4 ? `=HYPERLINK("https://mylink.com/${c}";"${c}")` : c]);
range.setValues(values);
}
In this modification, the values are retrieved from the cells of "C2:C" + sheet.getLastRow(), and an array including the formulas and values is created, and then, the array is put to the cells.
And I used the template literal for creating the formula.
Note:
In this case, please use this script with enabling V8 runtime.
References:
getLastRow()
getValues()
map()
Template literals
You just need to apply the HYPERLINK operation to the tickets that their length is more than 4. To achieve that, you can use map() to iterate over all the elements in your list.
Solution:
function ticketURLGenerator() {
const ss = SpreadsheetApp.getActiveSpreadsheet();
const sheet = ss.getSheetByName("Data");
const ticketR = sheet.getRange("C2:C"+sheet.getLastRow());
const ticketIDs = ticketR.getDisplayValues().flat();
const hLinks = ticketIDs.map(ti=>{
if(ti.length>4) {
return [`=HYPERLINK("https://mylink.com/${ti}"; ${ti})`]}
else {return [ti]}
})
ticketR.setValues(hLinks);
}

How to take a single cell and a range in a custom function and take the range data in an array in google sheets

Firstly, I am very new here. Searched the whole internet about this and finally landing a question here.
function StockCoverW(stock,range){
var x = stock;
var r = SpreadsheetApp.getActiveSheet().getDataRange().getValues();
var r1 = SpreadsheetApp.getActiveSheet().getNamedRanges(range);
}
Here, stock is a single cell for example: A1
and range is a range of cell for example: A2:E2
so the function call will be StockCoverW(A1,A2:E2)
now I need to take the values from the range cells into an Array.
Obviously the code here is not correct as cannot debug or do anything.
How to implement this in google spreadsheet script?
Change getDataRange (which grabs all valued on sheet) to getRange(range)
function StockCoverW(stock,range){
var x = stock;
var r = SpreadsheetApp.getActiveSheet().getRange(range).getValues();
var r1 = SpreadsheetApp.getActiveSheet().getNamedRanges(range);
}
Note though that the function doesn’t return or alter anything so when it runs it just gets the valued and the named ranges.
Also note that the array you get with values is a 2d array and if you want it to be just a simple array then use
function StockCoverW(stock,range){
var x = stock;
var r = SpreadsheetApp.getActiveSheet().getRange(range).getValues()[0];
var r1 = SpreadsheetApp.getActiveSheet().getNamedRanges(range);
}

For loop not performing last function in array (JavaScript)

The last function in the boxFill() array is not being performed. I've tried accounting for the length of the array but to no luck. (I'm very new to js, just saying). It iterates through the first four indices, and always does not perform the last index, even when I change the position of the index.
var pResult1 = document.getElementById("result1");
var pResult2 = document.getElementById("result2");
var pResult3 = document.getElementById("result3");
var pResult4 = document.getElementById("result4");
var pResult5 = document.getElementById("result5");
var pResult = [pResult1,pResult2,pResult3,pResult4,pResult5]
function checkBox() {
/*var aFlor = [2.8,"Florida","Science"];
var bGeo = [3.5,"Georgia","Business"];
var cTex = [2.3,"Texas","Health"];
var dNew = [4.2,"NewYork","Law"];
var eMic = [3.9,"Michigan","Humanities"];*/
var boxValue = document.getElementById("searchBox").value;
var boxFill = [
function(){listBox('1','Florida state Scholarship','3.5','Florida','Applied Sciences')},
function(){listBox('2','Great Achievers Scholarship','4.0','Texas','Health')},
function(){listBox('3','Helpful Future Scholarship','3.0','Georgia','Business')},
function(){listBox('4','Never Give Up Scholarship','2.0','Michigan','Humanities')},
function(){listBox('5','Times Square Talent Scholarship','3.5','New York','Law')}
]
if (boxValue.includes("f")) {
for (i=0;i<boxFill.length+1;i++) {
boxFill[i]();
}
function listBox(number,name,gpa,state,major) {
pResult[number].innerHTML =
"<dl><dt>"+number+". "+name+"</dt><dd>- minimum GPA is: "+gpa+"</dd><dd>- You must live in "+state+"</dd><dd>- For the "+major+" major!</dd></dl>";
}
Is there a direct problem with the for loop or is it something in the array itself?
i<boxFill.length+1 should be i<boxFill.length, otherwise your loop iterates one more time than there are elements.
The function gets called, but it will throw an error because it tries to access an index in pResult that doesn't exist. If you open your browser's console you should see an error such as
Cannot read property 'innerHTML' of undefined
Arrays are zero-indexed in JavaScript. That means that pResult[0] will access the first element, pResult[1] accesses the second element, etc.
Now, the last function in boxFill tries to access pResult[5], i.e. the sixth element. But pResult only has five elements!
You need pass the values 0 to 4 to listBox, not 1 to 5:
var boxFill = [
function(){listBox(0,'Florida state Scholarship','3.5','Florida','Applied Sciences')},
function(){listBox(1,'Great Achievers Scholarship','4.0','Texas','Health')},
function(){listBox(2,'Helpful Future Scholarship','3.0','Georgia','Business')},
function(){listBox(3,'Never Give Up Scholarship','2.0','Michigan','Humanities')},
function(){listBox(4,'Times Square Talent Scholarship','3.5','New York','Law')}
]
Or if you want to pass 1-5 then you need to subtract 1 when accessing the index:
pResult[number-1].innerHTML = ...;

How to remove all characters before specific character in array data

I have a comma-separated string being pulled into my application from a web service, which lists a user's roles. What I need to do with this string is turn it into an array, so I can then process it for my end result. I've successfully converted the string to an array with jQuery, which is goal #1. Goal #2, which I don't know how to do, is take the newly created array, and remove all characters before any array item that contains '/', including '/'.
I created a simple work-in-progress JSFiddle: https://jsfiddle.net/2Lfo4966/
The string I receive is the following:
ABCD,ABCD/Admin,ABCD/DataManagement,ABCD/XYZTeam,ABCD/DriverUsers,ABCD/RISC
ABCD/ in the string above can change, and may be XYZ, MNO, etc.
To convert to an array, I've done the following:
var importUserRole = 'ABCD,ABCD/Admin,ABCD/DataManagement,ABCD/XYZTeam,ABCD/DriverUsers,ABCD/RISC';
var currentUserRole = importUserRole.split(',');
Using console.log, I get the following result:
["ABCD", "ABCD/Admin", "ABCD/DataManagement", "ABCD/XYZTeam", "ABCD/DriverUsers", "ABCD/RISC"]
I'm now at the point where I need the code to look at each index of array, and if / exists, remove all characters before / including /.
I've searched for a solution, but the JS solutions I've found are for removing characters after a particular character, and are not quite what I need to get this done.
You can use a single for loop to go through the array, then split() the values by / and retrieve the last value of that resulting array using pop(). Try this:
for (var i = 0; i < currentUserRole.length; i++) {
var data = currentUserRole[i].split('/');
currentUserRole[i] = data.pop();
}
Example fiddle
The benefit of using pop() over an explicit index, eg [1], is that this code won't break if there are no or multiple slashes within the string.
You could go one step further and make this more succinct by using map():
var importUserRole = 'ABCD,ABCD/Admin,ABCD/DataManagement,ABCD/XYZTeam,ABCD/DriverUsers,ABCD/RISC';
var currentUserRole = importUserRole.split(',').map(function(user) {
return user.split('/').pop();
});
console.log(currentUserRole);
You can loop through the array and perform this string replace:
currentUserRole.forEach(function (role) {
role = role.replace(/(.*\/)/g, '');
});
$(document).ready(function(){
var A=['ABCD','ABCD/Admin','ABCD/DataManagement','ABCD/XYZTeam','ABCD/DriverUsers','ABCD/RISC'];
$.each(A,function(i,v){
if(v.indexOf('/')){
var e=v.split('/');
A[i]=e[e.length-1];
}
})
console.log(A);
});
You could replace the unwanted parts.
var array = ["ABCD", "ABCD/Admin", "ABCD/DataManagement", "ABCD/XYZTeam", "ABCD/DriverUsers", "ABCD/RISC"];
array = array.map(function (a) {
return a.replace(/^.*\//, '');
});
console.log(array);
var importUserRole = 'ABCD,ABCD/Admin,ABCD/DataManagement,ABCD/XYZTeam,ABCD/DriverUsers,ABCD/RISC';
var currentUserRole = importUserRole.split(',');
for(i=0;i<currentUserRole.length;i++ ){
result = currentUserRole[i].split('/');
if(result[1]){
console.log(result[1]+'-'+i);
}
else{
console.log(result[0]+'-'+i);
}
}
In console, you will get required result and array index
I would do like this;
var iur = 'ABCD,ABCD/Admin,ABCD/DataManagement,ABCD/XYZTeam,ABCD/DriverUsers,ABCD/RISC',
arr = iur.split(",").map(s => s.split("/").pop());
console.log(arr);
You can use the split method as you all ready know string split method and then use the pop method that will remove the last index of the array and return the value remove pop method
var importUserRole = ABCD,ABCD/Admin,ABCD/DataManagement,ABCD/XYZTeam,ABCD/DriverUsers,ABCD/RISC';
var currentUserRole = importUserRole.split(',');
for(var x = 0; x < currentUserRole.length; x++;){
var data = currentUserRole[x].split('/');
currentUserRole[x] = data.pop();
}
Here is a long way
You can iterate the array as you have done then check if includes the caracter '/' you will take the indexOf and substact the string after the '/'
substring method in javaScript
var importUserRole = 'ABCD,ABCD/Admin,ABCD/DataManagement,ABCD/XYZTeam,ABCD/DriverUsers,ABCD/RISC';
var currentUserRole = importUserRole.split(',');
for(var x = 0; x < currentUserRole.length; x++){
if(currentUserRole[x].includes('/')){
var lastIndex = currentUserRole[x].indexOf('/');
currentUserRole[x] = currentUserRole[x].substr(lastIndex+1);
}
}

Dynamically create a two dimensional Javascript Array

Can someone show me the javascript I need to use to dynamically create a two dimensional Javascript Array like below?
desired array contents:
[["test1","test2","test3","test4","test5"],["test6","test7","test8","test9","test10"]]
current invalid output from alert(outterArray):
"test6","test7","test8","test9","test10","test6","test7","test8","test9","test10"
JavaScript code:
var outterArray = new Array();
var innerArray = new Array();
var outterCount=0;
$something.each(function () {
var innerCount = 0;//should reset the inner array and overwrite previous values?
$something.somethingElse.each(function () {
innerArray[innerCount] = $(this).text();
innerCount++;
}
outterArray[outterCount] = innerArray;
outterCount++;
}
alert(outterArray);
This is pretty cut and dry, just set up a nested loop:
var count = 1;
var twoDimensionalArray =[];
for (var i=0;i<2;i++)
{
var data = [];
for (var j=0;j<5;j++)
{
data.push("Test" + count);
count++;
}
twoDimensionalArray.push(data);
}
It sounds like you want to map the array of text for each $something element into an outer jagged array. If so then try the following
var outterArray = [];
$something.each(function () {
var innerArray = [];
$(this).somethingElse.each(function () {
innerArray.push($(this).text());
});
outterArray.push(innerArray);
});
alert(outterArray);
A more flexible approach is to use raw objects, they are used in a similar way than dictionaries. Dynamically expendables and with more options to define the index (as string).
Here you have an example:
var myArray = {};
myArray[12]="banana";
myArray["superman"]=123;
myArray[13]={}; //here another dimension is created
myArray[13][55]="This is the second dimension";
You don't need to keep track of array lengths yourself; the runtime maintains the ".length" property for you. On top of that, there's the .push() method to add an element to the end of an array.
// ...
innerArray.push($(this).text());
// ...
outerArray.push(innerArray);
To make a new array, just use []:
innerArray = []; // new array for this row
Also "outer" has only one "t" :-)
[SEE IT IN ACTION ON JSFIDDLE] If that $something variable is a jQuery search, you can use .map() function like this:
var outterArray = [];
var outterArray = $('.something').map(function() {
// find .somethingElse inside current element
return [$(this).find('.somethingElse').map(function() {
return $(this).text();
}).get()]; // return an array of texts ['text1', 'text2','text3']
}).get(); // use .get() to get values only, as .map() normally returns jQuery wrapped array
// notice that this alert text1,text2,text3,text4,text5,text6
alert(outterArray);​
// even when the array is two dimensional as you can do this:
alert(outterArray[0]);
alert(outterArray[1]);
HTML:
<div class="something">
<span class="somethingElse">test1</span>
<span class="somethingElse">test2</span>
<span class="somethingElse">test3</span>
</div>
<div class="something">
<span class="somethingElse">test4</span>
<span class="somethingElse">test5</span>
<span class="somethingElse">test6</span>
</div>
Here you can see it working in a jsFiddle with your expected result: http://jsfiddle.net/gPKKG/2/
I had a similar issue recently while working on a Google Spreadsheet and came up with an answer similar to BrianV's:
// 1st nest to handle number of columns I'm formatting, 2nd nest to build 2d array
for (var i = 1; i <= 2; i++) {
tmpRange = sheet.getRange(Row + 1, Col + i, numCells2Format); // pass/fail cells
var d2Arr = [];
for (var j = 0; j < numCells2Format; j++) {
// 1st column of cells I'm formatting
if ( 1 == i) {
d2Arr[j] = ["center"];
// 2nd column of cells I'm formatting
} else if ( 2 == i ) {
d2Arr[j] = ["left"];
}
}
tmpRange.setHorizontalAlignments( d2Arr );
}
So, basically, I had to make the assignment d2Arr[index]=["some string"] in order to build the multidimensional array I was looking for. Since the number of cells I wanted to format can change from sheet to sheet, I wanted it generalized. The case I was working out required a 15-dimension array. Assigning a 1-D array to elements in a 1-D array ended up making the 15-D array I needed.
you can use Array.apply
Array.apply(0, Array(ARRAY_SIZE)).map((row, rowIndex) => {
return Array.apply(0, Array(ARRAY_SIZE)).map((column, columnIndex) => {
return null;
});
});`

Categories

Resources