martedì 26 giugno 2012

Come creare PDF con Java e iText

Introduzione

iText è una libreria Java originariamente creata da Bruno Lowagie che permette di creare, leggere e manipolare PDF.
Il tutorial che segue spiegherà come creare file PDF con iText. Si richiede che il lettore conosca le basi di Java e di Eclipse.

iText ha una struttura gerarchica. L'unità di testo più piccola è il "Chunk", di cui è possibile specificare il font. La "Phrase" è l'insieme di più "Chunk" e permette di definire lo spazio tra le linee di testo. "Paragraph" è una sottoclasse di "Phrase" e permette di definire maggiori attributi, come i margini. La classe "Anchor" è una sottoclasse di "Paragraph" e permette di creare collegamenti ipertestuali nel PDF generato.

Installazione

Scaricare iText da http://sourceforge.net/projects/itext/. In Eclipse creare un nuovo progetto Java e chiamarlo "iTextTest". Creare all'interno del progetto la cartella "lib" e aggiungere al suo interno il file itextpdf-5.3.0.jar (il numero di versione potrebbe essere diverso) contenuto nell'archivio scaricato, quindi aggiungere la libreria al classpath del proprio progetto.

Creare un PDF

Creare la classe che segue. Il codice dovrebbe essere abbastanza comprensibile grazie ai commenti inseriti. Per esempi più complessi si rimanda al sito ufficiale di iText.

import java.io.FileOutputStream;
import java.util.Date;

import com.itextpdf.text.Anchor;
import com.itextpdf.text.BadElementException;
import com.itextpdf.text.BaseColor;
import com.itextpdf.text.Chapter;
import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Element;
import com.itextpdf.text.Font;
import com.itextpdf.text.List;
import com.itextpdf.text.ListItem;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.Phrase;
import com.itextpdf.text.Section;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;


public class Test {
 private static String FILE = "C:/Test.pdf";
 private static Font bigFont  = new Font(Font.FontFamily.TIMES_ROMAN, 18,  Font.BOLD);
 private static Font redFont  = new Font(Font.FontFamily.TIMES_ROMAN, 12,  Font.NORMAL, BaseColor.RED);
 private static Font subFont  = new Font(Font.FontFamily.TIMES_ROMAN, 16,  Font.BOLD);
 private static Font smallBold  = new Font(Font.FontFamily.TIMES_ROMAN, 12,  Font.BOLD);

 public static void main(String[] args) {
  try {
   Document document = new Document();
   PdfWriter.getInstance(document, new FileOutputStream(FILE));
   document.open();
   aggiungiMetaDati(document);
   aggiungiPrefazione(document);
   aggiungiContenuto(document);
   document.close();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }
 
 /* iText permette di aggiungere metadati al pdf che possono essere 
  * visualizzati in Adobe Reader da File -> Proprietà */
 private static void aggiungiMetaDati(Document document) {
  document.addTitle("Il mio primo PDF");
  document.addSubject("Uso di iText");
  document.addKeywords("Java, PDF, iText");
  document.addAuthor("Mario Rossi");
  document.addCreator("Luigi Bianchi");
 }

 private static void aggiungiPrefazione(Document document) throws DocumentException {
  Paragraph prefazione = new Paragraph();
  
  // Aggiungiamo una linea vuota
  aggiungiLineaVuota(prefazione, 1);
  
  // Aggiungiamo il titolo
  prefazione.add(new Paragraph("Titolo del documento", bigFont));

  aggiungiLineaVuota(prefazione, 1);
  
  // Questa linea scrive "Documento generato da: nome utente, data"
  prefazione.add(new Paragraph("Documento generato da: " + System.getProperty("user.name") + ", " + new Date(), smallBold));
  
  aggiungiLineaVuota(prefazione, 3);
  
  prefazione.add(new Paragraph("Generato da iText", smallBold));

  aggiungiLineaVuota(prefazione, 3);
  
  prefazione.add(new Paragraph("Generato da iText", redFont));

  aggiungiLineaVuota(prefazione, 3);
  
  Anchor anchor = new Anchor("Questo è un link");
  anchor.setName("LINK");
  anchor.setReference("http://www.lowagie.com");
  prefazione.add(anchor);

  // Aggiunta al documento
  document.add(prefazione);
  
  // Nuova pagina
  document.newPage();
 }

 private static void aggiungiContenuto(Document document) throws DocumentException {

  // Il secondo parametro è il numero di capitolo
  Chapter chapter = new Chapter(new Paragraph("Primo Capitolo", bigFont), 1);

  Paragraph sectionParagraph = new Paragraph("Sezione 1", subFont);
  Section section = chapter.addSection(sectionParagraph);
  section.add(new Paragraph("Paragrafo 1"));

  sectionParagraph = new Paragraph("Sezione 2", subFont);
  section = chapter.addSection(sectionParagraph);
  section.add(new Paragraph("Paragrafo 1"));
  section.add(new Paragraph("Paragrafo 2"));
  section.add(new Paragraph("Paragrafo 3"));

  // Aggiungiamo una lista
  creaLista(section);
  
  Paragraph paragraph = new Paragraph();
  aggiungiLineaVuota(paragraph, 2);
  section.add(paragraph);

  // Aggiungiamo una tabella
  creaTabella(section);

  // Aggiunta al documento
  document.add(chapter);

  // Prossimo capitolo

  // Il secondo parametro è il numero di capitolo
  chapter = new Chapter(new Paragraph("Secondo Capitolo", bigFont), 2);

  sectionParagraph = new Paragraph("Sezione 1", subFont);
  section = chapter.addSection(sectionParagraph);
  section.add(new Paragraph("Paragrafo 1"));

  // Aggiunta al documento
  document.add(chapter);
 }

 private static void creaTabella(Section section) throws BadElementException {
  PdfPTable tabella = new PdfPTable(3);

  // tabella.setBorderColor(BaseColor.GRAY);
  // tabella.setPadding(4);
  // tabella.setSpacing(4);
  // tabella.setBorderWidth(1);

  PdfPCell c1 = new PdfPCell(new Phrase("Titolo 1"));
  c1.setHorizontalAlignment(Element.ALIGN_CENTER);
  c1.setGrayFill(0.8f);
  tabella.addCell(c1);

  c1 = new PdfPCell(new Phrase("Titolo 2"));
  c1.setHorizontalAlignment(Element.ALIGN_CENTER);
  c1.setGrayFill(0.8f);
  tabella.addCell(c1);

  c1 = new PdfPCell(new Phrase("Titolo 3"));
  c1.setHorizontalAlignment(Element.ALIGN_CENTER);
  c1.setGrayFill(0.8f);
  tabella.addCell(c1);
  tabella.setHeaderRows(1);

  tabella.addCell("1.0");
  tabella.addCell("1.1");
  tabella.addCell("1.2");
  tabella.addCell("2.1");
  tabella.addCell("2.2");
  tabella.addCell("2.3");

  section.add(tabella);

 }

 private static void creaLista(Section section) {
  List list = new List(true, false, 10);
  list.add(new ListItem("Punto primo"));
  list.add(new ListItem("Punto secondo"));
  list.add(new ListItem("Punto terzo"));
  section.add(list);
 }

 private static void aggiungiLineaVuota(Paragraph paragraph, int number) {
  for (int i = 0; i < number; i++) {
   paragraph.add(new Paragraph(" "));
  }
 }
}


Formattare il testo

La classe Paragraph permette di specificare l'allineamento e l'indentazione. Per questo esempio creare il file Test2.java come segue:

import java.io.FileOutputStream;

import com.itextpdf.text.Document;
import com.itextpdf.text.Element;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfWriter;

public class Test2 {
 private static String FILE = "C:/Test2.pdf";

 public static void main(String[] args) {
  try {
   Document document = new Document();
   PdfWriter.getInstance(document, new FileOutputStream(FILE));
   document.open();
   // Destra
   Paragraph paragraph = new Paragraph("Questo paragrafo è allineato a destra");
   paragraph.setAlignment(Element.ALIGN_RIGHT);
   document.add(paragraph);
   // Centro
   paragraph = new Paragraph("Questo paragrafo è centrato");
   paragraph.setAlignment(Element.ALIGN_CENTER);
   document.add(paragraph);
   // Sinistra
   paragraph = new Paragraph("Questo paragrafo è allineato a sinistra");
   paragraph.setAlignment(Element.ALIGN_LEFT);
   document.add(paragraph);
   // Sinistra con indentazione
   paragraph = new Paragraph("Questo paragrafo è allineato a sinistra con indentazione");
   paragraph.setAlignment(Element.ALIGN_LEFT);
   paragraph.setIndentationLeft(50);
   document.add(paragraph);

   document.close();
  } catch (Exception e) {
   e.printStackTrace();
  }
 }

}


Leggere un PDF esistente

iText permette di generare PDF che includono PDF già esistenti. L'esempio che segue creerà un PDF che contiene la pagina 2 del primo esempio (Test.pdf) e in più aggiungerà del contenuto in una seconda pagina.

import java.io.FileOutputStream;
import java.io.IOException;

import com.itextpdf.text.Document;
import com.itextpdf.text.DocumentException;
import com.itextpdf.text.Image;
import com.itextpdf.text.Paragraph;
import com.itextpdf.text.pdf.PdfImportedPage;
import com.itextpdf.text.pdf.PdfReader;
import com.itextpdf.text.pdf.PdfWriter;

public class Test3 {
 private static String INPUTFILE  = "C:/Test.pdf";
 private static String OUTPUTFILE  = "C:/Test3.pdf";

 public static void main(String[] args) throws DocumentException, IOException {
  Document document = new Document();

  PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(OUTPUTFILE));
  document.open();
  PdfReader reader = new PdfReader(INPUTFILE);
  
  //Aggiunta pagina 2
  PdfImportedPage page = writer.getImportedPage(reader, 2);
  Image instance = Image.getInstance(page);
  document.add(instance);
  
  //Inserimento di contenuto aggiuntivo
  Paragraph newParagraph = new Paragraph("Contenuto aggiuntivo");
  document.add(newParagraph);
  
  document.close();

 }

}


Sorgenti dell'esempio

È possibile scaricare il progetto Eclipse contenente i sorgenti di questi esempi da questo link.

Grazie e spero questa piccola guida torni utile.

3 commenti:

  1. Grazie molto utili gli esempi.
    Nell'ultimo esempio viene mostrato come si può aggiungere un immagine a una pagina. Se quell'immagine ora volessi rimuoverla? Mi aspetterei anche che la dimensione del file si riduca è corretto?

    Grazie

    RispondiElimina
  2. Ottima guida !!!
    Per creare un testo su 2 colonne (e mettere una parte di tabella a sinistra, una a destra, come se fosse fatto su word) come si fa ?

    RispondiElimina
  3. qualcuno potrebbe gentilmente dirmi come fare ad aprire il file pdf dell'esempio sopra mostrato, dopo averlo modificato, semplicemente eseguendo la classe in ambiente eclipse? Servono delle librerie particolari per far ciò?

    RispondiElimina