web-dev-qa-db-fra.com

Détermination de la dernière ligne d'une colonne

J'ai une feuille avec les données dans les colonnes A à H.

Je dois déterminer la dernière ligne de la colonne A qui contient des données (tout est contigu - aucune lacune dans les données/lignes).

Il y a aussi des données dans les autres colonnes qui ont plus des lignes de données que la colonne A, je dois donc isoler uniquement la colonne A. (Et/ou juste une plage dans la variable A). 

Je peux le faire au niveau de la feuille de calcul en utilisant 

=COUNTA(A2:A100)

Cependant, dans toutes mes recherches pour une solution de script Google Apps, tout ce que je semble avoir trouvé, ce sont des exigences pour pouvoir exécuter plusieurs fonctions englobant des dizaines de lignes de code, y compris de nombreux éléments i++ ... que je pourrais effectuer de manière moins complexe en décalant directement à partir de A1 .

Existe-t-il un moyen spécifique à la colonne de modifier cette méthode?

var aLast = ss.getDataRange().getNumRows();

Si un processus compliqué est ce qui est requis, alors qu’il en soit ainsi. Mais j'ai du mal à imaginer (et encore plus difficile à trouver!) Une solution plus simple.

Quelqu'un veut-il m'éclairer (ou faire éclater ma bulle)?

40
5th4x4

Pourquoi ne pas utiliser une astuce JavaScript?

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

J'ai emprunté cette idée à cette réponse . La méthode Array.filter() fonctionne sur le tableau Avals, qui contient toutes les cellules de la colonne A. En filtrant sur le constructeur d'une fonction native, nous récupérons uniquement les éléments non nuls.

Cela ne fonctionne que pour une seule colonne. si la plage contient plusieurs colonnes, le résultat de filter() inclura les cellules de toutes les colonnes et sera donc en dehors des dimensions remplies de la plage.

106
Mogsdad

Bien qu’il n’existe pas de formule simple, je pense, il n’est pas nécessaire de disposer de dizaines de lignes de code pour connaître la dernière ligne de la colonne A. Essayez cette fonction simple. Utilisez-le dans une cellule de la même manière que vous utiliseriez une autre fonction =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 ;
    }
  }
}
11
Srik

Vous pouvez le faire en procédant dans le sens inverse… .. À partir de la dernière ligne de la feuille de calcul et jusqu’à ce que vous obteniez une valeur. Cela fonctionnera dans tous les cas, même si vous avez des lignes vides entre les ..... Le code ressemble à ce qui suit:

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;
}
4
Akash Garg

La dernière ligne d'une feuille sera alors supposée basée sur la colonne 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();
  }              
}

Ceci corrige la réponse partiellement correcte de @ mrityunjay-pandey.

Pour étendre cette réponse pour obtenir la dernière ligne et la dernière colonne, nous pouvons utiliser:

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)];
}
3
Al Johri

Pour les très grands tableurs, cette solution est très rapide:

function GoLastRow() {
  var spreadsheet = SpreadsheetApp.getActive();
  spreadsheet.getRange('A:AC').createFilter();
  var criteria = SpreadsheetApp.newFilterCriteria().whenCellNotEmpty().build();
  var rg = spreadsheet.getActiveSheet().getFilter().setColumnFilterCriteria(1, criteria).getRange();

  var row = rg.getNextDataCell (SpreadsheetApp.Direction.DOWN);  

  LastRow = row.getRow();

  spreadsheet.getActiveSheet().getFilter().remove();

  spreadsheet.getActiveSheet().getRange(LastRow+1, 1).activate();

};
1
Luciano Pivi

personnellement, j'ai eu un problème similaire et je suis allé avec quelque chose comme ceci:

function getLastRowinColumn (ws, column) {
  var page_lastrow = ws.getDataRange().getNumRows();
  var last_row_col = 0
  for (i=1; i<=page_lastrow;i++) {
    if (!(spread.getRange(column.concat("",i)).isBlank())) {last_row_col = i};
  }
  return last_row_col
}

Il recherche le nombre de lignes dans les ws et les boucles dans chaque cellule de votre colonne. Lorsqu'il trouve une cellule non vide, il met à jour la position de cette cellule dans la variable last_row_col. Il présente l’avantage de vous permettre d’avoir des colonnes non contiguës tout en connaissant la dernière ligne (en supposant que vous parcouriez toute la colonne).

0
jello195

Jamais trop tard pour poster une réponse alternative j'espère. Voici un extrait de ma dernière cellule Trouver. Je suis principalement intéressé par la vitesse. Sur une base de données que j'utilise avec environ 150 000 lignes, cette fonction a pris (en moyenne) 0,087 seconde pour trouver la solution, par rapport à la solution JS @Mogsdad élégante ci-dessus, qui prend (en moyenne) 0,53 seconde pour les mêmes données. Les deux tableaux étaient pré-chargés avant l'appel de la fonction. Il utilise la récursivité pour effectuer une recherche binaire. Pour plus de 100 000 lignes, vous devriez constater qu'il ne faut pas plus de 15 à 20 sauts pour renvoyer le résultat.

J'ai laissé les appels au journal afin que vous puissiez d'abord le tester dans la console et voir son fonctionnement.

/* @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
DeeKay789

J'ai réécrit les fonctions getLastRow/getLastColumn pour spécifier un index de ligne ou un index de colonne. 

function get_used_rows(sheet, column_index){
      for (var r = sheet.getLastRow(); r--; r > 0) {
        if (sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn()).getCell(r, column_index).getValue() != ""){
          return r;
          break;
        }
      }
    }

function get_used_cols(sheet, row_index){
  for (var c = sheet.getLastColumn(); c--; c > 0) {
    if (sheet.getRange(1, 1, sheet.getLastRow(), sheet.getLastColumn()).getCell(row_index, c).getValue() != ""){
      return c;
      break;
    }
  }
}
0
Ashton Fei

J'ai essayé de rédiger 3 fonctions suivantes, vous pouvez les tester pour différents cas de la vôtre. Voici les données que j'ai testées avec:

enter image description here

La fonction getLastRow1 et getLastRow2 renverront 0 pour la colonne B La fonction getLastRow3 renverra 1 pour la colonne B

Dépend de ton cas, tu les ajusteras pour tes besoins.

function getLastRow1(sheet, column) {
  var data = sheet.getRange(1, column, sheet.getLastRow()).getValues();

  while(typeof data[data.length-1] !== 'undefined'
     && data[data.length-1][0].length === 0){ 
    data.pop();
  }
  return data.length;
}

function test() {
  var sh = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet6');
  Logger.log('Cách 1');
  Logger.log("Dòng cuối cùng của cột A là: " + getLastRow1(sh, 1));
  Logger.log("Dòng cuối cùng của cột B là: " + getLastRow1(sh, 2));
  Logger.log("Dòng cuối cùng của cột C là: " + getLastRow1(sh, 3));
  Logger.log("Dòng cuối cùng của cột D là: " + getLastRow1(sh, 4));
  Logger.log("Dòng cuối cùng của cột E là: " + getLastRow1(sh, 5));
  Logger.log('Cách 2');  
  Logger.log("Dòng cuối cùng của cột A là: " + getLastRow2(sh, 1));
  Logger.log("Dòng cuối cùng của cột B là: " + getLastRow2(sh, 2));
  Logger.log("Dòng cuối cùng của cột C là: " + getLastRow2(sh, 3));
  Logger.log("Dòng cuối cùng của cột D là: " + getLastRow2(sh, 4));
  Logger.log("Dòng cuối cùng của cột E là: " + getLastRow2(sh, 5));
  Logger.log('Cách 3');
  Logger.log("Dòng cuối cùng của cột A là: " + getLastRow3(sh, 'A'));
  Logger.log("Dòng cuối cùng của cột B là: " + getLastRow3(sh, 'B'));
  Logger.log("Dòng cuối cùng của cột C là: " + getLastRow3(sh, 'C'));
  Logger.log("Dòng cuối cùng của cột D là: " + getLastRow3(sh, 'D'));
  Logger.log("Dòng cuối cùng của cột E là: " + getLastRow3(sh, 'E'));

}

function getLastRow2(sheet, column) {
  var lr = sheet.getLastRow();
  var data = sheet.getRange(1, column, lr).getValues();

  while(lr > 0 && sheet.getRange(lr , column).isBlank()) {
    lr--;
  }

  return lr;
}

function getLastRow3(sheet, column) {
  var lastRow = sheet.getLastRow();
  var range = sheet.getRange(column + lastRow);
  if (range.getValue() !== '') {
    return lastRow;
  } else {
    return range.getNextDataCell(SpreadsheetApp.Direction.UP).getRow();
  } 
}

Pour obtenir le nombre de colonnes ou l'index de la dernière colonne:

var numColumns = sheet.getLastColumn()

Pour obtenir le nombre de lignes ou l'index de la dernière ligne:

var numRows = sheet.getLastRow()

var sheet = SpreadsheetApp.getActiveSheet()
0
Ashish Verma
var Direction=SpreadsheetApp.Direction;
var aLast =ss.getRange("A"+(ss.getLastRow()+1)).getNextDataCell(Direction.UP).getRow();
0
Mrityunjay pandey

C'est peut-être un autre moyen de contourner Lastrow. Vous devrez peut-être jouer avec le code pour répondre à vos besoins 

    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
Tariq Khalaf

J'ai utilisé getDataRegion

sheet.getRange(1, 1).getDataRegion(SpreadsheetApp.Dimension.ROWS).getLastRow()

Notez que cela dépend de la contiguïté des données (conformément à la demande de l'OP).

0
Simon Birt