I tried to write the script as shown below. It is necessary to combine the values and background colors in this cell range into a single array. But it does not come as needed.
function newsheet(){
var app = SpreadsheetApp
var ss = app.getActiveSpreadsheet().getSheetByName("AddData");
//get category if checked
var catList = ss.getRange("I5:J31").getValues();
var catClrs = ss.getRange("J5:J31").getBackgrounds();
var c = catList.map((key,index) => ({[key]:catClrs[index]}));
Logger.log(c);
}
The answer comes this way
But I want an outcome like this.
[{Extra,true,#b6d7a8}, {Extra,false,#ffffff}, {Extra,false,#ffffff}, {Ldrain ,false,#ffffff}, {Dish Drain,true,#0c343d}, {U drain,true,#274e13}, {Hard Sholder,true,#00ffff}, {Soft Sholder,true,#cc0000}, {As. wearing,true,#ff9900}, {Tack coat Wearing,true,#fce5cd}, {As.Binder,true,#9900ff}, {Tack Coat binder,true,#46bdc6}, {Prime coat,true,#000000}, {ABC overlay,false,#ffffff}, {Subbase overlay,true,#980000}, {Edgewidning ABC,true,#999999}, {Edgewidning Subbase,false,#ffffff}, {SubGrade Ew,true,#0000ff}, {Embankment 5,true,#9fc5e8}, {Embankment 4,true,#6fa8dc}, {Embankment 3,true,#3d85c6}, {Embankment 2,true,#0b5394}, {Embankment 1,true,#1c4587}, {Subgrade Emb,true,#8e7cc3}, {Soft Ground tratment 1,true,#c27ba0}, {Soft Ground tratment 2,true,#a64d79}, {Clearing & grabbing,true,#f1c232}
I'd do it like this because it will be easier to read the values as you iterate through the array by having property labels for the object
function myobject(){
const ss=SpreadsheetApp.getActive()
var sh = ss.getSheetByName("AddData");
var catList = sh.getRange("I5:J31").getValues();
var catClrs = sh.getRange("J5:J31").getBackgrounds().flat();
let c=[];
catList.forEach((row,i) => {c.push({label:row[0],value:row[1],color:catClrs[i]})});
Logger.log(JSON.stringify(c));
}
With my fake data:
[{"label":3,"value":21,"color":"#ffffff"},{"label":0,"value":17,"color":"#ffffff"},{"label":5,"value":29,"color":"#ffffff"},{"label":29,"value":25,"color":"#ffffff"},{"label":16,"value":24,"color":"#ffffff"},{"label":17,"value":15,"color":"#ffffff"},{"label":22,"value":4,"color":"#ffffff"},{"label":6,"value":1,"color":"#ffffff"},{"label":4,"value":28,"color":"#ffffff"},{"label":14,"value":28,"color":"#ffffff"},{"label":13,"value":1,"color":"#ffffff"},{"label":2,"value":15,"color":"#ffffff"},{"label":23,"value":6,"color":"#ffffff"},{"label":14,"value":24,"color":"#ffffff"},{"label":21,"value":6,"color":"#ffffff"},{"label":12,"value":18,"color":"#ffffff"},{"label":12,"value":7,"color":"#ffffff"},{"label":5,"value":5,"color":"#ffffff"},{"label":2,"value":0,"color":"#ffffff"},{"label":16,"value":16,"color":"#ffffff"},{"label":15,"value":21,"color":"#ffffff"},{"label":0,"value":25,"color":"#ffffff"},{"label":20,"value":6,"color":"#ffffff"},{"label":24,"value":23,"color":"#ffffff"},{"label":22,"value":0,"color":"#ffffff"},{"label":14,"value":15,"color":"#ffffff"},{"label":24,"value":6,"color":"#ffffff"}]
Added flat()
Replaced key by row, index by i and ({[key]:catClrs[index]}) by [row[0],row[1],catClrs[i]]
function newsheet(){
var app = SpreadsheetApp
var ss = app.getActiveSpreadsheet().getSheetByName("AddData");
//get category if checked
var catList = ss.getRange("I5:J31").getValues();
var catClrs = ss.getRange("J5:J31").getBackgrounds().flat();
var c = catList.map((row,i) => [row[0],row[1],catClrs[i]]);
Logger.log(c);
}
The result will be slightly different because {} is used for objects and objects requires a key and a value.
I changed key by row to make the variable name closer to what it's holding as usually a "key" is a string but in this case it's an Array holding the values of two cells in the same row. i is shorter than index.
Nothing new compared to the accepted answer, but just shortening your code and a slighty better performance:
function newsheet(){
const ss = SpreadsheetApp.getActive().getSheetByName("AddData");
const range = ss.getRange("I5:J31");
const [catList,catClrs] = [range.getValues(),range.getBackgrounds()];
const c = catList.map((row,i) => [row[0],row[1],catClrs[0][i]]);
Logger.log(c);
}
If you want to filter on the true values:
function newsheet(){
const ss = SpreadsheetApp.getActive().getSheetByName("AddData");
const range = ss.getRange("I5:J31");
const [catList,catClrs] = [range.getValues(),range.getBackgrounds()];
const c = catList.map((row,i) => [row[0],row[1],catClrs[0][i]]).filter(r=>r[1]);
Logger.log(c);
}
Here is the code that worked correctly. In addition to what is mentioned in the question, the method of filtering is also included.
function newsheet(){
var app = SpreadsheetApp
var ss = app.getActiveSpreadsheet().getSheetByName("AddData");
//get category
var catList = ss.getRange("I5:J31").getValues();
var catClrs = ss.getRange("J5:J31").getBackgrounds().flat();
//merge arrays
var c = catList.map((row,i) => [row[0],row[1],catClrs[i]]);
//filter "checked" boxes values
var fillterC = c.filter(filterLogic);
}
//create filter logic function
var filterLogic =function(item){
if(item[1] === true){
return true;
}else{
return false;
}
}
Thanks to everyone who helped. I learned a lot.
I have got a simple loop that puts data from a list to the table:
standings.forEach(function(item, i) {
const rowData = document.createElement("tr");
const tdData = document.createElement("td");
const tdData2 = document.createElement("td");
const tdData3 = document.createElement("td");
const tdData4 = document.createElement("td");
const tdData5 = document.createElement("td");
tbody.appendChild(rowData);
tdData.textContent = item.position;
rowData.appendChild(tdData);
tdData2.textContent = `${item.name} ${item.surname}`;
rowData.appendChild(tdData2);
tdData3.textContent = item.data2;
rowData.appendChild(tdData3);
tdData4.textContent = item.point;
rowData.appendChild(tdData4);
tdData5.textContent = item.fruits;
rowData.appendChild(tdData5);
})
Anyone knows how I can automate this process? I don't think, that my way is super efficient, so I am looking for another answer.
I typically break repeating elements down into smaller pieces, and then repeat as needed to make it easier to read. For instance, you are creating a lot of 'td' elements with text inside it, so I would start with something like:
function newElementWithText( innerText )
{
const td = document.createElement("td");
td.textContent = innerText;
return td;
}
to handle that part. If you incorporate that solely into your code, you would have:
standings.forEach(function(item, i) {
const rowData = document.createElement("tr");
rowData.appendChild(
newElementWithText(item.position) );
rowData.appendChild(
newElementWithText(`${item.name} ${item.surname}`);
rowData.appendChild( newElementWithText(item.data2);
rowData.appendChild( newElementWithText(item.point);
rowData.appendChild(
newElementWithText(item.fruits) );
tbody.appendChild(rowData);
}
This can be made more readable using an array of the data that is needed, and then mapping it into the new td element, and then finally appending it.
standings.forEach(function(item, i) {
const rowData = document.createElement("tr");
const data = [
item.position,
`${item.name} ${item.surname}`,
item.data2,
item.point,
item.fruits
];
//Creates an array of the 'td' elements with text.
var tdElements = data.map( x => newElementWithText(x) );
//Iterates over the new array and appends to the rowData.
tdElements.map( x => rowData.appendChild(x) );
tbody.appendChild(rowData);
}
Full disclaimer, I have not fully tested this code for syntax errors, but it works in theory.
I have this simplified code:
const chancesData = ["facebook","twitter","google"];
let inputsArr = [];
const inputsArrFill = chancesData.map((cur, index) => {
const input = (document.createElement("input").value =
chancesData[index]);
inputsArr.push(input); //I want the pushed value to be something like this "<input value"facebook">"
return inputsArr;
//so the returned array (should) be something like this:
//["<input value"facebook">","<input value"twitter">","<input value"google">"]
});
console.dir(inputsArrFill);
as you can see if you opened this coed in your console, the returned array looks like this:
['facebook', 'twiiter', 'google']
I want it to look like this:
['<input value="facebook">','<input value="twitter">','<input value="google">']
You can use setAttribute to put the value into the HTML markup, then retrieve it with outerHTML:
const chancesData = ["facebook", "twitter", "google"];
const inputsArrFill = chancesData.map(str => {
const input = document.createElement("input");
input.setAttribute('value', str);
return input.outerHTML;
});
console.dir(inputsArrFill);
But it'd be easier to use ordinary string concatenation:
const chancesData = ["facebook", "twitter", "google"];
const inputsArrFill = chancesData.map(str => `<input value="${str}">`);
console.dir(inputsArrFill);
The result of an assignment expression, is the assigned value. With
const input = (document.createElement("input").value =
chancesData[index]);
you did not store a reference to the created HTML element into your variable, you stored the assigned value, chancesData[index].
You need to do these two things in separate steps.
const chancesData = ["facebook","twitter","google"];
let inputsArr = [];
const inputsArrFill = chancesData.map((cur, index) => {
const input = document.createElement("input");
input.value = chancesData[index];
inputsArr.push(input); //I want the pushed value to be something like this "<input value"facebook">"
return inputsArr;
//so the returned array (should) be something like this:
//["<input value"facebook">","<input value"twitter">","<input value"google">"]
});
console.dir(inputsArrFill);
But if you really want <input value="facebook"> as a result, then you will probably have to push that in string form to begin with. You have little control over how an HTML element object gets displayed by the console.
Please refer below code.
(function createHTMlString() {
const chancesData = ["facebook", "twitter", "google"];
var outputObj = []
for (var i = 0; i < chancesData.length; i++) {
var inputTag = document.createElement("INPUT");
inputTag.setAttribute("value", chancesData[i]);
outputObj.push(inputTag);
}
console.log(outputObj)
})();
I'm trying to get an item in array which contains a specific value.
Let's say I have an array
var arr = ["boat.gif", "goat.png", "moat.jpg"];
And I have a variable var imageName = "boat"
Since I do not know the file extension of imageName, I need a way to run it through my array and get "boat.gif" as the output.
I tried this with regular expressions
let filesString = arr.join(" ");
let regExName = new RegExp(imageName, "i");
let fileName = regExName.exec(filesĀString),
file = fileName.input.substĀr(fileName.index, 5);
It works but I'm hoping there's a better way
I hope this makes sense
Might be easier to filter by .includes or .startsWith instead:
var arr = ["boat.gif", "goat.png", "moat.jpg"];
var imageName = "boat";
const found = arr.find(str => str.includes(imageName));
console.log(found);
or
var arr = ["boat.gif", "goat.png", "moat.jpg"];
var imageName = "boat";
const found = arr.find(str => str.startsWith(imageName));
console.log(found);
If there might be other files in the directory which start with the same word (like boats.gif), then construct a regular expression like you're doing, but lookahead for a .:
var arr = ["boat.gif", "goat.png", "moat.jpg"];
var imageName = "boat";
const pattern = new RegExp(imageName + '(?=\.)');
const found = arr.find(str => pattern.test(str));
console.log(found);