A Java és az XLS

Kategória: Excel, Fájlkezelés on szerda, május 26th, 2010 by javadev | Nincsenek megjegyzések

Egy érdekes cikk a prog.huról sniper tollából: a Java és az XLS.
Egy-egy alkalmazás kimenetét néha fontos más programok által is könnyen feldolgozható formátumban elmenteni. Jelen cikk célja annak bemutatása, hogyan is lehet adatokat a széles körben alkalmazott és elterjedt Excel XLS formátumba menteni Java-ból.

Egy programozónak sokszor fejtörést okozhat, hogy milyen formátumú kimenetet generáljon egy-egy programból. Sokszor a legegyszerűbb text állományok is megfelelnének a célnak, viszont a megrendelők nem tudnák kényelmesen kezelni a kapott adatokat. Emiatt sokszor kénytelen az ember más programok könnyen feldolgozható, formátumába menteni. Jelen cikkben bemutatom, hogyan is lehet a széles körben elterjedt és támogatott Excel “.xls” formátumába menteni adatokat JAVA-ból, anélkül, hogy a gépen lenne Excel.

Nagy szerencsénkre egy Andy Khan (http://www.andykhan.com) nevű programozó belekezdett egy olyan API fejlesztésébe, ami lehetővé teszi az Excel fájlok írását és olvasását JAVA környezetből anélkül, hogy lenne Excel telepítve a gépünkre. Természetesen a JExcelApi-n vannak még fejleszteni való funkciók, de az online közösségnek és a levelező listának hála, jó ütemben haladnak az egyre újabb funkciók implementálásai.

Képességek

* Excel 95,97, 2000 munkafüzeteket tud olvasni
* Írja és olvassa a képleteket(97-es és újabb verziójú Excel)
* Excel 2000 formátumú munkalapokat generál (Excel 97 vagy újabb verziójú Excel kell az olvasásához)
* Támogatja a betű-, szám- és dátumformázásokat
* Támogatja a cellák árnyékolását és színezését
* Módosítani tudja a meglévő munkalapokat
* Támogatja a képek létrehozását
* Megőrzi a makrókat másolás során
* Testre szabható loggolást biztosít

Korlátok

* A JExcelAPI nem tud diagramot és grafikont generálni valamint makró információkat, bár ezeket megőrzi a munkalapok másolása során.
* Képek munkalapokhoz adásakor csak a PNG formátumot támogatja.

A JExcelAPI használata
1. Új munkafüzet létrehozása

Az alábbi példa létrehoz egy üres munkafüzetet 3 munkalappal:

import jxl.write.*;
import jxl.*;
import java.util.Date;
import jxl.format.*;
import jxl.write.Number;
...
//kell egy változó amivel egy munkafüzethet tudunk hozzáférni:
private WritableWorkbook workBook;
//kell egy változó amivel egy munkalaphoz tudunk hozzáférni
private WritableSheet workSheet;
private static final int DEFAULT_FORMAT = -1;
private static final int TEXT_FORMAT = 0;
private static final int INTEGER_FORMAT = 1;
private static final int FLOAT_FORMAT = 2;
private static final int DATE_FORMAT = 3;
...
private void createEmptyXLS(String fileName)
{
//üres munkafüzet létrehozása
workBook = Workbook.createWorkbook(new File(fileName));
/*a fileName változó által megadott fájlnévre fogja menteni a
munkafüzetet a program */
//üres munkalapok hozzáadása
workBook.createSheet("Lap1",0);
//paraméterek: munkalap neve és az indexe
workBook.createSheet("Lap2",1);
workBook.createSheet("Lap3",2);
}

2. Munkalapok írása
A következő példában bemutatom, hogyan lehet kiválasztani egy adott munkalapot ahhoz, hogy írni tudjunk bele és lehet a celláit formázni. Első lépésként válasszuk ki a “Lap1″ nevű munkalapunkat:

workSheet = workBook.getSheet("Lap1");

Ezután minden adatunkat egy ciklusban kiírhatjuk az adott munkalapra. Ehhez nem kell mást tennünk, csak írni, egy olyan függvényt, ami paraméterben kapja az adatot, a cella koordinátáit és a formázó utasításokat pl.: cella típusa, színe, igazítása

private void writeCellDataToCell(int row, int col, String data, String format, String color, String align)
{
intiFormat = DEFAULT_FORMAT;// -1 = default; 0 = text; 1 = integer; 2 =float; 3= date
WritableCellFormat cell = new WritableCellFormat();
WritableCellFormat numCellFormat = newWritableCellFormat();
/*A formátumtól függően más-más formátumú cellát kell majd létrehoznunk az adatok
tárolására. Ezért a cell változónk a következő feltételek vizsgálatától függően
más-más formátumokkal fog létrejönni. Ennek következtében különböző típusú
cellákra lesz szükségünk az adatok tárolására, ezek kiválasztását fogja vezérelni
az iFormat változónk.*/
if(format.equalsIgnoreCase("INTEGER"))
{
cell = new WritableCellFormat(fontArial, NumberFormats.INTEGER);
iFormat = INTEGER_FORMAT;
}
else if(format.equalsIgnoreCase("FLOAT"))
{
cell = new WritableCellFormat(fontArial,NumberFormats.FLOAT);
iFormat = FLOAT_FORMAT;
}
else if(format.equalsIgnoreCase("THOUSANDS_INTEGER"))
{
cell = new WritableCellFormat(fontArial, NumberFormats.THOUSANDS_INTEGER);
iFormat = INTEGER_FORMAT;
}
else if(format.equalsIgnoreCase("THOUSANDS_FLOAT"))
{
cell = new WritableCellFormat(fontArial, NumberFormats.THOUSANDS_FLOAT);
iFormat = FLOAT_FORMAT;
}
else if(format.equalsIgnoreCase("PERCENT_INTEGER"))
{
cell = new WritableCellFormat(fontArial, NumberFormats.PERCENT_INTEGER);
iFormat = INTEGER_FORMAT;
}
else if(format.equalsIgnoreCase("PERCENT_FLOAT"))
{
cell = new WritableCellFormat(fontArial, NumberFormats.PERCENT_FLOAT);
iFormat = FLOAT_FORMAT;
}
else if(format.equalsIgnoreCase("TEXT"))
{
cell = new WritableCellFormat(fontArial,NumberFormats.TEXT);
iFormat = TEXT_FORMAT;
}
else if(format.equalsIgnoreCase("DEFAULT"))
{
cell = new WritableCellFormat(fontArial, NumberFormats.DEFAULT);
iFormat = DEFAULT_FORMAT;
}
else
{
cell = new WritableCellFormat(fontArial, NumberFormats.DEFAULT);
iFormat = DATE_FORMAT;
}
/*miután elkészült az új cellánk megadjuk, hogy merre legyen
bennük rendezve az adat*/

if(align.equalsIgnoreCase("CENTER"))
cell.setAlignment(cell.getAlignment().CENTRE);
else if(align.equalsIgnoreCase("LEFT"))
cell.setAlignment(cell.getAlignment().LEFT);
else if(align.equalsIgnoreCase("RIGHT"))
cell.setAlignment(cell.getAlignment().RIGHT);

/*miután az igazítás beállításával megvagyunk jöhet a cella
színének beállítása csak néhány színt használunk most a kód lerövidítése miatt*/

if(color == null|| color.equalsIgnoreCase("WHITE"))
cell.setBackground(cell.getBackgroundColour().WHITE);
else if(color.equalsIgnoreCase("AQUA"))
cell.setBackground(cell.getBackgroundColour().AQUA);
else
cell.setBackground(cell.getBackgroundColour().BLUE);

/*most már jöhet a megfelelő típusú cella létrehozása és a munkalapra írása:*/

if(iFormat == TEXT_FORMAT)
{
Label textCell = new Label(col,row,data,cell);
workSheet.addCell(textCell);
}
else if(iFormat == INTEGER_FORMAT)
{
Number numberCell = new Number(col, row,Integer.parseInt(data),cell);
workSheet.addCell(numberCell);
}
else if(iFormat == FLOAT_FORMAT)
{
Number numberCell = new Number(col, row,Double.parseDouble(data),cell);
workSheet.addCell(numberCell);
}
else
{
Label textCell = new Label(col,row,data,cell);
workSheet.addCell(textCell);
}
}

3. Munkafüzet mentése

workBook.write(); //a munkafüzet tartalmát fájlba írjuk
workBook.close(); //a munkafüzetet lezárjuk

4. Munkafüzet másolása

Szükségünk lehet arra, hogy egy munkafüzetet sablonként használjunk és az abból készített másolatokba írjunk. Most megmutatom, hogyan lehet egy munkafüzetet lemásolni egy adott helyre:

//az új, másolatból készülő írható munkafüzet:
private WritableWorkbook workBook;
//csak olvasható munkafüzet, amit másolni fogunk:
private Workbook workBookTemplate;

private void copyWorkBook(String from, String to)
{
//from=a sablonként használt munkafüzet elérésiútja és fájlneve
//to=az újonnan létrehozandó munkafüzet elérésiútja és fájlneve

workBookTemplate = Workbook.getWorkbook(new File(from));
workBook = Workbook.createWorkbook(new File(to),workBookTemplate);

}

5. Munkafüzet olvasása

Egy munkafüzet olvasásához meg kell nyitni egy munkafüzetet és ki kell választani belőle a beolvasandó munkalapot.

private void printSheet(Sheet sheet)
{
int iRows = workSheet.getRows();//sorok száma
int iCols = workSheet.getColumns();//oszlopok száma
String sRow = "";
for(int j = 0; j < iRows; j++)
{
sRow = "";
for(int i = 0; i < iCols; i++)
{
//cellák kiolvasása és kiírása az aktuális sorba
row += printCell(sheet.getCell(i,j))+"|";
}
System.out.println(row);//Aktuális sor kiíratása
}
}
private String printCell(Cell cell)
{
String sRet = "";
if(cell.getType() == CellType.LABEL)
{
LabelCell lc = (LabelCell)cell;
sRet = lc.getString();
}
else if(cell.getType() == CellType.NUMBER)
{
NumberCell nc = (NumberCell)cell;
sRet = String.valueOf(nc.getValue());
}
else if(cell.getType() == CellType.DATE)
{
DateCell dc = (DateCell)cell;
sRet = dc.toString();
}

return sRet;
}

6. Cellák formázása

Utolsó megjegyzésként kicsit még visszakanyarodnék a cellák formázására, amivel ugyan foglalkoztam a “Munkalapok írásánál” viszont vannak még apróbb dolgok, amiket érdemes megemlíteni. A számokat tároló cellákhoz számformátumokat tudunk rendelni, tehát megadható például, hogy hány tizedes jegy jelenjen meg az adott cellában. A cellák formázását a WritableCellFormat valamint a NumberFormat és a DateFormat osztályok segítségével tudjuk elvégezni.

Néhány példa ezek használatára:

WritableCellFormat integerFormat = new WritableCellFormat(NumberFormats.INTEGER);
Number myNumber = new Number(2,4, 1.23456789, integerFormat);
workSheet.addCell(myNumber);

Ez a kód részlet a harmadik oszlop ötödik sorába (C5 cella) az 1.23456789 számot fogja egész számként beleírni, vagyis konkrétan 1-et fog beleírni.

Ha mi szeretnénk megadni, hogy mondjuk 4 tizedes jegyig jelenjen meg egy érték egy cellában akkor a következő képpen kell eljárnunk:

NumberFormat numberFormat = new NumberFormat("#.####");
WritableCellFormat fourFrags = new WritableCellFormat(numberFormat);
Number myNumber = new Number(2,4, 1.2345, fourFrags);
workSheet.addCell(myNumber);

Dátumok formázásánál a dátum formátumot kell megadnunk:

Date currentTime = new Date(currentTimeMillis());
DateFormat dateFormat = new DateFormat("yyyy.MM.dd. hh:mm:ss");
WritableCellFormat dateCellFormat = new WritableCellFormat(dateFormat);
DateTime dateCell = new DateTime(2, 4, currentTime, dateCellFormat);
workSheet.addCell(dateCell);

Végszó

Remélem tudtam segíteni abban, hogy mindenki megismerhesse ezt hasznos kis API-t. Bízom benne, hogy minél többen fogják ezt a módszert választani ahhoz, adatok exportálásához.