Nessun risultato. Prova con un altro termine.
Guide
Notizie
Software
Tutorial

PDF-Writer: scrivere file PDF con Ruby

Generare PDF con Ruby e una classe di utilità per creare e salvare velocemente i documenti
Generare PDF con Ruby e una classe di utilità per creare e salvare velocemente i documenti
Link copiato negli appunti

PDF è un ottimo formato per condividere documenti e i motivi sono noti: un documento PDF appare sullo schermo esattamente come apparirebbe su un foglio di carta, è compatto, può contenere link e possiamo facilmente inviarlo via email.

Il PDF è inoltre riconosciuto per l'alto grado di trasportabilità sui piú svariati dispositivi, anche architetturalmente diversi. Un PDF risulta leggibile allo stesso modo su PC, MAC e dispositivi mobili. La sola cosa necessaria é l'installazione di un reader (Adobe Reader, xPDF, eVince ed altri).

In questo articolo vedremo come creare documenti PDF con Ruby utilizzando la gemma PDF-Writer. Questa gem non richiede dipendenze esterne come html2ps e ghostscript. PDF-Writer ci fornisce una serie di metodi per mostrare testi, immagini, tabelle e grafici

Installare la gem

Il modo più semplice per ottenere PDF-Writer è usare RubyGems che provvederà anche a risolvere le dipendenze.

gem install pdf-writer

Nota: nel caso in cui si voglia installare la libreria a partire dai sorgenti, è necessario installare altre due gemme: transaction-simple e color-tools.

Per utilizzare la gem possiamo includerla nel nostro sorgente con require 'rubygems' oppure impostare la variabile d'ambiente RUBYOPT per includere rubygems.

Esempi d'uso

È arrivato il momento di scrivere il nostro primo esempio. Creeremo un semplice file PDF stile "Hello World" impostando il tipo di font da utlizzare, la sua dimensione, la giustificazione del testo e lo salveremo in una directory da noi scelta.

Listato 1. Esempio "HelloWorld-like"

require 'rubygems'
require 'pdf/writer'
    
pdf = PDF::Writer.new
pdf.select_font("Helvetica")
pdf.text("Hello Ruby.HTML.it", 72, :justification => center)
pdf.save_as("../output/example.pdf")

Ci sono 14 font disponibili per ogni lettore PDF. Possiamo fare riferimento alla documentazione ufficiale (ben fatta) per la lista completa.

Risulta possibile specificare il tipo di codifica da usare per il testo. Il formato PDF standard usa come codifiche "none", "WinAnsiEncoding", "MacRomanEncoding" o "MacExpertEncoding". Come default PDF-Writer usa "WinAnsiEncoding". Possiamo anche inserire una mappa di differenze tra le codifiche in questo modo:

Listato 2. Impostazione della specifica e mapping di caratteri

encoding = {
  :encoding => "WinAnsiEncoding",
  :differences => {
    215 => "multiply", # mappa il byte 215 con il carattere "x"
    148 => "copyright" 
  }
}
     
pdf.select_font("Times-Roman", encoding)

Esiste un modo alternativo di creare un documento PDF in cui si specificano anche i margini sinistro, destro, alto e basso) e questo avviene tramite il metodo

Listato 3. Specificare i margini della pagina

options = {
  :left_margin => 50, :right_margin => 50, 
  :top_margin => 100, :bottom_margin => 100,
  :bleed_size => 24, #default 12 points
  :mark_length => 36 #default 18 points
}

PDF::Writer.prepress(options) do |i| 
  i.text(
    <<-EOS
    "Pezzi di arte locativa esposti in uno spazio elettronico che trascende i nostri sensi naturali. 
    Una rivista dedicata alle nuove tendenze, che nessuno ha ancora mai visto ma che vorrebbe imporsi come 
    l'equivalente europeo di 'Wired'. Lingue artificiali figlie della rivoluzione informatica. 
    (tratto da 'Con Gibson, nel Paese delle Spie', http://www.next-station.org)"
    EOS )
  i.save_as("prepress.pdf")
end

Se vogliamo il nostro testo posizionato con coordinate specifiche possiamo usare uno dei due seguenti metodi

# assicurarsi che il testo rientri nella dimensione width
# se size non viene specificato si fa riferimento a quanto impostato con select_font
# angle è misurato in gradi ed in senso orario
# test = true il testo non sarà scritto ma verra restiruito dal metodo
PDF::Writer.add_text_wrap(x, y, width, text, size = nil, justification = :left, angle = 0, test = false)  
PDF::Writer.add_text(x, y, text, size = nil, angle = 0, word_space_adjust = 0)

Vediamo ora come inserire delle immagini all'interno del nostro documento. I formati supportati dalla libreria sono JPEG e PNG, anche se quest'ultimo presenta delle limitazioni su alcune caratteristiche del formato.

Listato 4. Inserimento di immagini

pdf = PDF::Writer.new
pdf.image(filename, :justification => :center, :resize => 2.20)
pdf.save_as("image_file.pdf")

Passiamo ora ad analizzare il modo con cui è possibile creare tabelle con PDF-Writer. Abbiamo a disposizione la classe PDF::SimpleTable il cui utilizzo é molto semplice, ma che prevede numerose configurazioni.

Listato 5. Creazione tabelle

require 'rubygems'
require 'pdf/writer'
require 'pdf/simpletable'
    
pdf_document = PDF::Writer.new
pdf_document.select_font("Helvetica")
    
table_data = []
    
table_data << { "Nome" => "Mario", "Cognome" => "Rossi", "Eta" => 45 }  
table_data << { "Nome" => "Carlo", "Cognome" => "Bianchi", "Eta" => 54 }

table = PDF::SimpleTable.new
table.title = "tabella di prova"
table.position = :left
table.orientation = 50
    
table.data = table_data
table.column_order = ["Nome", "Cognome", "Età"]
table.render_on(pdf_document)
    
pdf_document.save_as("table.pdf")

Esempio finale

Riuniamo quanto detto finora creando una classe wrapper di utilità per la creazione di documenti PDF.

Listato 6. Creare la classe PdfDocument

require 'rubygems'
require 'pdf/writer'
require 'pdf/simpletable'

class PdfDocument
  attr_accessor :pdf

  def initialize(paper, orientation = :landscape)
    # paper imposta le dimensioni della pagina.
    # Possiamo specificare un formato standard(A4, A5, A3, C1...) oppure specificare le dimensioni in centimetri
    # o ancora il lower left-hand corner e l'upper right-hand corner [x0, y0, x1, y1]
    # orientation =>[:landscape, :portrait]
    @pdf  = PDF::Writer.new(:paper => paper, :orientation => orientation)

    # impostiamo i margini con un unico metodo
    # oppure chiamiamo i metodi top_margin, bottom_margin...
    @pdf.margins_pt(10,10, 15, 15)
  end

  def set_font(font, encoding = nil)
    @pdf.select_font(font, encoding)
  end

  def set_text(text, fontsize = 12, justification = :center)
    @pdf.text(text, :font_size=> fontsize, :justification => justification)
  end

  def new_page(force = true)
    @pdf.start_new_page(force)
  end

  def new_page_numbering
    @pdf.start_page_numbering(1100, 20, 10, :center)
  end
  
  def insert_image(filename, just, scale)
    pdf.image(filename, :justification => just, :resize => scale)
  end
  
  def insert_table(mytable)
    table = PDF::SimpleTable.new
    table.title_font_size = 22
    table.title_gap = 15 # distanza tra il titolo  e la tabella
    table.heading_font_size = 18
    table.bold_headings = true
    table.font_size = 16
    table.row_gap = 4
    
    table.shade_color = Color::RGB::Grey90 # oppure table.shade_rows = :shaded
    
    table.show_lines = :all
    table.show_headings = true
    table.position = :center
    table.orientation = :center
    
    table.data = mytable[:table_data]
    table.column_order = mytable[:table_column]
    table.title = mytable[:table_title]
    table.render_on(@pdf )
  end
  
  def save_as(filename)
    @pdf.save_as(filename)
    puts "=== scrittura di #{filename} completata ==="
  end
end


mytable = {
  :table_column => ["Categoria", "Titolo", "Autore", "Data"],
  :table_title => "Lista degli Articoli",
  :table_data => [
  
    {"Categoria" => "Programmazione Ruby", "Titolo" => "Creare file XML con Ruby", "Autore" => "Simone Carletti", "Data" => "08.07..2008" },
    {"Categoria" => "Programmazione Ruby", "Titolo" => "Espressioni regolari con Ruby e Oniguruma", "Autore" => "Sandro Paganotti", "Data" => "01.07.2008" }, 
    {"Categoria" => "Rails", "Titolo" => "Capistrano: il deployment Rails diventa facile", "Autore" => "Calogero Lo Leggio", "Data" => "27.05.2008" },
    {"Categoria" => "Rails", "Titolo" => "Non solo Rails: costruire un blog con Merb", "Autore" => "Carlo Pecchia", "Data" => "10.06.2008" },  
    {"Categoria" => "Rails", "Titolo" => "ActiveRecord - un ORM per Ruby", "Autore" => "Mirco Veltri", "Data" => "13.05.2008" }
  ]
}

mydoc = PdfDocument.new("A4")
mydoc.new_page_numbering
mydoc.set_font("Helvetica")
mydoc.insert_image("../images/logo.png",:center, 2.20)
mydoc.set_text("Hello Ruby.HTML.it", 72)
mydoc.new_page(true)
mydoc.set_text(":pdf => 'Testing new page method' ", 36)
mydoc.new_page(true)
mydoc.insert_table(mytable)
mydoc.save_as("../output/example.pdf")

Ti consigliamo anche