Le API Java POI sono molto importanti nel mondo dello sviluppo, poichè consentono di far interagire le nostre applicazioni con buona parte degli applicativi della suite Microsoft Office. In questo articolo vedremo brevemente quali sono le caratteristiche, i pregi e i difetti di Apache POI e presenteremo una serie di esempi di codice con il loro utilizzo.
Introduzione
Apache POI è un progetto dell’Apache Software Foundation che utilizza una libreria Java per leggere e scrivere file nel formato Microsoft Office come Word, PowerPoint ed Excel [1]. La sigla POI, così come altre sigle usate nel progetto, possono avere una interpretazione scherzosa, che prende garbatamente in giro le implementazioni dei vari formati Microsoft: in tal senso POI starebbe per Poor Obfuscation Implementation, con riferimento al fatto che è stato facile effettuare lo “smontaggio” dei vari formati, e HSSF vorrebbe dire Horrible SpreadSheet Format, con evidentemente riferimento al formato del foglio elettronico.
Il formato XML di Microsoft
Il progetto è nato con l’obiettivo di creare e mantenere API Java per manipolare diversi tipi di file che si basano sullo standard OfficeOpenXML (OOXML). Il formato OfficeOpenXML è il nuovo standard basato sui file XML che che si trova in Microsoft Office a partire dal 2007 e 2008, e che è riconoscibile nei file dalle estensioni.xlsx (foglio elettronico Excel),.docx (elaboratore di testi Word) e.pptx (applicazione di presentazione PowerPoint).
I componenti di Apache POI
Per ogni applicazione Microsoft Office esistono dei componenti che dialogano tra le api Java POI e OOXML: HSSF + XSSF per le cartelle Excel, HWPF + XWPF per i documenti Word e HSLF + XSLF per le presentazioni PowerPoint. A questi, recentemente si è aggiunto il componente HSNF per Microsoft Outlook. Esistono inoltre anche dei progetti ancora in fase di sviluppo come HDGF per Visio, HMEF per TNEF (winmail) e HPBF per Publisher. Vediamo di seguito un po’ di caratteristiche delle implementazioni esistenti.
Excel
HSSF è l’implementazione Java di POI per il formato Excel 97-2007 (.xls), mentre XSSF è quella per il formato Excel 2007 OOXML (.xlsx). Sia HSSF che XSSF permettono di leggere, creare, modificare, scrivere i fogli di calcolo di Excel. La figura 1 mostra uno specchietto riassuntivo delle caratteristiche di entrambi i componenti.
Figura 1 – Le caratteristiche dei componenti HSSF e XSSF di Apache POI.
Primi passi
Vediamo ora come viene creata una nuova cartella di lavoro in POI
Workbook wb = new HSSFWorkbook(); FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close(); Workbook wb = new XSSFWorkbook(); FileOutputStream fileOut = new FileOutputStream("workbook.xlsx"); wb.write(fileOut); fileOut.close();
Creazione di nuovo foglio di calcolo
Workbook wb = new HSSFWorkbook(); // oppure new XSSFWorkbook(); Sheet sheet1 = wb.createSheet("primoFoglio"); Sheet sheet2 = wb.createSheet("secondoFoglio"); // N.B.: il nome del foglio non deve superare // i 31 caratteri e non deve avere i seguenti: // 0x0000 // 0x0003 // due punti (:) // barra inversa backslash () // asterisco (*) // punto interrogativo (?) // barra slash (/) // parentesi quadre ([)(]) // Puoi utilizzare // org.apache.poi.ss.util.WorkbookUtil // #createSafeSheetName(String nameProposal)} // per scrivere nomi validi, questa sostituisce // i caratteri non validi con uno spazio (' ') String safeName = WorkbookUtil.createSafeSheetName("[O'Brien's sales*?]"); Sheet sheet3 = wb.createSheet(safeName); FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
Creazione di celle
Workbook wb = new HSSFWorkbook(); //Workbook wb = new XSSFWorkbook(); CreationHelper createHelper = wb.getCreationHelper(); Sheet sheet = wb.createSheet("new sheet"); // Creare una riga e mettere delle celle, partendo dalla riga zero Row row = sheet.createRow((short)0); // Mettere valori nella cella Cell cell = row.createCell(0); cell.setCellValue(1); // oppure fare tutto su una linea row.createCell(1).setCellValue(1.2); row.createCell(2).setCellValue( createHelper.createRichTextString("This is a string")); row.createCell(3).setCellValue(true); // salvare la cartella di lavoro in un file FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
Tipi di celle
Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("new sheet"); Row row = sheet.createRow((short)2); row.createCell(0).setCellValue(1.1); row.createCell(1).setCellValue(new Date()); row.createCell(2).setCellValue(Calendar.getInstance()); row.createCell(3).setCellValue("a string"); row.createCell(4).setCellValue(true); row.createCell(5).setCellType(Cell.CELL_TYPE_ERROR); // salvare la cartella di lavoro in un file FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
Vari tipi di allineamento testo
public static void main(String[] args) throws Exception { Workbook wb = new XSSFWorkbook(); //oppure new HSSFWorkbook(); Sheet sheet = wb.createSheet(); Row row = sheet.createRow((short) 2); row.setHeightInPoints(30); createCell(wb, row, (short) 0, CellStyle.ALIGN_CENTER, CellStyle.VERTICAL_BOTTOM); createCell(wb, row, (short) 1, CellStyle.ALIGN_CENTER_SELECTION, CellStyle.VERTICAL_BOTTOM); createCell(wb, row, (short) 2, CellStyle.ALIGN_FILL, CellStyle.VERTICAL_CENTER); createCell(wb, row, (short) 3, CellStyle.ALIGN_GENERAL, CellStyle.VERTICAL_CENTER); createCell(wb, row, (short) 4, CellStyle.ALIGN_JUSTIFY, CellStyle.VERTICAL_JUSTIFY); createCell(wb, row, (short) 5, CellStyle.ALIGN_LEFT, CellStyle.VERTICAL_TOP); createCell(wb, row, (short) 6, CellStyle.ALIGN_RIGHT, CellStyle.VERTICAL_TOP); // salvare la cartella di lavoro in un file FileOutputStream fileOut = new FileOutputStream("xssf-align.xlsx"); wb.write(fileOut); fileOut.close(); } /** * Creo e allineo celle in diverse maniere * * @param wb workbook * @param row riga * @param column colonna * @param halign allineamento */ private static void createCell(Workbook wb, Row row, short column, short halign, short valign) { Cell cell = row.createCell(column); cell.setCellValue("Allineata"); CellStyle cellStyle = wb.createCellStyle(); cellStyle.setAlignment(halign); cellStyle.setVerticalAlignment(valign); cell.setCellStyle(cellStyle); }
Lavorare con i bordi
Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("new sheet"); // Creare una riga e inserire delle celle, partendo dalla riga zero Row row = sheet.createRow(1); // Mettere valori nella cella Cell cell = row.createCell(1); cell.setCellValue(4); // Impostare lo stile della cella con i bordi tutti intorno CellStyle style = wb.createCellStyle(); style.setBorderBottom(CellStyle.BORDER_THIN); style.setBottomBorderColor(IndexedColors.BLACK.getIndex()); style.setBorderLeft(CellStyle.BORDER_THIN); style.setLeftBorderColor(IndexedColors.GREEN.getIndex()); style.setBorderRight(CellStyle.BORDER_THIN); style.setRightBorderColor(IndexedColors.BLUE.getIndex()); style.setBorderTop(CellStyle.BORDER_MEDIUM_DASHED); style.setTopBorderColor(IndexedColors.BLACK.getIndex()); cell.setCellStyle(style); // Salvare la cartella di lavoro in un file FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
Iterare righe e celle
Row definisce CellIterator, classe interna per gestire l’iterazione sulle celle (ottenere un oggetto con chiamata a row.cellIterator () ), e su uno sheet fornisce un metodo rowIterator() per dare un iteratore a tutte le righe. Questi implementano l’interfaccia java.lang.Iterable per consentire di ciclare a un for each.
Sheet sheet = wb.getSheetAt(0); for (Row row : sheet) { for (Cell cell : row) { // Fai qualcosa } }
Ottenere il contenuto delle celle
Per ottenere il contenuto di una cella, è necessario prima sapere che tipo di cella sia. Quindi si vuole attivare il tipo di cella, e poi chiamare il getter appropriato per quella cella. Nel codice seguente, si cicla su ogni cella del foglio, facendo stampare il riferimento e il contenuto di quella cella.
// import org.apache.poi.ss.usermodel.*; Sheet sheet1 = wb.getSheetAt(0); for (Row row : sheet1) { for (Cell cell : row) { CellReference cellRef = new CellReference(row.getRowNum(), cell.getColumnIndex()); System.out.print(cellRef.formatAsString()); System.out.print(" - "); switch (cell.getCellType()) { case Cell.CELL_TYPE_STRING: System.out.println(cell.getRichStringCellValue().getString()); break; case Cell.CELL_TYPE_NUMERIC: if (DateUtil.isCellDateFormatted(cell)) { System.out.println(cell.getDateCellValue()); } else { System.out.println(cell.getNumericCellValue()); } break; case Cell.CELL_TYPE_BOOLEAN: System.out.println(cell.getBooleanCellValue()); break; case Cell.CELL_TYPE_FORMULA: System.out.println(cell.getCellFormula()); break; default: System.out.println(); } } }
Lavorare con i caratteri
Workbook wb = new HSSFWorkbook(); Sheet sheet = wb.createSheet("new sheet"); // Creare una riga e mettere delle celle, partendo dalla riga zero Row row = sheet.createRow(1); // Impostare un nuovo font Font font = wb.createFont(); font.setFontHeightInPoints((short)24); font.setFontName("Courier New"); font.setItalic(true); font.setStrikeout(true); // I font sono impostati all'interno di uno stile style CellStyle style = wb.createCellStyle(); style.setFont(font); // Mettere valori nella cella Cell cell = row.createCell(1); cell.setCellValue("This is a test of fonts"); cell.setCellStyle(style); // Salvare la cartella di lavoro in un file FileOutputStream fileOut = new FileOutputStream("workbook.xls"); wb.write(fileOut); fileOut.close();
Concludiamo qua la nostra carrellata sugli esempi Excel, perchè ce ne sarebbero stati molti altri da far vedere: questi però, a mio avviso, sono quelli di base da cui si può partire per scrivere delle applicazioni di reportistica in Java che possano interfacciarsi con Excel.
Word
HWPF è il nome dell’oggetto per manipolare file in Java nel formato Word 97-2007. Esso permette il solo accesso in lettura ai documenti in formato Word 6 e Word 95. Successivamente è stato introdotto l’oggetto XWPF per il formato Word OOXML, quello più nuovo e caratterizzato dall’estensione.docx.
Entrambi gli oggetti (XWPF e XWPF) potrebbero essere descritti come “moderatamente funzionali”. In alcuni casi come l’estrazione del testo, il supporto è molto forte, mentre per altre funzionalità il supporto potrebbe risultare limitato e quindi potrebbe essere necessario andare a scavare nel codice sorgente. Per questo la comunità Apache accetta volentieri l’aiuto di tutti. Vediamo ora alcune funzionalità
Estrazione di base del testo
Per l’estrazione di base del testo, bisogna fare uso di org.apache.poi.xwpf.extractor.XWPFWordExtractor. Si accetta un flusso di input o un XWPFDocument. Il metodo getText() può essere utilizzato per ottenere il testo da tutti i paragrafi, insieme a tabelle, intestazioni e così via.
Estrazione di testo specifico
Per ottenere del testo specifico, bisogna creare innanzitutto un org.apache.poi.xwpf.XWPFDocument. Selezionare la IBodyElement di interesse (tabella, comma, etc.), e da lì prendere un XWPFRun. Infine prendere il testo e ricavarne le proprietà.
Intestazioni e piè di pagina
Per ottenere le intestazioni e piè di pagina di un documento Word, in primo luogo creare un org.apache.poi.xwpf.XWPFDocument. Successivamente, è necessario creare un org.apache.poi.xwpf.usermodel.XWPFHeaderFooter, passandogli il nostro XWPFDocument. Infine, il XWPFHeaderFooter permette di accedere alle intestazioni e piè di pagina, incluse anche quelle pagine dispari diverse se così definite nel documento.
Modifica testo
Da un XWPFParagraph, è possibile recuperare gli elementi XWPFRun esistenti che compongono il testo. Per aggiungere nuovo testo, il metodo createRun() aggiunge un nuovo XWPFRun alla fine dell’elenco. insertNewRun(int) può invece essere utilizzato per aggiungere un nuovo XWPFRun in un punto specifico nel paragrafo.
Una volta che si sia ottenuto un XWPFRun, è possibile utilizzare il metodo setText(String) per apportare modifiche al testo. Per aggiungere elementi “spazi bianchi” come tabulazioni e interruzioni di linea, è necessario utilizzare metodi come addTab() e addCarriageReturn().
Esempio
public class SimpleDocument { public static void main(String[] args) throws Exception { XWPFDocument doc = new XWPFDocument(); XWPFParagraph p1 = doc.createParagraph(); p1.setAlignment(ParagraphAlignment.CENTER); p1.setBorderBottom(Borders.DOUBLE); p1.setBorderTop(Borders.DOUBLE); p1.setBorderRight(Borders.DOUBLE); p1.setBorderLeft(Borders.DOUBLE); p1.setBorderBetween(Borders.SINGLE); p1.setVerticalAlignment(TextAlignment.TOP); XWPFRun r1 = p1.createRun(); r1.setBold(true); r1.setText("The quick brown fox"); r1.setBold(true); r1.setFontFamily("Courier"); r1.setUnderline(UnderlinePatterns.DOT_DOT_DASH); r1.setTextPosition(100); XWPFParagraph p2 = doc.createParagraph(); p2.setAlignment(ParagraphAlignment.RIGHT); //bordi p2.setBorderBottom(Borders.DOUBLE); p2.setBorderTop(Borders.DOUBLE); p2.setBorderRight(Borders.DOUBLE); p2.setBorderLeft(Borders.DOUBLE); p2.setBorderBetween(Borders.SINGLE); XWPFRun r2 = p2.createRun(); r2.setText("jumped over the lazy dog"); r2.setStrike(true); r2.setFontSize(20); XWPFRun r3 = p2.createRun(); r3.setText("and went away"); r3.setStrike(true); r3.setFontSize(20); r3.setSubscript(VerticalAlign.SUPERSCRIPT); XWPFParagraph p3 = doc.createParagraph(); p3.setWordWrap(true); p3.setPageBreak(true); p3.setAlignment(ParagraphAlignment.BOTH); p3.setSpacingLineRule(LineSpacingRule.EXACT); p3.setIndentationFirstLine(600); XWPFRun r4 = p3.createRun(); r4.setTextPosition(20); r4.setText("CIAO"); r4.addBreak(BreakType.PAGE); r4.setText("MONDO"); "); r4.setItalic(true); XWPFRun r5 = p3.createRun(); r5.setTextPosition(-10); r5.setText("altro testo"); r5.addCarriageReturn(); r5.setText("TESTO"); r5.addBreak(); r5.setText("PROVA"); r5.addBreak(BreakClear.ALL); r5.setText("FINE"); FileOutputStream out = new FileOutputStream("simple.docx"); doc.write(out); out.close(); } }
Inserire immagini in un testo
public class SimpleImages { public static void main(String[] args) throws Exception { XWPFDocument doc = new XWPFDocument(); XWPFParagraph p = doc.createParagraph(); XWPFRun r = p.createRun(); for(String imgFile : args) { int format; if(imgFile.endsWith(".emf")) format = XWPFDocument.PICTURE_TYPE_EMF; else if(imgFile.endsWith(".wmf")) format = XWPFDocument.PICTURE_TYPE_WMF; else if(imgFile.endsWith(".pict")) format = XWPFDocument.PICTURE_TYPE_PICT; else if(imgFile.endsWith(".jpeg") || imgFile.endsWith(".jpg")) format = XWPFDocument.PICTURE_TYPE_JPEG; else if(imgFile.endsWith(".png")) format = XWPFDocument.PICTURE_TYPE_PNG; else if(imgFile.endsWith(".dib")) format = XWPFDocument.PICTURE_TYPE_DIB; else if(imgFile.endsWith(".gif")) format = XWPFDocument.PICTURE_TYPE_GIF; else if(imgFile.endsWith(".tiff")) format = XWPFDocument.PICTURE_TYPE_TIFF; else if(imgFile.endsWith(".eps")) format = XWPFDocument.PICTURE_TYPE_EPS; else if(imgFile.endsWith(".bmp")) format = XWPFDocument.PICTURE_TYPE_BMP; else if(imgFile.endsWith(".wpg")) format = XWPFDocument.PICTURE_TYPE_WPG; else { System.err.println("Unsupported picture: " + imgFile + ". Expected emf|wmf|pict|jpeg|png|dib|gif|tiff|eps|bmp|wpg"); continue; } r.setText(imgFile); r.addBreak(); r.addPicture(new FileInputStream(imgFile), format, imgFile, Units.toEMU(200), Units.toEMU(200)); // 200x200 pixels r.addBreak(BreakType.PAGE); } FileOutputStream out = new FileOutputStream("images.docx"); doc.write(out); out.close(); }
PowerPoint
Anche con l’applicazione di presentazione Powerpoint, le POI Apache presentano due componenti:
- HSLF per gestire il vecchio formato .ppt e
- XSLF per il formato basato su XML introdotto a partire del 2007, vale a dire il .pptx.
HSLF e XSLF hanno caratteristiche simili, ma non c’è una interfaccia comune al momento anche perchè XSLF è in sviluppo da poco tempo.
L’implementazione Java HSLF permette di leggere, creare o modificare presentazioni PowerPoint in particolare con l’estrazione di dati (testo, immagini, oggetti incorporati e suoni) e le specifiche API per creare, leggere o modificare file .ppt.
HSLF: estrazione di base del testo
Per l’estrazione di testo, fare uso di org.apache.poi.hslf.extractor.PowerPointExtractor. Si accetta come input un file o un flusso di dati. Il metodo getText() può essere utilizzato per ottenere il testo da diapositive, mentre getNotes() può essere utilizzato per ottenere il testo dalle note. Infine, getText(true, true) otterrà il testo da entrambe.
HSLF: estrazione di testo specifico
Per ottenere del testo specifico, creare innanzitutto un org.apache.poi.hslf.usermodel.SlideShow da un org.apache.poi.hslf.HSLFSlideShow, che accetta un file o un flusso come input. Utilizzare poi getSlides() e getNotes() per ottenere le diapositive e le note. Queste possono essere interrogate per ottenere il loro ID di pagina, anche se dovrebbero essere restituite nel giusto ordine.
È quindi possibile chiamare getTextRuns() su questi, per ottenere i loro blocchi di testo. Una TextRun contiene normalmente tutto il testo in una determinata area della pagina, ad esempio nella barra del titolo. Dal TextRun è possibile estrarre il testo e verificare che tipo di testo è: corpo, titolo, etc. È possibile chiamare anche getRichTextRuns(), che restituirà i RichTextRuns che compongono il TextRun. Un RichTextRun è costituito da una sequenza di testo, avente tutto la stessa formattazione di carattere e paragrafo.
HSLF: estrazione di testo di scarsa qualità
Se la velocità è la cosa più importante e non è un problema ottenere testo “sporco”, ossia con duplicati, con parti di testo vecchio derivanti da sostituzioni e cancellature e con formattazione non ottimale, allora org.apache.poi.hslf.extractor.QuickButCruddyTextExtractor potrebbe fare al caso nostro.
QuickButCruddyTextExtractor non utilizza il normale codice di registrazione parsing, ma usa invece un metodo di ricerca cieca sulla struttura ad albero, per ottenere tutti i record di immissione di testo. Si otterrà tutto il testo in qualche modo contenuto nel file, e tra questo anche un sacco di testo “sporco” che normalmente non è quel che si cerca: però ciò accade in maniera molto veloce!
Ci sono due modi di ottenere il testo:
- getTextAsString() restituirà una singola stringa, con tutto il testo in essa;
- getTextAsVector() restituirà un vettore di stringhe, una per ogni record testo trovato nel file.
HSLF: modifica del testo
È possibile modificare il testo tramite TextRun.setText(String) o RichTextRun.setText(String). Non è ancora possibile aggiungere TextRuns o RichTextRuns supplementari. Quando si chiama TextRun.setText(String ), tutto il testo si concluderà con la stessa formattazione. Quando si chiama RichTextRun.setText(String), il testo mantiene la formattazione del vecchio che RichTextRun.
HSLF: aggiunta di diapositive
Si possono aggiungere nuove diapositive chiamando SlideShow.createSlide(), che aggiungerà una nuova diapositiva alla fine della presentazione. Non è attualmente possibile riordinare diapositive, nè aggiungere nuovo testo alle diapositive.
XSLF: creare una nuova presentazione
//crea una presentazione vuota XMLSlideShow ppt = new XMLSlideShow(); //aggiunge una slide XSLFSlide blankSlide = ppt.createSlide();
XSLF: leggere una presentazione esistente e aggiungere una slide
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("slideshow.pptx")); // Aggiungo slide alla fine
XSLF: creazione di una slide da un layout predefinito
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("slideshow.pptx")); // cerco i layout presenti: System.out.println("Available slide layouts:"); for(XSLFSlideMaster master : ppt.getSlideMasters()){ for(XSLFSlideLayout layout : master.getSlideLayouts()){ System.out.println(layout.getType()); } } // slide vuota XSLFSlide blankSlide = ppt.createSlide(); // a scopo dimostrativo usiamo la prima slide (default) XSLFSlideMaster defaultMaster = ppt.getSlideMasters()[0]; // titolo slide XSLFSlideLayout titleLayout = defaultMaster.getLayout(SlideLayout.TITLE); XSLFSlide slide1 = ppt.createSlide(titleLayout); XSLFTextShape title1 = slide1.getPlaceholder(0); title1.setText("First Title"); // titolo e contenuto XSLFSlideLayout titleBodyLayout = defaultMaster.getLayout(SlideLayout.TITLE_AND_CONTENT); XSLFSlide slide2 = ppt.createSlide(titleBodyLayout); XSLFTextShape title2 = slide2.getPlaceholder(0); title2.setText("Second Title"); XSLFTextShape body2 = slide2.getPlaceholder(1); body2.clearText(); // cancella testo esistente body2.addNewTextParagraph().addNewTextRun().setText("First paragraph"); body2.addNewTextParagraph().addNewTextRun().setText("Second paragraph"); body2.addNewTextParagraph().addNewTextRun().setText("Third paragraph");
XSLF: rimuovere una slide
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("slideshow.pptx")); ppt.removeSlide(0); // slide 0 rimossa
XSLF: riordinare slide
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("slideshow.pptx")); XSLFSlide[] slides = ppt.getSlides(); XSLFSlide thirdSlide = slides[2]; ppt.setSlideOrder(thirdSlide, 0); // sposta la terza slide all'inizio
XSLF: cambiare o recuperare dimensioni
XMLSlideShow ppt = new XMLSlideShow(); java.awt.Dimension pgsize = ppt.getPageSize(); int pgx = pgsize.width; int pgy = pgsize.height; //imposta nuove dimensioni ppt.setPageSize(new java.awt.Dimension(1024, 768));
XSLF: leggere le forme contenute in un particolare diapositiva
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("slideshow.pptx")); // ottiene slide XSLFSlide[] slide = ppt.getSlides(); for (int i = 0; i < slide.length; i++){ XSLFShape[] sh = slide[i].getShapes(); for (int j = 0; j < sh.length; j++){ //nome della forma String name = sh[j].getShapeName(); // definisce l'ancoraggio anchor che // stabilisce la posizione della forma nella slide java.awt.geom.Rectangle2D anchor = sh[j].getAnchor(); if (sh[j] instanceof XSLFConnectorShape){ XSLFConnectorShape line = (XSLFConnectorShape)sh[j]; // lavora con le linee } else if (sh[j] instanceof XSLFTextShape){ XSLFTextShape shape = (XSLFTextShape)sh[j]; // lavora con le forme che non hanno testo } else if (sh[j] instanceof XSLFPictureShape){ XSLFPictureShape shape = (XSLFPictureShape)sh[j]; // lavora con le immagini } } }
XSLF: aggiungere un imagine ad una slide
XMLSlideShow ppt = new XMLSlideShow(); XSLFSlide slide = ppt.createSlide(); byte[] pictureData = IOUtils.toByteArray(new FileInputStream("image.png")); int idx = ppt.addPicture(pictureData, XSLFPictureData.PICTURE_TYPE_PNG); XSLFPictureShape pic = slide.createPicture(idx);
XSLF: leggere immagini contenute in una presentazione
XMLSlideShow ppt = new XMLSlideShow(new FileInputStream("slideshow.pptx")); for(XSLFPictureData data : ppt.getAllPictures()){ byte[] bytes = data.getData(); String fileName = data.getFileName(); }
XSLF: formattazione del testo
XMLSlideShow ppt = new XMLSlideShow(); XSLFSlide slide = ppt.createSlide(); XSLFTextBox shape = slide.createTextBox(); XSLFTextParagraph p = shape.addNewTextParagraph(); XSLFTextRun r1 = p.addNewTextRun(); r1.setText("The"); r1.setFontColor(Color.blue); r1.setFontSize(24); XSLFTextRun r2 = p.addNewTextRun(); r2.setText(" quick"); r2.setFontColor(Color.red); r2.setBold(true); XSLFTextRun r3 = p.addNewTextRun(); r3.setText(" brown"); r3.setFontSize(12); r3.setItalic(true); r3.setStrikethrough(true); XSLFTextRun r4 = p.addNewTextRun(); r4.setText(" fox"); r4.setUnderline(true);
XSLF: leggere un collegamento ipertestuale da una slide
XMLSlideShow ppt = new XMLSlideShow(); XSLFSlide slide = ppt.createSlide(); // assegna un collegamento ipertestuale a text run XSLFTextBox shape = slide.createTextBox(); XSLFTextRun r = shape.addNewTextParagraph().addNewTextRun(); r.setText("Apache POI"); XSLFHyperlink link = r.createHyperlink(); link.setAddress("http://poi.apache.org");
Conclusioni
Le API Java POI hanno una loro importanza, vista la diffusione degli applicativi Microsoft Office, e devono stare nel bagaglio di ogni buon programmatore. Alcune di esse, per quanto valide, non sono ancora complete (come nel caso di Word o Powerpoint), mentre altre sono proprio alle prime fasi di sviluppo (come quelle per Outlook e Visio): in ogni caso ci permettono di fare quello che è necessario per lo sviluppo di applicazioni che fanno reportistica. Confidiamo comunque che il progetto vada avanti e che certe funzionalità si aggiungano presto: rimandiamo pertanto alla documentazione ufficiale per gli aggiornamenti e gli approfondimenti.
Yuri Cervoni si è laureato alla facoltà di Ingegneria Informatica dell’Università “La Sapienza” di Roma nel maggio 2009 con la tesi: “Implementazione e realizzazione di un metodo per l’animazione dell’algoritmo di Dijkstra”. Dall’Aprile 2009, prima come stagista e poi come sviluppatore software, lavora nella Società degli Studi di Settore. Nel tempo libero cerca di ampliare le sue conoscenze informatiche partecipando a progetti software presenti su SourceForge.net come “FlaQuizTV” e la documentazione italiana di “Argo UML”.