35
votes

The employee sheet contains the name of the employee in cell C2. The name of the employee should also be on the data sheet in the range B3:B153.

How can I get the rownumber of the cell on the data sheet that matches the employee name?

I tried the following script but it doesn't seem to work.

  var Sheet = SpreadsheetApp.getActive();
  var Employeesheet = Sheet.getSheetByName('Employee')
  var DataSheet = Sheet.getSheetByName('Data');
  var Column = Sheet.getRange(3,2,151,1);
  var Values = column.getValues(); 
  var Row = 0;

  while ( Values[Row] && Values[Row][0] !=(EmployeeSheet.getRange(2,3,1,1).getValue()) ) {
    Row++;
  }

  if ( Values[Row][0] === (EmployeeSheet.getRange(2,3,1,1).getValue()) ) 
    return Row+1;
  else 
    return -1;

  }
4

4 Answers

60
votes

Here the code

function rowOfEmployee(){
  var sheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
  var data = sheet.getDataRange().getValues();
  var employeeName = sheet.getRange("C2").getValue();
  for(var i = 0; i<data.length;i++){
    if(data[i][1] == employeeName){ //[1] because column B
      Logger.log((i+1))
      return i+1;
    }
  }
}

When you want to perform this kind of lookup it is better to retrieve data with sheet.getDataRange().getValues() because in this case you will get data as a table of values this is faster. When you use the standard EmployeeSheet.getRange(2,3,1,1).getValue() in fact you retrieve an object which need more time to be processed and each time you query the spreadsheet.

In my exemple I made only one query to retrieve all data instead n query to retrieve one data each time.

Stéphane

13
votes

I faced this problem today and I found a native method to do the job.

Here is the snippet to test if it works for you:

  var spreadsheet = SpreadsheetApp.getActive();
  var tosearch = "your text to search";
  var tf = spreadsheet.createTextFinder(tosearch);
  var all = tf.findAll();
  
  for (var i = 0; i < all.length; i++) {
    Logger.log('The sheet %s, cell %s, has the value %s.', all[i].getSheet().getName(), all[i].getA1Notation(), all[i].getValue());
  }
3
votes

Since Google App Script is a JavaScript platform, I can think of two more methods to get the row index. It may be a bit faster because these are built-in Array methods.

Method 1: using Array.prototype.forEach()

function getRowIndexUsingforEach(){
  let term = '[email protected]';
  var data = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(1, 1, 2000).getValues();
  data.forEach((val, index) => {
     if(val == term){
         Browser.msgBox(index+1); //because Logger.log() takes too long
     }               
  })
}

Method 2: using Array.prototype.findIndex()

function getRowUsingfindIndex(){
  let term = '[email protected]';
  let data = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet().getRange(1, 1, 2000).getValues();
  let row = data.findIndex(users => {return users[0] == term});  
  Browser.msgBox(row+1); //because Logger.log() takes too long
}

To see which method will be faster, I ran these two methods and the accepted anwer's method over a column of 22000 rows of data several times. The averages are listed below:

  • Using for loop (from Accepted Answer): 2.66ms
  • Using Array.prototype.forEach: 11.75ms
  • Using Array.prototype.findIndex: 2.00ms

I guess Array.prototype.forEach is not meant to find the index of a match; it is Array.prototype.findIndex that is designed for this purpose

2
votes

I prefer loading all values into an array once when the sheet is opened, and then using Array.indexOf() to look up the index of the matched string. I think this solution will have less execution time than other solutions.

function updateValues(){
  dataRangeSearch = activeSheet.getRange(1,1,activeSheet.getLastRow());
  dataSearch = dataRangeSearch.getValues().reduce(function (a, b) {
    return a.concat(b);
  });;
}
updateValues();

function findValue(fieldName){
  var row = dataSearch.indexOf(fieldName);
  if (row == -1){ // Variable could not be found
    SpreadsheetApp.getUi().alert('I couldn\'t find field name "'+fieldName+'"');
    return "";
  } else {
    return activeSheet.getRange(row+1,2).getValue(); //Return the value of the field to the right of the matched string
  }
}