2010-04-15 7 views
11

J'essaie de trouver l'index de la dernière ligne d'une feuille de calcul Excel à l'aide du POI d'Apache pour Java. Je pensais que cela devrait être possible avec getLastRowNum() ou getPhysicalNumberOfRows() mais ils ne semblent pas donner les bons résultats. Par exemple, j'ai une feuille de calcul d'une ligne et ces deux fonctions retournent une valeur de 1140. Une autre feuille de calcul deux lignes obtient une valeur de 1162.Recherche de la dernière ligne d'une feuille de calcul Excel

L'autre problème est que je ne peux pas simplement rechercher la première ligne vide, car il peut être possible d'avoir des lignes vides entre les lignes de données valides.

Y a-t-il un moyen de trouver l'index de la dernière rangée? Je suppose que je pourrais faire une exigence de ne pas avoir des lignes vides entre les données, mais j'espérais une meilleure solution.

Modifier: Pour l'enregistrement en utilisant un itérateur n'a pas aidé. Il a juste itéré sur les 1140/1162 rangées supposées.

+4

Il existe une raison pour laquelle toutes les classes de POI pour Excel sont appelées HSSF ... – ig0774

Répondre

1

Je sais comment résoudre votre problème en utilisant VBA, mais je ne suis pas sûr de savoir comment obtenir des informations équivalentes à partir de l'interface Apache POI. Dans VBA, pour obtenir la gamme de cellules utilisées dans feuille « Sheet1 », utilisez:

Worksheets("Sheet1").UsedRange 

Ce retourne un objet Range qui a des propriétés qui fournissent de plus amples informations. Par exemple, pour obtenir le nombre de lignes dans ce Range, utilisez:

Worksheets("Sheet1").UsedRange.Rows 

Encore une fois, je ne suis pas sûr que ce soit acessible via l'API de POI, mais sinon, peut-être est un moyen d'exécution arbitraire extraits de VBA?

+0

À première vue, je ne vois rien de similaire à la solution VBA. Pas trop sûr de l'exécution des extraits de VBA non plus. – FromCanada

7

je reçois la sortie prévue en utilisant poi-et test.xls 3,6 à 20.091.214 ayant deux lignes vides suivies de trois lignes occupées:

InputStream myxls = new FileInputStream("test.xls"); 
Workbook book = new HSSFWorkbook(myxls); 
Sheet sheet = book.getSheetAt(0); 
System.out.println(sheet.getLastRowNum()); 

Sortie: 4

+0

En fait, après avoir vérifié à nouveau, j'ai remarqué que j'obtenais le résultat correct sur certaines des feuilles de calcul sur la centaine que j'utilisais. La seule différence semblait que ceux qui ne travaillaient pas seulement avaient une feuille de calcul renommée. J'ai essayé de tester un nouveau classeur et cela a donné le bon résultat. Cependant, je n'ai pas été capable de reproduire l'erreur en renommant la feuille de travail et en supprimant les autres, la source du problème est toujours inconnue = – FromCanada

+0

Une façon d'éliminer manuellement les livres errants en vérifiant s'il y a une discordance? – trashgod

+0

cela fonctionnera dans le cas normal .. mais ne fonctionnera pas lorsque vous exécutez le même code après avoir supprimé quelques dernières lignes ... sheet.getLastRowNum donnera le nombre de lignes précédent seulement ... –

0

Vous pouvez le faire par le code suivant :

SVTableModel model = new SVTableModel(sheet); 
lastRowNum = model.getRowCount(); 

Cependant, je suis en train de le faire dans Apache POI 3.7 mais n'a pas pu trouver le SVTableModel dans l'API. Cela a été retiré depuis 3.2, je suppose.

3

Vous pouvez utiliser la méthode suivante pour obtenir le nombre de lignes d'origine.

HSSFSheet worksheet = workbook.getSheet("Role_Mapping"); 
int rowsNum = worksheet.getPhysicalNumberOfRows(); 
1

La seule façon de savoir avec certitude est de tester les lignes. Voici la solution que je utilise pour le même problème:

int lastRowIndex = -1; 
if(sheet.getPhysicalNumberOfRows() > 0) 
{ 
    // getLastRowNum() actually returns an index, not a row number 
    lastRowIndex = sheet.getLastRowNum(); 

    // now, start at end of spreadsheet and work our way backwards until we find a row having data 
    for(; lastRowIndex >= 0; lastRowIndex--){ 
     Row row = sheet.getRow(lastRowIndex); 
     if(row != null){ 
      break; 
     } 
    } 
} 

Note: cela ne vérifie pas pour les lignes qui semblent être vides, mais ne sont pas, comme les cellules qui ont une chaîne vide en eux. Pour cela, vous avez besoin d'une solution plus complète comme:

private int determineRowCount() 
{ 
    this.evaluator = workbook.getCreationHelper().createFormulaEvaluator(); 
    this.formatter = new DataFormatter(true); 

    int lastRowIndex = -1; 
    if(sheet.getPhysicalNumberOfRows() > 0) 
    { 
     // getLastRowNum() actually returns an index, not a row number 
     lastRowIndex = sheet.getLastRowNum(); 

     // now, start at end of spreadsheet and work our way backwards until we find a row having data 
     for(; lastRowIndex >= 0; lastRowIndex--) 
     { 
      Row row = sheet.getRow(lastRowIndex); 
      if(!isRowEmpty(row)) 
      { 
       break; 
      } 
     } 
    } 
    return lastRowIndex; 
} 

/** 
* Determine whether a row is effectively completely empty - i.e. all cells either contain an empty string or nothing. 
*/ 
private boolean isRowEmpty(Row row) 
{ 
    if(row == null){ 
     return true; 
    } 

    int cellCount = row.getLastCellNum() + 1; 
    for(int i = 0; i < cellCount; i++){ 
     String cellValue = getCellValue(row, i); 
     if(cellValue != null && cellValue.length() > 0){ 
      return false; 
     } 
    } 
    return true; 
} 

/** 
* Get the effective value of a cell, formatted according to the formatting of the cell. 
* If the cell contains a formula, it is evaluated first, then the result is formatted. 
* 
* @param row the row 
* @param columnIndex the cell's column index 
* @return the cell's value 
*/ 
private String getCellValue(Row row, int columnIndex) 
{ 
    String cellValue; 
    Cell cell = row.getCell(columnIndex); 
    if(cell == null){ 
     // no data in this cell 
     cellValue = null; 
    } 
    else{ 
     if(cell.getCellType() != Cell.CELL_TYPE_FORMULA){ 
      // cell has a value, so format it into a string 
      cellValue = this.formatter.formatCellValue(cell); 
     } 
     else { 
      // cell has a formula, so evaluate it 
      cellValue = this.formatter.formatCellValue(cell, this.evaluator); 
     } 
    } 
    return cellValue; 
} 
-2
int total = sheet.getPhysicalNumberOfRows() - sheet.getLastRowNum(); 
+1

La question a demandé l'index de la dernière rangée. Cela semble obtenir l'index de la première ligne, et l'attribue inexplicablement à une variable nommée "total". –

0

J'ai eu le même problème auparavant.J'utilise cette astuce pour obtenir la bonne valeur de ligne retournée:

  1. Ouvrez le fichier excel et aller la feuille attendue.
  2. Sélectionnez la dernière ligne + 1. Par exemple, vous avez 12 lignes avec des données, puis cliquez sur la ligne 13, puis descendez jusqu'à la ligne 2000. Assurez-vous que toutes les lignes sont sélectionnées.
  3. Cliquez avec le bouton droit sur la ligne sélectionnée et choisissez Supprimer.
  4. Réexécutez le code et vérifiez la valeur renvoyée.

Ce n'est pas le problème de la bibliothèque POI.