Konečně se v našem seriálu dostáváme k čistě javovým implemtacím Excelového formátu. Začneme knihovnou Java Excel API (JExcelApi), kterou vytvořil Andy Khan a uvolnil pod licencí GNU LGPL.
Co tato knihovna umí zajímavého?
- vytváření a čtení XLS souborů
- formátování buněk
- práci se vzorci
- vkládání PNG obrázků
- kopírování grafů (vytváření nových podporováno není)
Zajímavější pro vás může být informace, co mi na této knihovně vadí. Tady jsou mé připomínky:
- odlišný přístup k dokumentům při čtení a při zápisu (třídy Workbook a WritableWorkbook nemají ani společný interface)
- práce s čisly podporuje pouze typ double, osobně bych uvítal např. i BigDecimal
- chybí jakákoliv podpora pro makra (ani při kopírování nezůstanou zachována)
- nepodporuje automatickou šířku sloupce (Auto Fit Selection)
- nelze nastavit typ buňky (viz příklad - vložím vzorec jehož výsledkem je text, ale JExcelApi si při čtení myslí, že to je číslo)
- tvar vzorců neodpovídá na 100% tvaru z Excelu (chybí uvozovací rovnítko, jako oddělovač parametrů funkcí je použita čárka namísto středníku)
WorkbookSettings.setLocale(...)), ale osobně bych to preferoval úplně bez překladů.
A nakonec praktická ukázka:
/**
* Priklad cteni dokumentu pres JExcel
* @throws BiffException
* @throws IOException
* @throws FormulaException
*/
public static void readDemo() throws BiffException, IOException, FormulaException {
System.out.println("Ctu soubor: " + FILE_NAME);
// otevreni souboru
final Workbook wb = Workbook.getWorkbook(new File(FILE_NAME));
//vypisem vsechny listy
for (int i=0,m=wb.getNumberOfSheets();i<m;i++) {
final Sheet sheet = wb.getSheet(i);
System.out.println("List: " + sheet.getName());
//vypisem hodnoty v listu
for (int j=0,n=sheet.getRows();j<n;j++) {
final Cell[] cells = sheet.getRow(j);
final StringBuffer tmpStrRow = new StringBuffer();
for (int k=0; k<cells.length; k++) {
//spravne bychom tady meli bunku zpracovavat v zavislosti na jejim typu,
//neb v JavaDocu je metoda getContents oznacena jako "dirty" :)
tmpStrRow.append(cells[k].getContents());
//zracovani podle typu bunky muze vypadat nasledovne:
if (cells[k].getType()==CellType.BOOLEAN_FORMULA
|| cells[k].getType()==CellType.DATE_FORMULA
|| cells[k].getType()==CellType.NUMBER_FORMULA
|| cells[k].getType()==CellType.STRING_FORMULA) {
final FormulaCell tmpFormula = (FormulaCell) cells[k];
//do zavorky vypiseme vzorech pouzity v teto bunce
tmpStrRow.append(" (").append(tmpFormula.getFormula()).append(")");
}
tmpStrRow.append("\t");
}
System.out.println(tmpStrRow.toString());
}
}
//nakonec zavrem workbook a uvolnime pamet
wb.close();
}
/**
* Priklad vytvoreni XLS dokumentu pres JExcel
* @throws IOException see {@link Workbook}
* @throws RowsExceededException see {@link WritableSheet#addCell(jxl.write.WritableCell)}
* @throws WriteException see {@link WritableSheet#addCell(jxl.write.WritableCell)}
*/
public static void writeDemo() throws IOException, RowsExceededException, WriteException {
System.out.println("Vytvarim soubor: " + FILE_NAME);
// konfigurace - nechci pouzivat jmena funkci v nemcine :)
final WorkbookSettings wbs = new WorkbookSettings();
wbs.setLocale(Locale.US);
//vytvoreni noveho Workbooku (souboru)
final WritableWorkbook wb = Workbook.createWorkbook(new File(FILE_NAME),wbs);
//pridame list
final WritableSheet sheet = wb.createSheet("Muj super list", 0);
//nastaveni fontu
final WritableFont font = new WritableFont(WritableFont.TIMES, 16, WritableFont.BOLD, true);
final WritableCellFormat cellFormat = new WritableCellFormat(font);
//pridani stringu
sheet.addCell(new Label(0,0,"Popisek hodnoty", cellFormat));
//pridani cisla (bez specialniho formatovani)
sheet.addCell(new Number(1,0, 1.23456d));
//pridani vzorce
sheet.addCell(new Formula(1,1, "CONCATENATE(\"Vysledek vzorce: \",B1+1.90703)"));
//zapsani do souboru
wb.write();
//uvolneni z pameti
wb.close();
System.out.println("Soubor ulozen.");
}
výstupem programu bylo na mém německém počítači toto:
Vytvarim soubor: jne5.xls
Soubor ulozen.
Ctu soubor: jne5.xls
List: Muj super list
Popisek hodnoty 1,235
4 (VERKETTEN("Vysledek vzorce: ",B1+1.90703))
Celý příklad si můžete stáhnout na adrese http://www.cacek.cz/javlog-attachments/JakNaExcel5.zip
Komentáře
Vytvarim soubor: jne5.xls
Exception in thread "main" java.lang.ExceptionInInitializerError
at JExcelApiTest.writeDemo(JExcelApiTest.java:86)
at JExcelApiTest.main(JExcelApiTest.java:116)
Caused by: java.lang.NullPointerException
at java.lang.Class.forName0(Native Method)
at java.lang.Class.forName(Unknown Source)
at common.Logger.initializeLogger(Logger.java:71)
at common.Logger.getLogger(Logger.java:42)
at jxl.WorkbookSettings.[clinit]*(WorkbookSettings.java:42)
... 2 more
(*[clinit] je v ostrych zavorkach, formular mi vsak nedovoli psat tagy)
cestu k souboru mám, si myslím, nastavenou dobře. Každopádně to spadne v době, kdy jí to snad ani nepotřebuje.
Nevíte kde je chyba?