The Artima Developer Community
Sponsored Link

Ruby Code & Style
Creating Printable Documents with Ruby
by Austin Ziegler
October 10, 2005

<<  Page 4 of 4

Advertisement

Tables

Tables in PDF::Writer are achieved with the PDF::SimpleTable class, so called because it has a relatively simple table model with more constraints on how the table can be rendered than the table model in HTML or XHTML. The table model itself is simple, but there are a number of configuration options that affect the display of the table. The following code demonstrates part of what is possible with PDF::SimpleTable.

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

      pdf = PDF::Writer.new
      pdf.select_font("Helvetica")

      PDF::SimpleTable.new do |tab|
        tab.title = "PDF User Unit Conversions"
        tab.column_order.push(*%w(from1 to1 from2 to2))

        tab.columns["from1"] = PDF::SimpleTable::Column.new("from1") { |col|
          col.heading = "From"
        }
        tab.columns["to1"] = PDF::SimpleTable::Column.new("to1") { |col|
          col.heading = "To"
        }
        tab.columns["from2"] = PDF::SimpleTable::Column.new("from2") { |col|
          col.heading = "From"
        }
        tab.columns["to2"] = PDF::SimpleTable::Column.new("to2") { |col|
          col.heading = "To"
        }

        tab.show_lines    = :all
        tab.show_headings = true
        tab.orientation   = :center
        tab.position      = :center

        data = [
          { "from1" =< "1 point", "to1" =< "0.3528 mm",
            "from2" =< "1 point", "to2" =< "1/72”" },
          { "from1" =< "10 mm", "to1" =< "28.35 pts",
            "from2" =< "", "to2" =< "" },
          { "from1" =< "A4", "to1" =< "210 mm × 297 mm",
            "from2" =< "A4", "to2" =< "595.28 pts × 841.89 pts" },
          { "from1" =< "LETTER", "to1" =< "81/2” × 11”",
            "from2" =< "LETTER", "to2" =< "612 pts × 792 pts" },
          ]

        tab.data.replace data
        tab.render_on(pdf)
      end
      pdf.save_as('unit-conversion.pdf')
    
Unit conversion PDF example
Figure 6. Unit Conversion Table PDF Example

Partial Document Generation Technique

One of the limitations of PDF::Writer (that the documents may never become singleton objects or hold references to Proc objects) also provides a strength for document generation. This limitation means that a document may be saved with Marshal::dump at any point during the generation process and it may then be restarted with the pregenerated code in that program or a separate program entirely. PDF::TechBook uses a variant of this to cache the manual so that all that needs to be done is page numbering and table of contents generation.

This technique could be used to generate a partial document that contains a letterhead or logo, like below:

      # letterhead.rb
      require 'pdf/writer'
      pdf = PDF::Writer.new

      pdf.text "Using PDF::Writer"
      pdf.line(pdf.absolute_left_margin, pdf.y + 10,
      pdf.absolute_right_margin, pdf.y + 10).stroke
      pdf.top_margin = pdf.y + 20

      File.open("letterhead._pc", "wb") { |f| f.write Marshal.dump(pdf) }
    

Then, at a later date, this pregenerated letter head can be loaded—even by multiple processes at the same time—and added to:

      require "pdf/writer"

      class HelloController < ApplicationController
        # ...
        def pdf
          _pdf = File.open("letterhead._pc", "rb") { |f|
            Marshal.load(f.read)
          }

          _pdf.text "Hello, Ruby.", :font_size => 72, :justification => :center

          send_data _pdf.render, :filename => "hello.pdf",
                    :type => "application/pdf"
        end
        # ...
      end
    

Conclusion

PDF::Writer is a powerful and useful library that can be used in most situations requiring formatted output. While its layout engine isn’t as powerful as a word processor’s, it is sufficient for most purposes. Being pure Ruby, it isn’t as fast as other solutions, either, but it is certainly fast enough. There are techniques that one can use, too, such as the partial document generation technique, to amortize the cost of generating complex documents. Development on PDF::Writer is active, and I am receptive of any bug fixes, enhancements, or extensions you wish to offer.

Talk Back!

Have an opinion about PDF::Writer? Discuss this article in the Articles Forum topic, Creating Printable Documents with Ruby.

Resources

[0] Bindings for ClibPDF
http://www2s.biglobe.ne.jp/~Nori/ruby/

[1] ClibPDF
http://www.fastio.com/

[2] Panda PDF
https://savannah.nongnu.org/projects/panda/

[3] Bindings to PDFlib
http://www-ps.kek.jp/thitoshi/ruby/pdflib/index.html

[4] PDFlib
http://www.pdflib.com/

[5] PHP Library “cPDF” by R & OS
http://ros.co.nz/pdf/

[6] PDF::Writer Preview
http://www.ruby-talk.org/cgi-bin/scat.rb/ruby/ruby-talk/82246

[7] PDF::Writer 1.1.3
http://rubyforge.org/frs/?group_id=81

[8] Transaction::Simple
http://rubyforge.org/projects/trans-simple/

[9] Color-tools
http://ruby-pdf.rubyforge.org/color-tools/

[10] Ruby on Rails
http://rubyonrails.org/

[11] RMagick
http://rmagick.rubyforge.org/

[12] Why 72 DPI?
http://www.wildpicture.com/pages/photography/dpi.htm

[13] Scalable Vector Graphics
http://www.w3c.org/Graphics/SVG

[14] Encapsulated PostScript
http:////www.cs.indiana.edu/docproject/programming/postscript/eps.html

[15] Bézier Curves
http://astronomy.swin.edu.au/~pbourke/curves/bezier/

About the Author

Austin Ziegler has been programming for twenty years, starting on a TRS-80 Model III computer. He discovered Ruby three years ago and has since developed, ported, or extended several different packages, including PDF::Writer, Ruwiki, Text::Format, MIME::Types, and Diff::LCS. He lives in Toronto, Canada.

<<  Page 4 of 4


Sponsored Links



Google
  Web Artima.com   
Copyright © 1996-2014 Artima, Inc. All Rights Reserved. - Privacy Policy - Terms of Use - Advertise with Us