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?