In questo articolo vedremo come creare un documento Word e come successivamente possiamo leggerlo, tramite la libreria Apache POI. Purtroppo le API non sono complete come per la versione Excel e non esistono interfacce Wrapper per entrambe le versioni HWPF e XWPF, in poche parole dovremo usare due classi distinte se vogliamo creare e/o leggere un file di tipo .doc o di tipo .docx e, ancora peggio, il loro utilizzo è piuttosto differente.
In questo articolo vedremo come creare un documento Word e come successivamente possiamo leggerlo, tramite la libreria Apache POI. Purtroppo le API non sono complete come per la versione Excel e non esistono interfacce Wrapper per entrambe le versioni HWPF e XWPF, in poche parole dovremo usare due classi distinte se vogliamo creare e/o leggere un file di tipo .doc o di tipo .docx e, ancora peggio, il loro utilizzo è piuttosto differente.
Prima di vedere qualche esempio, elenchiamo le dipendenze della libreria POI:
Componente | Tipo Applicazione | Id Artefatto Maven |
---|---|---|
POIFS | OLE2 Filesystem | poi |
HPSF | OLE2 Property Sets | poi |
HSSF | Excel XLS | poi |
HSLF | PowerPoint PPT | poi-scratchpad |
HWPF | Word DOC | poi-scratchpad |
HDGF | Visio VSD | poi-scratchpad |
HPBF | Publisher PUB | poi-scratchpad |
HSMF | Outlook MSG | poi-scratchpad |
XSSF | Excel XLSX | poi-ooxml |
XSLF | PowerPoint PPTX | poi-ooxml |
XWPF | Word DOCX | poi-ooxml |
OpenXML4J | OOXML | poi-ooxml-schemas, ooxml-schemas |
Nella tabella precedente troviamo nella prima colonna il nome del Componente della libreria Apche POI, nella seconda colonna il Tipo di Applicazione per cui viene utilizzato ed infine nella terza colonna l’Id dell’Artefatto Maven che lo implementa.
Id Artefatto Maven | Prerequisiti | JAR |
---|---|---|
poi | commons-logging, log4j | poi-version-yyyymmdd.jar |
poi-scratchpad | poi | poi-scratchpad-version-yyyymmdd.jar |
poi-ooxml | poi, poi-ooxml-schemas, dom4j | poi-ooxml-version-yyyymmdd.jar |
poi-ooxml-schemas (*) | xmlbeans, stax-api-1.0.1 | poi-ooxml-schemas-version-yyyymmdd.jar |
poi-examples (*) | poi, poi-scratchpad, poi-ooxml | poi-examples-version-yyyymmdd.jar |
ooxml-schemas | xmlbeans, stax-api-1.0.1 | ooxml-schemas-1.1.jar |
(*) a partire dalla 3.6-beta1-20091124.
In questa ultima tabella vediamo nella seconda colonna i prerequisiti per i vari Artifatti Maven ed il corrispondente jar (che troviamo incluso nel download della libreria Apache POI).
Facciamo un esempio: se dovessimo usare il componente HWPF (documenti .doc) dovremmo includere nel nostro classpath i jar commons-logging e log4j ed utilizzare la libreria poi-scratchpad-version-yyyymmdd.jar e poi-version-yyyymmdd.jar; se invece volessimo utilizzare il componente XWPF (documenti .docx) dovremmo includere oltre alle librerie precedenti, i jar xmlbeans, stax-api-1.0.1, dom4j, poi-ooxml-version-yyyymmdd.jar e poi-ooxml-schemas-version-yyyymmdd.jar.
Nel caso in cui usiamo Eclipse come IDE di sviluppo dobbiamo includere tali librerie nel Build Path del Progetto Java.
Facciamo ora qualche esempio prima con le API del componente HWPF. La prima cosa da fare è aprire un file .doc in quanto non è possibile crearne uno da programma (il costruttore HWPFDocument() è di tipo protected:
String nomefile = "test.doc"; POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream(nomefile)); HWPFDocument doc = new HWPFDocument(fs);
per poter modificare il testo contenuto nel documento word dobbiamo avere una istanza della classe Range che rappresenta l’insieme di testo all’interno del file .doc, possiamo poi prendere i vari elementi quali i Paragrafi direttamente da esso. Per ottenere il Range utilizziamo il metodo getRange():
Range range = doc.getRange(); range.insertAfter("Hello World!!");
con i metodi insertBefore e insertAfter possiamo aggiungere del testo prima e dopo del Range. Dal Range possiamo poi ottenere i Paragrafi e i CharacterRuns (insieme di testo che condivide le stesse proprietà).
Un metodo più efficace di estrarre il testo è istanziando una calsse di tipo WordExtractor:
WordExtractor we = new WordExtractor(doc); String[] paragrafi = we.getParagraphText(); System.out.println( "Il documento Word ha " + paragrafi.length + " paragrafi" ); for( int i=0; iparagrafi[i] = paragrafi[i].replaceAll("\cM?r?n",""); System.out.println( "Testo: "+paragrafi[ i ]); System.out.println( "Lunghezza: "+paragrafi[ i ].length()); }
Con il codice su riportato estraiamo i paragrafi dal doc e li inseriamo in un array di stringhe (una stringa per ogni paragrafo) e poi iteriamo stampando a video lunghezza e contenuto. Possiamo anche utilizzare più semplicemente il metodo getText() di WordExtractor per ottenere tutto il testo del doc.
Utilizzando invece la classe XWPFDocument (per file .docx) non abbiamo bisogno di un file preesistente, ma possiamo scriverne uno alla fine delle nostre manipolazioni.
Proviamo a creare dei paragrafi, utilizzando stili e allineamenti diversi, creiamo inoltre all’interno dei paragrafi, degli XWPFRun che sono porzioni di testo che condividono lo stesso stile e formato:
package it.appuntisoftware; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import org.apache.poi.xwpf.usermodel.Borders; import org.apache.poi.xwpf.usermodel.ParagraphAlignment; import org.apache.poi.xwpf.usermodel.VerticalAlign; import org.apache.poi.xwpf.usermodel.XWPFDocument; import org.apache.poi.xwpf.usermodel.XWPFParagraph; import org.apache.poi.xwpf.usermodel.XWPFRun; public class TestWordPOI { public static void main(String[] args) { String filename = "text.docx"; XWPFDocument document = new XWPFDocument(); XWPFParagraph paragrafoUno = document.createParagraph(); paragrafoUno.setAlignment(ParagraphAlignment.CENTER); paragrafoUno.setBorderBottom(Borders.SINGLE); paragrafoUno.setBorderTop(Borders.SINGLE); paragrafoUno.setBorderRight(Borders.SINGLE); paragrafoUno.setBorderLeft(Borders.SINGLE); paragrafoUno.setBorderBetween(Borders.SINGLE); XWPFRun paragrafoUnoRunUno = paragrafoUno.createRun(); paragrafoUnoRunUno.setBold(true); paragrafoUnoRunUno.setItalic(true); paragrafoUnoRunUno.setText("Hello world! Questo è il paragrafo Uno, Run Uno!"); paragrafoUnoRunUno.addBreak(); XWPFRun paragrafoUnoRunDue = paragrafoUno.createRun(); paragrafoUnoRunDue.setText("Secondo Run!"); paragrafoUnoRunDue.setTextPosition(100); XWPFRun paragrafoUnoRunTre = paragrafoUno.createRun(); paragrafoUnoRunTre.setStrike(true); paragrafoUnoRunTre.setFontSize(20); paragrafoUnoRunTre.setSubscript(VerticalAlign.SUBSCRIPT); paragrafoUnoRunTre.setText(" Ancora paragrafo Uno..."); XWPFParagraph paragrafoDue = document.createParagraph(); paragrafoDue.setAlignment(ParagraphAlignment.DISTRIBUTE); paragrafoDue.setIndentationRight(200); XWPFRun paragraphTwoRunOne = paragrafoDue.createRun(); paragraphTwoRunOne.setText("Questo è il paragrafo due!"); FileOutputStream outStream = null; try { outStream = new FileOutputStream(filename); document.write(outStream); outStream.close(); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }
Possiamo inoltre creare e riempire delle tabelle di testo:
XWPFDocument document = new XWPFDocument(); int righe = 5, colonne = 5; XWPFTable table = document.createTable(righe , colonne); for(int i=0; i< righe; i++) for(int j=0; j< colonne; j++) table.getRow(i).getCell(j).addParagraph().createRun() .setText("cella: ["+i+"]["+j+"]" );
COMMENTS
l’esempio è chiaro ma per renderlo realmente utile va corredato delle opportune “import”.
secondariamente, mi chiedo come mai un sito che rende disponibili tante informazioni non disponga di una pur minima interfaccia di ricerca.
ho aggiunto gli import all’esempio, era uno dei miei primi post quindi leggermente incompleto, per quanto riguarda la ricerca la trovi in alto a destra sotto i tasti di condivisione di facebook, twitter, ect…
grazie per la segnalazione
Quando cerco di eseguire il suo esempio mi esce questo errore
Exception in thread “main” java.lang.NoClassDefFoundError: org/apache/xmlbeans/XmlException
at EstraiFileDoc.metodoXWPF(EstraiFileDoc.java:43)
at EstraiFileDoc.main(EstraiFileDoc.java:37)
Caused by: java.lang.ClassNotFoundException: org.apache.xmlbeans.XmlException
at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:301)
at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
… 2 more
Il file .doc l’ho creato in una cartella “files”
Non riesco proprio a capire il problema
Ringrazio anticpatamente
ciao, l’errore è risolvibile se aggiungi al classpath il jar xmlbeans-version.jar, che dovresti trovare nel pacchetto zip dei binari della versione della libreria POI che hai scaricato.
Se usi Eclipse devi aggiungere la suddetta libreria al Build Path.
Vi sono poi altre dipendenze in base alla classe specifica che stai utilizzando per i tuoi esempi, a questo punto aggiungo all’articolo l’elenco delle dipendenze in base alle classi che si utilizzano.
ciao e grazie per aver letto l’articolo.
Ciao sto provando a compilare la prima parte del programma ma mi dice che non trova il metodo insertAfter della riga range.insertAfter(“Hello World!!”);
Ho aggiunto tutti i jar che ho scaricato…magari sono sbagliati…sai dirmi quello giusto???
Ciao Andrea,
per compilare un progetto Java che fa uso del componente HWPF di Apache POI devi avere necessariamente incluso nel Build Path del tuo progetto i seguenti jar:
commons-logging
log4j
poi-version-yyyymmdd.jar
poi-scratchpad-version-yyyymmdd.jar
proprio in questo ultimo jar è definita la classe Range e probabilmente è questo jar che ti manca.
Ciao. So che è una domanda banalissima, sono però nuova di java e netbeans.
Volevo chiederti come faccio a far sì che il codice che hai postato funzioni sul mio computer, cioè non so aggiungere librerie esterne. Ho scaricato i due file .zip, quello bin e src, e messi nella cartella del mio progetto, ma ora cosa devo fare affinchè Netbeans li veda?
Grazie e scusa la banalità.
Ciao, nel tutorial utilizzo Eclipse e per aggiungere librerie esterne basta fare click col tasto destro sul progetto e scegliere Configure Build Path…
Per quanto riguarda Netbeans devi cliccare col destro sul progetto e selezionare la voce Properties, da questa poi devi andare su Libriaries e qui trovi la lista delle librerie disponibili, prima però devi importare la libreria in Netbeans, potresti vedere su questo sito come si fa:
http://www.oracledistilled.com/netbeans/adding-java-libraries-to-netbeans-6-9/
grazie per aver letto il tutorial
Ciao
bello il tutorial funziona tutto ma ho due domande da fare.
come faccio a posizionarmi in una certa posizione del documento word e poi inserire un testo o una tabella, va bene sia un doc che un docx
In pratica in un modello di partenza metto una parola chiave e dopo di essa devo inserire un testo.
In alternativa posso fare un cerca sul documento e rimanere posizionato
in quella posizione per fare operazioni diverse.
grazie
salvatore