Non case sensitive remove row with specific data - javascript

I have this Google Apps Script that is checking specific columns for listed words in it and removes rows that match those words:
function sort() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var values = rows.getValues();
var rowsDeleted = 0;
var arrayOfWords = ['möbelübernahme','können übernommen werden','caravan','wohnwagen']
for (var i = values.length - 1; i >= 0; i--) {
var row = values[i];
for (var j = 0; j < arrayOfWords.length; j++) {
if (row['21','17'].indexOf(arrayOfWords[j]) > -1) {
sheet.deleteRow(i+1);
rowsDeleted++;
break;
}
}
}
};
Can I make the words check to be not case sensitive? So if I include a word like "mietwohnung" it will remove all matching options: MIETWOHNUNG, mietwohnung, Mietwohnung?

Explanation:
You need to convert each element in the row array to lower case. In order to do that, you need to use map() and toLowerCase(). In this way you will apply toLowerCase to every element of row. The modification will be here:
if (row.map(r=>r.toLowerCase()).indexOf(arrayOfWords[j]) > -1)
row['21','17'] is not a valid javascript object. You can't slice an array like that. If your goal is to check only column 21 and 17 then use this if statement instead:
if ([row[21],row[17]].map(r=>r.toLowerCase()).indexOf(arrayOfWords[j]) > -1)
Note here that row[21] is column V and row[17] is column R in the sheet. Remember the index in javascript starts from 0. Namely, 0 is column A, 1 is column B etc.
Solution:
function sort() {
var sheet = SpreadsheetApp.getActiveSheet();
var rows = sheet.getDataRange();
var values = rows.getValues();
var rowsDeleted = 0;
var arrayOfWords = ['möbelübernahme','können übernommen werden','caravan','wohnwagen']
for (var i = values.length - 1; i >= 0; i--) {
var row = values[i];
for (var j = 0; j < arrayOfWords.length; j++) {
if (row.map(r=>r.toLowerCase()).indexOf(arrayOfWords[j]) > -1) {
sheet.deleteRow(i+1);
rowsDeleted++;
break;
}
}
}
};

An alternative to the solution already provided
You can simply use toLowerCase() - in this way "Mietwohnung" will become "mietwohnung" for example, and the comparison can be made with no issues.
So, you can do the following modification to your script:
for (let i = values.length - 1; i >= 0; i--) {
var row = values[i];
var found = false;
for (let k = 0; k < row.length; k++)
for (let j = 0; j < arrayOfWords.length; j++)
if (row[k].toString().toLowerCase().indexOf(arrayOfWords[j]) > -1)
found = true;
if (found == true) {
sheet.deleteRow(i + 1);
rowsDeleted++;
}
}
The above script loops through all the values from the data range, hence the other loop added, and then making use of the toLowerCase() function, checks if the value is part of the arrayOfWords array and if needed, deletes the row(s). The found variable is used here to indicate whether the word has been found or not.
Reference
JavaScript String.prototype.toLowerCase().

Related

Finding two elements within an array with IF statement using Apps Script

I am very new to programming and I am trying to locate two consecutive values within a 1-d array in google sheets and the answers need to be highlighted in bold in the google sheet. The first value should be greater than 5 (located for example in cell D10) and the next value should be less than 4.99 (and located in E10). I have tried two methods but can't seem to get the Code to work - I don't know if I am over-complicating the problem or not. The first method was to make the row into 2 separate arrays of elements so that if element J is greater than 5, and element k (which looks at the element next to J) is less than 4.99.
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var ui2 = SpreadsheetApp.getUi();
var data1 = ss.getRange(10,2,1,20).getValues()[0]; //Variable 1 - to find the ON value B10:U10
var data2 = ss.getRange(10,3,1,20).getValues()[0]; //to find the OFF value;
var onA = 5.00;
var on = data1 > onA;
var offA = 4.99;
var off = data2 < offA;
for(var i = 0; i < 20; i++){
for(var j = 0; j < 20; j++){
if(data1[i] < 5.00 && data2[j] < 4.99){
ss.getRange(10,2,1,20).setValue(data1[i]).setFontSize(12).setFontWeight("bold");
ss.getRange(10,3,1,20).setValue(data2[j]).setFontSize(12).setFontWeight("bold");
break;
}
else {
ui2.alert("the values are not found");
break;
}}}}
My other method was not search the cells as a single array - this works but once I add a message to a else statement to state the values are not found it would repeat this alert for the same number of times as the loop.
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var ui2 = SpreadsheetApp.getUi();
for(var j = 2; j < 22; j++){ // j is column number
for(var k = j+1; k < 23; k++){
var result = ss.getRange(10,j).getValue();
var result2 = ss.getRange(10,k).getValue();
var resulta = result > 5.00;
var resultb = result2 < 4.99;
if (resulta == true && resultb == true) {
ss.getRange(10,j).setValue(result).setFontSize(12).setFontWeight("bold");
ss.getRange(10,k).setValue(result2).setFontSize(12).setFontWeight("bold");
break;
} else {
break;
ui2.alert('Values not found');
}}}}
Any help would be amazing and very greatly appreciated!
Try this:
function findconsecutives() {
const ss=SpreadsheetApp.getActive();
const sh=ss.getSheetByName('Sheet1')
const rg=sh.getRange(10,2,1,20);
const vs=rg.getValues()[0];
for(let i=0;i<vs.length-1;i++) {
if(vs[i]<5 && vs[i+1]<4.99) {
sh.getRange(10,i+2,1,2).setFontSize(12).setFontWeight('bold');
break;
}
}
ss.toast('not found');
}
I just changed the fontsize and fontweight to the cells that meet the requirements if you want to change feel free. I don't want to.

Adapting merge cells in InDesign script

I found this script on SO, which is very close to what I need. But instead of it merging the cells with the one above I need it to merge with the cell to left of any empty cell.
I have tried to experiment with it and manged to get it to merge horizontally once but it merge three cells that weren't empty into one.
Would be greatful for any help
THanks
var myDoc = app.activeDocument;
myPage = myDoc.pages;
for (var p=0; myPage.length>p; p++){
try{
var myTable = myPage[p].textFrames.everyItem().tables.everyItem();
if (myTable.constructor.name == 'Table'){
for (var t = myTable.cells.length - 1; t >= 0; t--)
{
if (myTable.cells[t].contents==""){
var w = myTable.columns.length;
myTable.cells[t-w].merge(myTable.cells[t]);
}
}
}
}
catch(e){}
}
I found a solution
var i, j, cells;
// Get all the rows in the document
var rows = app.documents[0].stories.everyItem().tables.everyItem().rows.everyItem().getElements();
for (i = 0; i < rows.length; i++) {
// Get all the cells in a row
cells = rows[i].cells.everyItem().getElements();
for (j = cells.length-1; j >= 1; j--) {
if (cells[j].contents == '') {
cells[j-1].merge (cells[j]);
}
}
}

Get the first empty row in multidimensionnal array

I have a question about a function where I'm trying to get a first look at a multidimensional array.
To explain my problem: In a sheet, I manage my roadmap with projects. A project is composed by 4 rows where I have some information (Project Name, Estimated Team, Timeline ...).
And In my timeline, I need to retrieve the first empty rows in multiple arrays (the first non empty is the startDate).
The problem, I have 4 teams in this multidimensional array, and (for example), the start date can be in the 1st team array for the project A, but the start date can be also in the 3rd team array for the project B.
In my function, I'm trying to get to the start date, but my first step is to check the first array ... (projectRange and after in the code)
So ... I think the best way should be check every rows in the first column, and continue like this to the getLastColumn, right?
So, how can I manage my Loop with this way?
function findLastRow(column) {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getSheetByName(roadmapSS);
var startRow = 11;
var startCol = 11;
var dataLength = sheet.getLastRow()-(startRow+2);
var rangeData = sheet.getRange(startRow, 2, sheet.getLastRow(), sheet.getLastColumn());
var dataValues = rangeData.getValues();
var projectsList = rangeData.getValues();
var projectDatas = {};
var projectRange = null;
var projectName = null;
var projectPlan = {};
var realStart = null;
for (var i = 0; i < dataLength; i+=4) {
projectDatas = projectsList[i];
var step = startRow+i;
var realStartRange = startRow+i+1
for (var j = 0; j < 1; j+=4) {
projectName = projectDatas[j];
}
projectRange = ([step, startCol, 4, sheet.getLastColumn()]).toString();
var projectPlan = sheet.getRange(step, startCol, 4, sheet.getLastColumn()).getValues();
for (var k = 0; k < projectPlan.length; ++k) {
realStart = projectPlan[k];
for (var l = 0; l < realStart.length; ++l) {
if (realStart[l] != '') {
break;
}
}
}
//sheet.getRange(realStartRange, 2).setValue(columnToLetter([l]))
console.log(projectName, [l], columnToLetter([l]));
}
}
In fact, i'm trying to get the first column of B in this example (because it's the first non empty occurence :
var projectTimeline = [
['','','A','A','','A'],
['','B','B','','B',''],
['','','','C','C',''],
['','','','','D','D']
]
I found my solution :
I throughed the column first, and then the row. It worked, I founded the column :)
function findFirstDate (timeline) {
for (var col = 0; col < timeline[0].length; col++) {
for (var row = 0; row < 4; row++) {
if (timeline[row][col] != '') {
return [col];
}
}
}
}

Using Google Script to get an array from a list of cells in google sheet

How do I create an array of values that are in a set of cells in Google sheets?
The array should be the same rows and columns as the cells and it should have the same values as the sheet has in each location.
Also, I want to be able to pass the range of the array in as a parameter so that I can use the function for different ranges.
edit 2:
New code, nearly working, I just need to have it receive the ranges from user input on the google sheet itself. This is what I am trying to get work, but the beginning is struggling to work, I can't pass in a choice of ranges and have the cell update and have the function run.
Also, I am having a problem with getting a reference error almost every time even when I try to preset the ranges within the function without any parameters
function sortingtest(pWO, pInfo, pSearch) {
var WO = SpreadsheetApp.getActiveSpreadsheet().getRange(pWO).getValues();
var Info = SpreadsheetApp.getActiveSpreadsheet().getRange(pInfo).getValues();
var Search = SpreadsheetApp.getActiveSpreadsheet().getRange(pSearch).getValues();
//[row][column]
var FinalArray1 = [];
var FinalArray2 = [];
var FinalArray3 = [];
var LastArray = [];
var a = 0;
var b = 0;
var c = 0;
var d = 0;
for (var row = 0; row < WO.length; row ++) {
var counter = row - 1;
while (WO[row] == "") {
WO[row] = WO[counter];
counter--;
}
}
for (var col = 0; col < Info[0].length; col++) {
for (var row = 0; row < Info.length; row++) {
if (Info[row][col] == Search[col]) {
if (col == 0) {
FinalArray1[a] = WO[row];
a++;
}
else if (col == 1) {
FinalArray2[b] = WO[row];
b++;
}
else if (col == 2) {
FinalArray3[c] = WO[row];
c++;
}
}
}
}
for (var i = 0; i < FinalArray1.length; i++) {
for (var j = 0; j < FinalArray2.length; j++) {
for (var k = 0; k < FinalArray3.length; k++) {
if (FinalArray3[k] == FinalArray2[j] && FinalArray2[j] == FinalArray1[i]) {
LastArray[d] = FinalArray1[i];
d++;
}
}
}
}
return LastArray;
}
If you call your function from within the spreadsheet as you indicate it in your comment (=sortingtest(sheet1!A1:C12,sheet3!D1:E12,sheet2!F1:G4)), you do not need to call any of the SpreadsheetApp functions to get arrays: pWO, pInfo and pSearch will already be 2 dimensional arrays.
Quoting the Google custom function article:
If you call your function with a reference to a range of cells as an argument (like =DOUBLE(A1:B10)), the argument will be a two-dimensional array of the cells' values. For example, in the screenshot below, the arguments in =DOUBLE(A1:B2) are interpreted by Apps Script as double([[1,3],[2,4]]).

Searching a 2D Javascript Array For Value Index

I am trying to write a jQuery that will find the index of a specific value within a 7x7 2D array.
So if the value I am looking for is 0 then I need the function to search the 2D array and once it finds 0 it stores the index of the two indexes.
This is what I have so far, but it returns "0 0" (the initial values set to the variable.
Here is a jsFiddle and the function I have so far:
http://jsfiddle.net/31pj8ydz/1/
$(document).ready( function() {
var items = [[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,0,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7]];
var row = 0;
var line = 0;
for (i = 0; i < 7; ++i) {
for (j = 0; i < 7; ++i) {
if (items[i, j] == '0,') {
row = i;
line = j;
}
}
}
$('.text').text(row + ' ' + line);
});
HTML:
<p class="text"></p>
Your if statement is comparing
if (items[i, j] == '0,')
Accessing is wrong, you should use [i][j].
And your array has values:
[1,2,3,4,5,6,7]
....
Your value '0,' is a string, which will not match numeric values inside the array, meaning that your row and line won't change.
First, you are accessing your array wrong. To access a 2D array, you use the format items[i][j].
Second, your array doesn't contain the value '0'. It doesn't contain any strings. So the row and line variables are never changed.
You should change your if statement to look like this:
if(items[i][j] == 0) {
Notice it is searching for the number 0, not the string '0'.
You access your array with the wrong way. Please just try this one:
items[i][j]
When we have a multidimensional array we access the an element of the array, using array[firstDimensionIndex][secondDimensionIndex]...[nthDimensionIndex].
That being said, you should change the condition in your if statement:
if( items[i][j] === 0 )
Please notice that I have removed the , you had after 0. It isn't needed. Also I have removed the ''. We don't need them also.
There are following problems in the code
1) items[i,j] should be items[i][j].
2) You are comparing it with '0,' it should be 0 or '0', if you are not concerned about type.
3) In your inner for loop you should be incrementing j and testing j as exit condition.
Change your for loop like bellow and it will work
for (i = 0; i < 7; i++) {
for (j = 0; j < 7; j++) {
if (items[i][j] == '0') {
row = i;
line = j;
}
}
}
DEMO
Note:-
1) Better to use === at the place of ==, it checks for type also. As you see with 0=='0' gives true.
2) Better to say i < items.length and j<items[i].length instead of hard-coding it as 7.
var foo;
items.forEach(function(arr, i) {
arr.forEach(function(val, j) {
if (!val) { //0 coerces to false
foo = [i, j];
}
}
}
Here foo will be the last instance of 0 in the 2D array.
You are doing loop wrong
On place of
for (i = 0; i < 7; ++i) {
for (j = 0; i < 7; ++i) {
if (items[i, j] == '0,') {
row = i;
line = j;
}
}
}
use this
for (i = 0; i < 7; i++) {
for (j = 0; j < 7; j++) {
if (items[i][j] == 0) {
row = i;
line = j;
}
}
}
Here is the demo
looks like you are still learning how to program. But here is an algorithm I've made. Analyze it and compare to your code ;)
var itens = [[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,0,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7],
[1,2,3,4,5,6,7]];
var row = null;
var collumn = null;
for (var i = 0; i < itens.length; i++) {
for (var j = 0; j < itens[i].length; j++) {
if (itens[i][j] == 0) {
row = i;
collumn = j;
}
}
}
console.log(row, collumn);

Categories