Finding an empty cell in a column using google sheet script - javascript

I am trying to find an empty cell in a specific column in google sheets. I am familiar with getLastRow(), but it returns the last row in whole sheet. I want to get the first empty cell in a specific column. So, I used a for loop and if. But I don't know why it is not working. The problem is that for loop does not return anything.
I am getting 10 rows of the column H (position 8) in the sheet test (line2). first 5 rows already have content. Data will be added to this cell later using another code. so, I want to be able to find the first empty cell in this column to be able to put the new data.
var sheettest = SpreadsheetApp.getActive().getSheetByName("test");
var columntest = sheettest.getRange(4, 8, 10).getValues();
for(var i=0; columntest[i]=="" ; i++){
if (columntest[i] ==""){
var notationofemptycell = sheettest.getRange(i,8).getA1Notation();
return notationofemptycell
}
}
As I said, I want to find the first empty cell in that column. I defined the for loop to go on as long as the cell is not empty. then if the cell is empty, it should return the A1 notation of that cell.
It seems the for loop does go on until it find the empty cell, because I get no definition for the var "notationofemptycell" in debugging.

This may be faster:
function getFirstEmptyCellIn_A_Column() {
var rng,sh,values,x;
/* Ive tested the code for speed using many different ways to do this and using array.some
is the fastest way - when array.some finds the first true statement it stops iterating -
*/
sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('test');
rng = sh.getRange('A:A');//This is the fastest - Its faster than getting the last row and
//getting a specific range that goes only to the last row
values = rng.getValues(); // get all the data in the column - This is a 2D array
x = 0;
values.some(function(ca,i){
//Logger.log(i)
//Logger.log(ca[0])
x = i;//Set the value every time - its faster than first testing for a reason to set the value
return ca[0] == "";//The first time that this is true it stops looping
});
Logger.log('x: ' + x)//x is the index of the value in the array - which is one less than
//the row number
return x + 1;
}

You need to loop through the length of columntest. Try this:
function myFunction() {
var sheettest = SpreadsheetApp.getActive().getSheetByName("test");
var lr=sheettest.getLastRow()
var columntest = sheettest.getRange(4, 8, lr).getValues();
for(var i=0; i<columntest.length ; i++){
if (columntest[i] ==""){
var notationofemptycell = sheettest.getActiveCell().getA1Notation();
Logger.log( notationofemptycell)
break;//stop when first blank cell on column H os found.
}
}
}

Related

For Loop deleteRow(i) deleting the wrong rows

I'm using Google Apps Script to write a script to edit Google Sheets for a Mailing List. I'd like it to run through all rows and delete any rows with 'BOUNCED' 'ERROR' or 'NO_RECIPIENT' in a specific cell.
The problem I'm having is the For Loop uses brackets [ ] to designate the rows and columns, which indexes the first row at 0. The deleteRows() action uses curved parenthesis, which indexes the first row at 1. For this reason, I'm having trouble deleting the correct row.
If I program deleteRow(i), it deletes the row following the one being tested by the For loop. If I program deleteRow(i+1), it deletes the correct row the first time, but subsequently deletes the following row. See my code below:
function cleanUp() {
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheet = ss.getActiveSheet();
var data = sheet.getDataRange().getValues();
for ( var i = 1; i < 30; i++) {
if (data[i][9] === 'ERROR' || data[i][9] === 'BOUNCED' || data[i][9] === 'NO_RECIPIENT') {
sheet.deleteRow(i+1);
}
}
}
Once a row is deleted the rows below it change it's position. One way to avoid this problem is to do the loop in reverse order.
In other words, instead of
for(var i = 1; i < 30; i++)
Use
for(var i = 29 ; i > 0; i--)

Apps Script JS adding items to array from range (if not already in array) fails

I am looping through various cells and want to add their string content do an array, if the content is not already in the array. It works perfectly fine when I do it manually like so, trying to add 'eJobs' to the array (see below "var item = 'eJobs') which already containts 'eJobs':
var divisionarray = ['eJobs']
for (var i = 0; i < cells_users.length-1; ++i) {
var row_users = cells_users[i];
if (row_users[0] == user_ldap) {
var podarray = row_users[1].split(', ')
for (j = 0; j < podarray.length; j++) {
for (var k = 0; k < cells_edit.length; ++k) {
var row_edit = cells_edit[k]
if (podarray[j] === row_edit[0]) {
var item = 'eJobs'
if (!(divisionarray.indexOf(item) >= 0)) {
divisionarray.push(item)
}
}
}
}
Logger.log(divisionarray)
As expected, the log file shows [17-10-08 19:11:04:111 BST] [eJobs], illustrating that the code works and 'eJobs' has not been added to the array as it is already in the array.
Now, when I change var item='eJobs' to values of a range
var item = sheet_pods_edit.getRange(startRow+k, startColumn+1).getValue();
the code does not work anylonger, as the log file shows:
[17-10-08 19:14:03:770 BST] [eJobs, eJobs, BestJobs, Vivre Deco, ...
Note I have a range of thousands of cells, so I get alot of duplicates added. What am I missing? Note the cells of the defined range are indeed just strings with a single word (e.g. 'eJobs').
The code is working and the log file is indicating what the problem is..
[eJobs, eJobs, BestJobs, Vivre Deco,
In the second eJobs there is a white space before eJobs, so the first value and the second value don't match.
Without seeing your data and going by the 'just strings with a single word' I would say that using a .replace(" ", "") on the text string should work, this will find the first " " in the string and remove it. I.e. " eJobs" would become "eJobs".
2.
Is this line of code just for testing? You should never use a method like this in a script. It will be extremely inefficient
var item = sheet_pods_edit.getRange(startRow+k, startColumn+1).getValue();
Instead get the full range using .getValues()and iterate over it then.
3.
Is there a reason you are using === in if (podarray[j] === row_edit[0]) unless you need to check for type always use ==

compare array values javascript replace values matched

I have two sheets, one is updated from time to time, one is the backup which it may contain some the same values of the first one, the first one needs to be updated in some columns with recorded data already saved in the backup, I have written this script which is working fine some times but other times completely wrong (!) is taking right value form wrong row! second sheet is sorted descendant way so that inedxOf will match the right value for sure as first one.
var M = data.length;
for ( var r = 0; r < M ;r++){
var L = datiArchivio.length;
var row = data[r];
var nave = row[4];
var imo1 = data [r][23]
if ( imo1 == "" && nave!= ""){
for (var j = 0; j < L;j++){
var roww = datiArchivio[j];
var IMO = roww[23];
var naveArchivio = roww[4];
var GT = roww[25];
if ( IMO == ""){continue;} else {
if ( naveArchivio == nave) {
row.splice(23,1,IMO);
row.splice(25,1,GT);
}
}
}
}
}
I guess you meant something like this, but it is not working, in the archivio sheet there could be matching row with empty value at the reference column as well as fulfil values, it is ordered so that it should match first one which fullfil the condition, hence I added roww[23]=="" condition in order to skip that j row. it is challenging, keep on work on the logic.
This last version is working, and also quickly, I was stucked in the old "rubbish in rubbish out".

Using row ID to delete rows in a loop 'Cannot read property 'remove' of null'

I have a script that adds and subtracts rows from a table. As I add new rows, I assign the row ID a number. And when I subtract rows, I decrease that number. When I decide to select a row to delete, I delete the row by using the ID number.
I am stuck on one function 'clearfields' that is supposed to clear all rows up to row 11 when a button is pushed. In my loop I am going from a start point of 12 to the end of the table length.
My issue is if I delete a row sort of in the middle lets say row 18 out of 22, I get a remove null error when the button is pushed and I run this function. Any way around this? Can I just delete all rows no matter what the ID is up until a row ID of 11 is reached?Any help is most appreciated. Thanks
Javascript
function clearFields(){
buttonLim=0;
var tableClr = document.getElementById('table2').rows.length;
var subJob=tableClr;
var subJob2=tableClr-10;
var numb=11;
var getter= $("#num1").val();
i=11;
for (var i = 0; i <= tableClr-1; i++) {// this is where I empty the cells
var adde=i+4;
$("#num"+adde+"Sun").val("");
$("#num"+adde+"Mon").val("");
$("#num"+adde+"Tue").val("");
$("#num"+adde+"Wed").val("");
$("#num"+adde+"Thu").val("");
$("#num"+adde+"Fri").val("");
$("#num"+adde+"Sat").val("");
added=0;
}
if(tableClr>11){ //comment here... this is where I delete the rows
for (var j = 12; j <= tableClr; j++) {
document.getElementById("row" + j).remove();
}
}
else
{
}
}
Check the for loop variables and their constraints i am no expert but i get a feeling that your problem might be solved when you correct the for loop with different variables and conditions(just give var to j not like a number(12) and update the var) see what i am saying just relax and try after a bit you'll figure it out for yourself, it happens with me at all the times.

Is it possible to use a variable in the copyTo command in Google Apps Script for Sheets?

I have a spreadsheet that generates a test plan based on info from a Google Form. What I want to do is make a script that checks the B column, and if there's content in B[row number], copy cell I3 into I[row number].
Here's what I am working with:
var testplan = SpreadsheetApp.getActiveSpreadsheet().getSheetByName("TestPlan");
for (var j = 0; j < 200; j++) {
var destination = testplan.getRange(3, 9);
var contentCheck = testplan.getRange("B2:B200").getValues();
if (contentCheck != '' && contentCheck != 0) {
destination.copyTo(testplan.getRange(j, 9));
};
Now, if I set the copyTo from anything that's not j, like 4, it copies to I4 just fine. Otherwise, I get the error "The coordinates or dimensions of the range are invalid."
Is there a way to use a variable here I'm not seeing? Or do I have something else gone wrong?
Several problems:
You're planning to copy I3 to I[row], but you have contentCheck starting at B2, which overlaps. That overlap is what is causing the error, "The coordinates or dimensions of the range are invalid."
You've called your source cell, I3, "destination", and that's confusing. Let's call it source. Also, you know the cell coordinates, so why not use them?
You've declared that value inside a loop... but it never changes so instead do that before the loop, just once.
Similarly, contentCheck could be loaded once, before the loop. It yields a 2-D array (an array of rows, each with a single column, in this case). You need to address it as an array, using row and column indexes, otherwise the entire array is first flattened to create a string value to compare to '', then parsed for an integer to compare to '0' here:
if (contentCheck != '' && contentCheck != 0) {
Nice thing here, once we index in to a single value, ala contentCheck[j][0]... that comparison can be simplified to a test for truthiness:
if (contentCheck[j][0]) {
The array will be 0-based, while spreadsheet row and column indexes are 1-based. You need to adjust for that, especially since your range begins at B2, skipping a row. (To avoid the overlap mentioned earlier, let's say it should start at B4 - you'll need to sort out your actual values.)
You should end up with something like this:
var testplan = SpreadsheetApp.getActiveSpreadsheet()
.getSheetByName("TestPlan");
var source = testplan.getRange("I3");
var contentCheck = testplan.getRange("B4:B200").getValues();
for (var j = 0; j < contentCheck.length; j++) {
if (contentCheck[j][0])) {
// 0-based j plus 1 to be 1-based, plus starting row
source.copyTo(testplan.getRange(j+1+4, 9));
};
}

Categories