Determining the last row in a single column

前端 未结 19 1256
野性不改
野性不改 2020-11-22 10:46

I have a sheet with data in cols A through H.

I need to determine the last row in column A that contains data (it\'s all conti

相关标签:
19条回答
  • 2020-11-22 11:00

    This will get the last row in a sheet assuming based on column A.

    function getLastDataRow(sheet) {
      var lastRow = sheet.getLastRow();
      var range = sheet.getRange("A" + lastRow);
      if (range.getValue() !== "") {
        return lastRow;
      } else {
        return range.getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
      }              
    }
    

    This fixes @mrityunjay-pandey partially-correct answer.

    To extend this answer to get the last row and column, we can use:

    function columnToLetter(column) {
      var temp, letter = '';
      while (column > 0) {
        temp = (column - 1) % 26;
        letter = String.fromCharCode(temp + 65) + letter;
        column = (column - temp - 1) / 26;
      }
      return letter;
    }
    
    function letterToColumn(letter) {
      var column = 0, length = letter.length;
      for (var i = 0; i < length; i++) {
        column += (letter.charCodeAt(i) - 64) * Math.pow(26, length - i - 1);
      }
      return column;
    }
    
    function getLastDataColumn(sheet) {
      var lastCol = sheet.getLastColumn();
      var range = sheet.getRange(columnToLetter(lastCol) + "1");
      if (range.getValue() !== "") {
        return lastCol;
      } else {
        return range.getNextDataCell(SpreadsheetApp.Direction.PREVIOUS).getColumn();
      }              
    }
    
    function getLastDataRow(sheet) {
      var lastRow = sheet.getLastRow();
      var range = sheet.getRange("A" + lastRow);
      if (range.getValue() !== "") {
        return lastRow;
      } else {
        return range.getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
      }              
    }
    
    function run() {
      var sheet = SpreadsheetApp.getActiveSheet();
      var [startRow, lastRow] = [2, getLastDataRow(sheet)];
      var [startCol, lastCol] = [1, getLastDataColumn(sheet)];
    }
    
    0 讨论(0)
  • 2020-11-22 11:00

    You can do this by going in the reverse way. Starting from the last row in spreadsheet and going up till you get some value. This will work in all the cases even if you have some empty rows in between. Code looks like below:

    var iLastRowWithData = lastValue('A');
    function lastValue(column) {
      var iLastRow = SpreadsheetApp.getActiveSheet().getMaxRows();
      var aValues = SpreadsheetApp.getActiveSheet().getRange(column + "2:" + column + lastRow).getValues();
    
      for (; aValues[iLastRow - 1] == "" && iLastRow > 0; iLastRow--) {}
      return iLastRow;
    }
    
    0 讨论(0)
  • 2020-11-22 11:02

    How about using a JavaScript trick?

    var Avals = ss.getRange("A1:A").getValues();
    var Alast = Avals.filter(String).length;
    

    I borrowed this idea from this answer. The Array.filter() method is operating on the Avals array, which contains all the cells in column A. By filtering on a native function's constructor, we get back only non-null elements.

    This works for a single column only; if the range contains multiple columns,then the outcome of filter() will include cells from all columns, and thus be outside the populated dimensions of the range.

    0 讨论(0)
  • 2020-11-22 11:02

    Never too late to post an alternative answer I hope. Here's a snippet of my Find last Cell. I'm primarily interested in speed. On a DB I'm using with around 150,000 rows this function took (average) 0.087 seconds to find solution compared to @Mogsdad elegant JS solution above which takes (average) 0.53 sec on same data. Both arrays were pre-loaded before the function call. It makes use of recursion to do a binary search. For 100,000+ rows you should find it takes no more than 15 to 20 hops to return it's result.

    I've left the Log calls in so you can test it in the console first and see its workings.

    /* @OnlyCurrentDoc */
    
    function myLastRow() {
    
    var ss=SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
    var colArray = ss.getRange('A1:A').getDisplayValues();  // Change to relevant column label and put in Cache
    var TestRow=ss.getLastRow();
    var MaxRow=ss.getMaxRows(); 
    
    Logger.log ('TestRow = %s',TestRow);
    Logger.log ('MaxRow = %s',MaxRow);
    
    var FoundRow=FindLastRow(TestRow,MaxRow);
    
    Logger.log ('FoundRow = %s',FoundRow);    
    
    function FindLastRow(v_TestRow,v_MaxRow) {
    
    /* Some housekeeping/error trapping first
    * 1) Check that LastRow doesn't = Max Rows. If so then suggest to add a few lines as this
    * indicates the LastRow was the end of the sheet.
    * 2) Check it's not a new sheet with no data ie, LastRow = 0 and/or cell A1 is empty.
    * 3) A return result of 0 = an error otherwise any positive value is a valid result.
    */
    
     return   !(colArray[0][0]) ? 1                   // if first row is empty then presume it's a new empty sheet
            :!!(colArray[v_TestRow][0]) ? v_TestRow   // if the last row is not empty then column A was the longest
            : v_MaxRow==v_TestRow ? v_TestRow         // if Last=Max then consider adding a line here to extend row count, else
            : searchPair(0,v_TestRow);                // get on an find the last row
    }
    
    function searchPair(LowRow,HighRow){
    
    var BinRow = ((LowRow+HighRow)/2)|0;   // force an INT to avoid row ambiguity
    
    Logger.log ('LowRow/HighRow/BinRow = %s/%s/%s',LowRow, HighRow, BinRow);
    
    /*   Check your log. You shoud find that the last row is always found in under 20 hops.
     *   This will be true whether your data rows are 100 or 100,000 long.
     *   The longest element of this script is loading the Cache (ColArray)
     */
    
     return   (!(colArray[BinRow-1][0]))^(!(colArray[BinRow][0])) ? BinRow
            : (!(colArray[BinRow-1][0]))&(!(colArray[BinRow][0])) ? searchPair(LowRow,BinRow-1)
            : (!!(colArray[BinRow-1][0]))|(!!(colArray[BinRow][0])) ? searchPair(BinRow+1,HighRow)
            : false;   // Error
     }
    }
    
    /* The premise for the above logic is that the binary search is looking for a specific pairing, <Text/No text>
     * on adjacent rows.  You said there are no gaps so the pairing <No Text/Text> is not tested as it's irrelevant.
     * If the logic finds <No Text/No Text> then it looks back up the sheet, if it finds <Text/Text> it looks further
     * down the sheet.  I think you'll find this is quite fast, especially on datasets > 100,000 rows.
     */
    
    0 讨论(0)
  • 2020-11-22 11:02

    This may be another way to go around lastrow. You may need to play around with the code to suit your needs

        function fill() {
          var spreadsheet = SpreadsheetApp.getActive();
          spreadsheet.getRange('a1').activate();
          var lsr = spreadsheet.getLastRow();
          lsr=lsr+1;
          lsr="A1:A"+lsr;
    
          spreadsheet.getActiveRange().autoFill(spreadsheet.getRange(lsr), SpreadsheetApp.AutoFillSeries.DEFAULT_SERIES);
    };
    
    0 讨论(0)
  • 2020-11-22 11:06

    Although there is no straighforward formula, I can think of, it doesn't require dozens of lines of code to find out the last row in column A. Try this simple function. Use it in a cell the normal way you'd use some other function =CountColA()

    function CountColA(){
      var sheet = SpreadsheetApp.getActiveSheet();
      var data = sheet.getDataRange().getValues();
      for(var i = data.length-1 ; i >=0 ; i--){
        if (data[i][0] != null && data[i][0] != ''){
          return i+1 ;
        }
      }
    }
    
    0 讨论(0)
提交回复
热议问题