Copying or updating the row based on the occurrence of a row cell value - google-apps-script

I'm trying to add a given row or update an existing row to a Google Sheet based on a specific value in the row data. My row data is represented as an array object, like this: [id, number, date, type, url, count].
What I expect is that, if there exists a row with a matching number, I increment the count by 1 in the same range in the Google Sheet, else I add a new row with my row data.
Here's what I've tried so far, but it works only for count=2 and not beyond that.
function copyRowBasedOnNumber(sheetId, sheetName, rowData) {
var sheet = SpreadsheetApp.openById(sheetId);
var sheetname = sheet.getSheetByName(sheetName);
var count = 0;
var matchingRow = sheetname.getLastRow();
var values = sheetname.getDataRange().getValues();
for (var row in values) {
for (var col in values[row]) {
if (values[row][col] == rowData[1]) { // rowData[1] corresponds to the number
matchingRow = row;
count++;
break;
}
}
}
if(count == 0) {
var lastRowNum = sheetname.getLastRow();
sheet.insertRowAfter(lastRowNum);
rowData[5] = 1;
sheetname.getRange(lastRowNum + 1, 1, 1, rowData.length).setValues([rowData]);
} else {
sheetname.getRange(parseInt(matchingRow) + 1, 6).setValue(count + 1);
}
return count + 1;
}

I've figured it out. In case this helps someone in future, here's the code. Here, count is the value I want to check before I add a new entry or update an existing entry.
function copyRowToSheetWithoutDuplicate(sheetId, tabName, rowData) {
var sheet = SpreadsheetApp.openById(sheetId);
var sheetname = sheet.getSheetByName(tabName);
var count = 0;
var existingCount = 0;
var existingEntryRow = 0;
var allValues = sheetname.getDataRange().getValues();
var numColumns = sheetname.getLastColumn();
var numRows = sheetname.getLastRow();
for(var i=0;i<numRows;i++) {
var dateFromRowData = rowData[3].substring(0,10);
var todayDate = Utilities.formatDate(new Date(), "GMT+05:30", "''yyyy-MM-dd");
if(allValues[i][1]==rowData[1] && dateFromRowData!=todayDate) {
count++;
existingCount = allValues[i][6];
existingEntryRow = i + 1;
break;
}
}
if(count == 0) {
// insert a row and make an entry
sheetname.insertRowAfter(numRows);
rowData.push(1); // count
sheetname.getRange(numRows + 1, 1, 1, rowData.length).setValues([rowData]);
return 1;
} else {
// update the existing count by incrementing it by 1
existingCount++;
rowData.push(existingCount); // count
sheetname.getRange(existingEntryRow, 1, 1, rowData.length).setValues([rowData]);
return existingCount;
}
}

Related

Why is this function not deleting many rows at once correctly?

This function works with a little bit of data, but not with hundreds of rows and I wonder if I'm missing some Spreadsheet.flush() or something of this nature.
const values = [["2022-12-31T06:00:00.000Z"],["2022-12-31T06:00:00.000Z"],["2022-12-31T06:00:00.000Z"],["2022-12-31T06:00:00.000Z"],["2022-12-31T06:00:00.000Z"],["2022-12-31T06:00:00.000Z"],["2022-12-31T06:00:00.000Z"],["2022-12-31T06:00:00.000Z"],["2022-12-31T06:00:00.000Z"],["2022-12-31T06:00:00.000Z"],["2022-12-31T06:00:00.000Z"],["2022-12-31T06:00:00.000Z"]];
function DeleteRows(sheetName, year) {
sheetName = 'Saved Budgets'//For tests
year = '2022' //For tests
var SS = SpreadsheetApp.getActiveSpreadsheet().getSheetByName(sheetName); //Get Open Lines Sheet
var lastRow = SS.getLastRow();
var range = SS.getRange(2, 1, lastRow - 1, 1); //get range
range.sort({ column: 1, ascending: false }) // filter data descending
var firstRowToDelete = 0;
var numOfRows = 1; // starting row to be increment and become the number of rows
var values = range.getValues();//Got it for comparison
for (let a = 0; a < values.length; a++) {
let dt = new Date(values[a]).getFullYear();
if (dt == year) {
firstRowToDelete = parseInt(a);
numOfRows++
}
}
if (numOfRows != 1) {
numOfRows = numOfRows - 1 // minus 1 to get the last row
SS.deleteRows(firstRowToDelete, numOfRows);
}
range.sort({ column: 1, ascending: true }) // filter data again ascending
}
If you want to delete rows that the column "A" is year = '2022', firstRowToDelete = parseInt(a); is the last index of the rows that the column "A" is year = '2022'. And, numOfRows is the number of rows. In this case, I'm worried that all rows that the column "A" is year = '2022' cannot be deleted. And also, when the values are large, the rows for deleting might be over the bottom of the sheet, and/or range of range.sort({ column: 1, ascending: true }) might be over the bottom of the sheet. I thought that this might be the reason for your issue.
If you want to remove this issue, when your script is modified, how about the following modification?
From:
for (let a = 0; a < values.length; a++) {
let dt = new Date(values[a]).getFullYear();
if (dt == year) {
firstRowToDelete = parseInt(a);
numOfRows++
}
}
if (numOfRows != 1) {
numOfRows = numOfRows - 1 // minus 1 to get the last row
SS.deleteRows(firstRowToDelete, numOfRows);
}
range.sort({ column: 1, ascending: true }) // filter data again ascending
To:
for (let a = 0; a < values.length; a++) {
let dt = new Date(values[a]).getFullYear();
if (dt == year) {
if (firstRowToDelete == 0) firstRowToDelete = a + 2; // Modified
numOfRows++
}
}
if (numOfRows != 1) {
numOfRows = numOfRows - 1;
SS.deleteRows(firstRowToDelete, numOfRows);
}
SS.getRange(2, 1, SS.getLastRow() - 1, 1).sort({ column: 1, ascending: true }); // Modified
As another modification, how about the following modification?
From:
var values = range.getValues();//Got it for comparison
for (let a = 0; a < values.length; a++) {
let dt = new Date(values[a]).getFullYear();
if (dt == year) {
firstRowToDelete = parseInt(a);
numOfRows++
}
}
if (numOfRows != 1) {
numOfRows = numOfRows - 1 // minus 1 to get the last row
SS.deleteRows(firstRowToDelete, numOfRows);
}
range.sort({ column: 1, ascending: true }) // filter data again ascending
To:
var values = range.getDisplayValues();
var numOfRows = values.filter(([a]) => new Date(a).getFullYear() == year).length;
if (numOfRows > 0) {
var firstRowToDelete = values.findIndex(([a]) => new Date(a).getFullYear() == year);
SS.deleteRows(firstRowToDelete > -1 ? firstRowToDelete + 2 : firstRowToDelete, numOfRows);
}
SS.getRange(2, 1, SS.getLastRow() - 1, 1).sort({ column: 1, ascending: true });
Try this:
NOTE: This is all based on the assumption that the values global variable is actually a data in the spreadsheet, and you would want to remove all data with 2022.
function myFunction() {
var ss = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet(); //you can change this to specify a specific sheet
var range = ss.getRange(2,1,ss.getLastRow(), ss.getLastColumn());
var values = range.getValues();
var year = /2022/; // change this to filter other years
var newval = values.filter(x=>year.test(x) ? null : x);
console.log(newval); //to check if it populates the correct data during logging.
range.clearContent(); //clears the data based on the current range keeping the formatting.
var newrange = ss.getRange(2,1,newval.length, ss.getLastColumn()); //creates a new range based on the size of `newval`
newrange.setValues(newval);
}
Explanation:
var range = ss.getRange(2,1,ss.getLastRow(), ss.getLastColumn()); gets the current data on the spreadsheet, including the columns.
Using var values = range.getValues(); we get a 2D array structure of the data on the spreadsheet.
Using filter() and test() method on var newval = values.filter(x=>year.test(x) ? null : x); using a ternary operator to test whether an array element contains the year to filter out.
range.clearContent(); to delete the contents of the range.
var newrange = ss.getRange(2,1,newval.length, ss.getLastColumn()); creates a new range based on the new array.
newrange.setValues(newval); sets the new value on the spreadsheet
Screenshots:
NOTE: Multiple columns in the data are for testing to see dynamic deletion even if there is additional data on the columns.
Initial data:
After running the script:
Execution duration:
References:
https://developers.google.com/apps-script/reference/spreadsheet/range#clearContent()
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp/test

How to Include more sheets to write incremental number

I am using this function which works upon submitting the entry via Google Forms. Currently the below script is adding increment number to the Sheet1 Last empty row
I want to include two more sheets where same incremental number will be added to last empty row.
Column will be same where increment number is pasting that is Column A but Sheet1 data starts from Row2 and Sheet2 and Sheet3 Data starts from row6.
Your help will be much appreciated.
function uPDATEiT() {
var aiColumnName = 'A'; //Sheet1,Sheet2,Sheet3 same column
var requieredColName = 'C' //it is just for Sheet1
var ss = SpreadsheetApp.getActiveSpreadsheet()
var worksheet = ss.getSheetByName('Sheet1','Sheet2','Sheet3')
var aiColRange = worksheet.getRange(aiColumnName + '1:' + aiColumnName + '1000');
var aiCol = aiColRange.getValues();
var aiColIndex = aiColRange.getColumn();
var reqCol = worksheet.getRange(requieredColName + '1:' + requieredColName + '1000').getValues();
var maxSeq = 0;
for (var i = 0; i <= aiCol.length; i++) {
if (parseInt(aiCol[i], 10) > maxSeq) { maxSeq = aiCol[i]; }
}
for (var i = 0; i <= aiCol.length; i++) {
if (('' + reqCol[i]).length > 0 && ('' + aiCol[i]).length === 0) {
maxSeq++;
worksheet.getRange(i + 1, aiColIndex).setValue(maxSeq);
}
}
}
You can use this formula in Sheet2!A4 and Sheet3!A4:
={"ID's";ARRAYFORMULA(IF(B5:B<>"",vlookup(B5:B,{'Data Sheet (Sheet1)'!$B$2:$B,'Data Sheet (Sheet1)'!$A$2:$A},2,false),""))}
What it does?
Check if column B is not empty, then get the id from Sheet1 based on the matched name(column B) as a key in the vlookup()
Output:
Original Sheet2:
Sheet 2 using the formula:
Update
If you just want to append your maxSeq in Sheet2, you can use this:
Code:
function uPDATEiT() {
var aiColumnName = 'A'; //Sheet1,Sheet2,Sheet3 same column
var requieredColName = 'C' //it is just for Sheet1
var ss = SpreadsheetApp.getActiveSpreadsheet()
var worksheet = ss.getSheetByName('Data Sheet (Sheet1)')
var sheet2 = ss.getSheetByName('Sheet2')
Logger.log(worksheet)
Logger.log(sheet2.getLastRow())
var aiColRange = worksheet.getRange(aiColumnName + '1:' + aiColumnName + '1000');
var aiCol = aiColRange.getValues();
var aiColIndex = aiColRange.getColumn();
var reqCol = worksheet.getRange(requieredColName + '1:' + requieredColName + '1000').getValues();
var maxSeq = 0;
for (var i = 0; i <= aiCol.length; i++) {
if (parseInt(aiCol[i], 10) > maxSeq) { maxSeq = aiCol[i]; }
}
for (var i = 0; i <= aiCol.length; i++) {
if (('' + reqCol[i]).length > 0 && ('' + aiCol[i]).length === 0) {
maxSeq++;
worksheet.getRange(i + 1, aiColIndex).setValue(maxSeq);
sheet2.getRange(sheet2.getLastRow()+1,aiColIndex).setValue(maxSeq);
}
}
}
Get the last row in the sheet that contains data using getLastRow() , then increment it by 1.
Output:

Set values in a column on a sheet from a 1d array

I have a script that gathers Full Names contained within an email group
The idea is to have an up to date list of members of a team to use within a drop down.
It is working correctly but I can't seem to get it to setValues() Everything I have tried, either only lists one name from the list, all values in one cell or doesn't work. I think it's to do with the fact it's a 1 dimensional array but I could be wrong.
Here's what I have so far:
function listGroupMembers() {
var GROUP_EMAIL = "email#email.com";
var group = GroupsApp.getGroupByEmail(GROUP_EMAIL);
var users = group.getUsers();
var str = "Group " + GROUP_EMAIL + " has " + users.length + " members: ";
var valueRange=[];
valueRange[0]=[];
for (var i = 0; i < users.length; i++) {
var user = users[i];
var email = user.getEmail();
var contact = ContactsApp.getContact(email);
if(contact!=null){
valueRange[i]=[];
valueRange[i].push (contact.getFullName());
}
}
var sheet = SpreadsheetApp.getActive().getSheetByName("sheet name");
var numberRows = valueRange.length;
var range = sheet.getRange(1, 1, numberRows, 1);
range.setValues(valueRange);
}
I am struggling with out to get these values, into Column1, Row1, on my sheet like follows in seperate cells:
Name 1
Name 2
Name 3
Name 4
The array is as follows: [Name 1, Name 2, Name 3, Name 5, etc]
Please help, hope this all makes sense!
To output your values into a value range and assign this value range to a row:
Based on the code you provided, perform the following modification:
function listGroupMembers() {
var GROUP_EMAIL = "emailgroup#email.com";
var group = GroupsApp.getGroupByEmail(GROUP_EMAIL);
var users = group.getUsers();
var str = "Group " + GROUP_EMAIL + " has " + users.length + " members: ";
var valueRange=[];
valueRange[0]=[];
for (var i = 0; i < users.length; i++) {
var user = users[i];
var email = user.getEmail();
var contact = ContactsApp.getContact(email);
valueRange[i]=[];
if(contact!=null){
valueRange[i].push (contact.getFullName());
}else{
valueRange[i].push ("");
}
}
var sheet = SpreadsheetApp.getActive().getSheetByName("INSERT HERE THE NAME OF YOUR SHEET");
var numberColumns = valueRange[0].length;
var range = sheet.getRange(1, 1, 1, numberColumns);
range.setValues(valueRange);
}
Explanation:
setValues() expect a 2-D value range, that is a nested array with the dimensions [numberRows][numberColumns]. For a row, it is a 2-D array with the height of 1 and the width corresponding to the number of your values. For a column, it would be exactly the opposite.
push() is a Javascript method useful for populating the array elements of the value range with your values
To insert values vertically (in one column) instead of horizontally - loop through rows instead of columns. Sample:
for (var i = 0; i < users.length; i++) {
var user = users[i];
var email = user.getEmail();
var contact = ContactsApp.getContact(email);
valueRange[i]=[];
if(contact!=null){
valueRange[i].push (contact.getFullName());
}else{
valueRange[i].push ("");
}
}
var sheet = SpreadsheetApp.getActive().getSheetByName("INSERT HERE THE NAME OF YOUR SHEET");
var numberRows = valueRange.length;
var range = sheet.getRange(1, 1, numberRows, 1);
range.setValues(valueRange);

How should I properly use the set range and get range functions in Google Apps Script?

I need to update the value of "product quantity" based on the value of "order quantity" but only when "order sku" is equal to "product sku".
function productLoop2() {
var app = SpreadsheetApp;
var ss = app.getActiveSpreadsheet();
var activeSheet = ss.getActiveSheet();
var t = 2;
var n = 2;
var s = 0;
for(var t = 2; t < 52; t++) {
var x = activeSheet.getRange(t, 1).getValue();
//x is the ORDER SKU
var r = activeSheet.getRange(t, 2).getValue();
//r is the ORDER QUANTITY
var q = activeSheet.getRange(n, 3).getValue();
//q is the PRODUCT SKU
var u = activeSheet.getRange(n, 4).getValue();
//u is the PRODUCT QUANTITY
if (x != q) {
n++;
} else {
s = u - r;
}
var m = activeSheet.getRange(n,4).setValue(s);
}
}
I need the cell "n,4" (order quantity) to update so the value equals the result of "u"(product quantity) minus "r"(order quantity)
The code "if" fragment should be corrected as below:
if (x != q) {
n++;
} else {
activeSheet.getRange(n,4).setValue(u - r);
}
Update after discussion:
function updateProductQuantities() {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var values = activeSheet.getDataRange().getValues();
// Sum quantities by orders (columns A and B)
var sku = {};
for (var i in values) {
if (i == 0) continue; // headers row
if (sku[values[i][0]] == undefined) {
sku[values[i][0]] = values[i][1];
} else {
sku[values[i][0]] += values[i][1];
}
}
// Update product quantities (columns C and D)
for (i in values) {
if (sku[values[i][2]] != undefined) {
values[i][3] -= sku[values[i][2]];
}
}
// return values to the sheet
activeSheet.getDataRange().setValues(values);
}
You should use 2 "for" loops. One is for sum of orders quantities, and the other is for subtraction.
Here is how you can get all the data, modify it and set it in the sheet.
function productLoop2() {
var sheet = SpreadsheetApp.getActive().getActiveSheet();
// Get the active sheet of the active spreadsheet
var orderRange = sheet.getRange('A2:B52');
var productRange = sheet.getRange('C2:D52');
// Get the data ranges (change these references as necessary)
var orderData = orderRange.getValues();
var productData = productRange.getValues();
// Get the values from the ranges. This method returns an array.
for (var row = 0; row < orderData.length; row++) {
// Loops through every row of the order array
// Arrays are zero-based; this means the first element is element 0,
// the second element in element 1 and so on.
// Data is accessed with [row index][column index];
var oSku = orderData[row][0];
var oQty = orderData[row][1];
for (var productIndex = 0; productIndex < productData.length; productIndex++) {
// Loops through every product in the product array
var pSku = productData[productIndex][0];
var pQty = productData[productIndex][1];
if (oSku === pSku) {
productData[productIndex][1] = pQty - oQty;
// Changes the pQty value in the array
break;
// Added upon suggestion from user tehhowch
}
}
}
productRange.setValues(productData);
// Sets all product values in the array to the range from which they were taken
}
References:
Multidimensional arrays
Best practices - batch operations
For loops

Find LastRow of column C (when Col A and B have a different row size)?

How to find the last used cell of column C ?
Example: "Sheet1" : "Col A" and "Col B" have 1200 rows. And "Col C" has only 1 row.
## ColA ColB ColC
## 1 1 1
## 2 2 empty
## .. .. ..
## 1200 1200 empty
Here are my unsuccessful tests :
Function find_last_row_other_column() {
var ws_sheet =
var ws = SpreadsheetApp.openById("Dy...spreadsheet_id...4I")
var ws_sheet = ws1.getSheetByName("Sheet1");
var lastRow = ws_sheet.getRange("C").getLastRow();
var lastRow = ws_sheet.getRange("C:C").getLastRow();
var lastRow = ws_sheet.getRange(1,3,ws_sheet.getLastRow()); 1200 rows for colA! instead of row = 1 for col C.
}
Note: I can't use C1 because next time I use the function it will be C1200 or something else.
var lastRow = ws_sheet.getRange("C1").getLastRow();
I ask this because my next goal is to copy/paste the result of C1 into C2:C1200. Here is my test :
var lastRow = ws_sheet.getLastRow();
var target_range = ws_sheet.getRange(1,3,lastRow,1); //C1 until last row
var Formula_values = source_range.getValues();
target_range.setValues(Formula_values);
Thanks in advance ;)
ps: I have spend 2 hours on it. I have tried similar problems & their solutions already given on this website, but I can't happen to make them working. I am lost ! :
More efficient way too look up the last row in a specific column?
and Get last row of specific column function - best solution
As I mentioned in the comments above, this is the subject of the highest score post on StackOverFlow...
The original post returns the value of the last cell in a column but a (very) little modification makes it return the row index.
Original post :
Script:
function lastValue(column) {
var lastRow = SpreadsheetApp.getActiveSheet().getMaxRows();
var values = SpreadsheetApp.getActiveSheet().getRange(column + "1:" + column + lastRow).getValues();
for (; values[lastRow - 1] == "" && lastRow > 0; lastRow--) {}
return values[lastRow - 1];
}
modified to return index of the last used cell in a column :
function lastValue(column) {
var lastRow = SpreadsheetApp.getActiveSheet().getMaxRows();
var values = SpreadsheetApp.getActiveSheet().getRange(column + "1:" + column + lastRow).getValues();
for (; values[lastRow - 1] == "" && lastRow > 0; lastRow--) {}
return lastRow;
}
Here is the function to do it:
function lastRowInColumnLetter(column) {
var lastRow = SpreadsheetApp.getActiveSheet().getLastRow() - 1; // values[] array index
var values = SpreadsheetApp.getActiveSheet().getRange(column + "1:" + column + (lastRow + 1)).getValues();
while (lastRow > -1 && values[lastRow] == "") {
lastRow--;
}
if (lastRow == -1) {
return "Empty Column";
} else {
return lastRow + 1;
}
}
and you invoke it as =lastRowInColumnLetter("C").
And here are 3 more useful functions in this context:
function lastValueInColumnLetter(column) {
var lastRow = SpreadsheetApp.getActiveSheet().getLastRow() - 1; // values[] array index
var values = SpreadsheetApp.getActiveSheet().getRange(column + "1:" + column + (lastRow + 1)).getValues();
while (lastRow > -1 && values[lastRow] == "") {
lastRow--;
}
if (lastRow == -1) {
return "Empty Column";
} else {
return values[lastRow];
}
}
function lastValueInColumnNumber(column) {
var lastRow = SpreadsheetApp.getActiveSheet().getLastRow() - 1; // values[] array index
var values = SpreadsheetApp.getActiveSheet().getRange(1,column,lastRow + 1).getValues();
while (lastRow > -1 && values[lastRow] == "") {
lastRow--;
}
if (lastRow == -1) {
return "Empty Column";
} else {
return values[lastRow];
}
}
function lastRowInColumnNumber(column) {
var lastRow = SpreadsheetApp.getActiveSheet().getLastRow() - 1; // values[] array index
var values = SpreadsheetApp.getActiveSheet().getRange(1,column,lastRow + 1).getValues();
while (lastRow > -1 && values[lastRow] == "") {
lastRow--;
}
if (lastRow == -1) {
return "Empty Column";
} else {
return lastRow + 1;
}
}
These functions properly address empty columns, and also start counting backwards from the last row with content on the active sheet getLastRow(), and not from the last row on the sheet (with or without content) getMaxRows() as in the accepted answer.
If you don't have empty cells between your data, you can use this:
function last_Column_Row(){
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var Direction = SpreadsheetApp.Direction;
var xcol = 2;//e.g. for column 2 ("B"), to obtain its last row
var yrow = 8;//e.g. for row 8, to obtain its last column
var lastRow =sheet.getRange(1,xcol).getNextDataCell(Direction.DOWN).getRow();//last row of column 'xcol'
var lastCol =sheet.getRange(yrow,1).getNextDataCell(Direction.NEXT).getColumn();//last column of row 'yrow'
};
It gets the number of next empty cell-1 of a specific row or column (similar to Ctrl + 'arrow' in a sheet)
But If you have empty cells between your data, you can use this:
function last_Row_Column2()
{
var ss = SpreadsheetApp.getActive();
var sheet = ss.getActiveSheet();
var Direction = SpreadsheetApp.Direction;
var maxR =sheet.getMaxRows();
var maxC = sheet.getMaxColumns();
var yrow = 8;//e.g. for row 8, to obtain its last column
var xcol = 2;//e.g. for column 2 ('B'), to obtain its last row
var valMaxR = sheet.getRange(maxR,xcol).getValue();//for the case that the last row has the last value
var valMaxC = sheet.getRange(yrow,maxC).getValue();//for the case that the last column has the last value
if(valMaxR !=''){var lastRow = maxR;}//if the last row in studied column is the last row of sheet
else{var lastRow =sheet.getRange(maxR,xcol).getNextDataCell(Direction.UP).getRow();}
if(valMaxC !=''){var lastCol = maxC;}//if the last column in studied row is the last column of sheet(e.g.'Z')
else{var lastCol =sheet.getRange(yrow,maxC).getNextDataCell(Direction.PREVIOUS).getColumn();}
};
[UPADTE} Please disregard this answer. User Serge's code instead. I was having a brain fart. His answer is magnitudes better in every way. That will teach me not to answer SO questions after you come back from a cocktail night... [/UPDATE]
The following function will log the last non-blank row number of column C. Note: if, for example, column C has a value in row 1 and row 200, with rows 2-199 blank, the function will return 200 as last non-blank row - it does not account for blank rows above last non-blank row.
function getLastNonBlankColCrow() {
var sheet = SpreadsheetApp.getActiveSheet();
var lastNonBlankColCrow = 0;
for (var i=1, lenRows=sheet.getRange("C:C").getNumRows(); i<=lenRows; i++) {
if ( !sheet.getRange(i, 3).isBlank() ) { // 3 is 1-based index of column C
lastNonBlankColCrow = i;
}
}
Logger.log(lastNonBlankColCrow);
}