JavaSvet - otvorena java zajednica

 
glavna stranica arr2javasvet  english version arr2java.net

Čitanje Excel dokumenta iz Jave

Nemanja Kostić
29 Maj 2004

Jedan od korisnijih paketa iz radionice Jakarta tima je svakako Jakarta POI paket koji omogućava rad sa Microsoft file formatima poput Excel .xls i Word .doc formata. Deo POI paketa koji se bavi radom sa Excel dokumentima naziva se HSSF, dok se Word-ovim dokumentima bavi HWPF. HSSF je dostigao vrlo zrelu fazu, tako da se može reći da je skoro bez bagova. U nastavku ćemo videti zašto sam stavio "skoro". Sa druge strane, HWPF je još uvek u nekoj ranoj fazi razvoja i koliko sam uspeo da vidim na sajtu Jakarta traži developere koji bi nastavili sa radom na ovom projektu. Daćemo još malo vremena razvoju HWPF-a, a do tada ću opisati samo HSSF paket.

Za sve one koje mrzi da češljaju dokumentaciju, u nastavku ću prikazati kako se podaci mogu pročitati iz Excel fajla. Upis u Excel fajl ću ostaviti za neki drugi put. Mada relano gledano, ko bi uopšte želeo nešto da upisuje u Excel? ;)

Pa da krenemo redom...
Klase koje ćemo koristiti iz paketa POI su POIFSFileSystem, HSSFWorkbook, HSSFSheet, HSSFRow i HSSFCell.
Njih dakle importujemo na početku:

import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFCell;

U POIFSFileSystem učitavamo naš Excel dokument čime ga prevodimo u POI format i omogućavamo parsiranje dokumenta. HSSFWorkbook predstavlja logički ekvivalent isparsiranog Excel dokumenta, dok je svrha ostalih klasa koje koristimo (HSSFSheet, HSSFRow i HSSFCell) jasna već po samom nazivu.

Dalje, učitavamo naš excel fajl TestExcel.xls:

POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("TestExcel.xls"));
HSSFWorkbook wb =
new HSSFWorkbook(fs);

Sad kad imamo HSSFWorkbook možemo da pročitamo broj stranica (Sheet) u Excelu i njihove nazive. Na osnovu toga odabiramo sa kojom ćemo stranicom nastaviti da radimo. Mi ćemo predpostaviti da nas samo prva stranica (Sheet1) zanima tj. nulta:

HSSFSheet sheet = wb.getSheetAt(0);

Ovo je poslednja faza učitavanja našeg Excel dokumenta. Pošto imamo HSSFSheet, mi smo dospeli upravo tamo gde smo i hteli. A to je u odgovarajuću stranicu Excel fajla. Dalje nam na raspolaganju stoje svi podaci u svim redovima i kolonama te stranice i samo je pitanje šta nam zapravo treba.

Navigacija po redovima se vrši pomoću iteratora:

Iterator rows = sheet.rowIterator();
HSSFRow row =
(HSSFRow) rows.next();

Navigacija po kolonama se vrši unutar odgovarajućeg reda takođe pomoću iteratora:

Iterator cells = row.cellIterator();

Recimo da želimo da pročitamo sve podatke iz treće kolone. Pre nego se pozicioniramo direktno u treću kolonu bilo bi pametno proveriti da li ona uopšte postoji:

int numberOfColumns = row.getPhysicalNumberOfCells();

Ukoliko postoji, idemo dalje:

int desiredColumn = 2;
if(numberOfColumns>desiredColumn)
{   
    
while (rows.hasNext())
     {
     
HSSFRow row = (HSSFRow) rows.next();
      HSSFCell cell = row.getCell
( (short) desiredColumn );
      String value = getCellValue
(cell);
      System.out.println
("Vrednost polja u redu="+row.getRowNum()+
                        
" i koloni"+desiredColum+" je " + value);
    
}       
}

Pošto polja u Excel-u mogu biti raznih tipova, HSSFCell ima mogućnost raspoznavanja istih. Ta logika je izvučena u metodi getCellValue(HSSFCell cell).

public String getCellValue(HSSFCell cell) {

   
switch (cell.getCellType()) {
   
case HSSFCell.CELL_TYPE_NUMERIC: {
       
double value = cell.getNumericCellValue();
       
return Double.toString(value);
   
}
   
case HSSFCell.CELL_TYPE_STRING: {
       
String value = cell.getStringCellValue();
       
return value;
   
}
   
case HSSFCell.CELL_TYPE_BLANK: {              
       
return "";
   
}
   
case HSSFCell.CELL_TYPE_BOOLEAN: {              
       
return cell.getBooleanCellValue()?"true":"false";
   
}
   
default: {             
       
return "unknown value type";
   
}
    }
}

I to je sve. Vrlo jednostavno, a vrlo korisno. Međutim, kako sam imao prilike da parsiram ogromne Excel fajlove, došlo je do određenih problema. Prvo, sam Excel stavlja limit na broj redova unutar jedne stranice, a to je 65536. Ali dobro, na to ne možemo da utičemo. Drugo, problem sa POI paketom je da ne ume da pročita redove posle 32768-og. Ali za ovo ima rešenja.

Naime, problem se javlja samo kada redove čitamo pomou iteratora, tj. kao:

Iterator rows = sheet.rowIterator();

Iako je to preporučeni način rada, ja sam morao da izbegnem iteratore nebili se dokopao druge polovine podataka. Rešenje je jednostavno. Moramo koristiti metode klase HSSFSheet za čitanje ukupnog broja redova i za ručno pozicioniranje na svaki.

// podatak o ukupnom broju redova
int numberOfRows = sheet.getPhysicalNumberOfRows();       

// pozicioniranje na odredjeni red
HSSFRow row = sheet.getRowAt(specificRowNumber);

POI se trenutno nalazi u finalnoj verziji 2.5 i može se download-ovati sa sajta Jakarte: http://jakarta.apache.org/poi