API per applicazioni

II parte: Interagire con le applicazioni MS Office grazie ad Apache POIdi

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.

 

 

Riferimenti

[1] Il progetto POI descritto su Wikipedia

http://en.wikipedia.org/wiki/Apache_POI

 

[2] Il sito ufficiale di Apache POI, in cui è possibile consultare l'intera documentazione

http://poi.apache.org/

Condividi

Pubblicato nel numero
202 gennaio 2015
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…
Articoli nella stessa serie
Ti potrebbe interessare anche