Flylib.com

Books Software

 
 
 

Recipe 15.5. Generating PDF Documents


Recipe 15.5. Generating PDF Documents

Problem

You have an application that generates a report, a receipt, or some other output that you'd like users to be able to save. You'd like to generate this output as PDF documents for consistent formatting and convenient distribution.

Solution

Use Ruby FPDF to create PDF documents from within your Rails application.

First, download Ruby FPDF from http://brian.imxcc.com/fpdf/rfpdf153c.tar.gz. Extract the archive, and move the file called fpdf.rb to the your application's lib directory for it to be available to your controllers.

Next, create a Reports Controller that calls require to include the PDF creation library in your lib directory. This controller defines a private method called pdf_report_card and a public method or action called pdf_report .

app/controllers/reports_controller.rb :

class ReportsController < ApplicationController

  require 'fpdf'

  def index
  end

  def pdf_report

    # Data
    col_sizes = [40,20,20,20]
    data = [['Course','Exam 1','Exam 2','Final'],
            ['ENGLISH 101','90','87','B'],
            ['MUSIC 5A','97','100','A'],
            ['CALC 2','98','91','A'],
            ['SWIM','89','84','B'],
            ['HIST 110','91','81','B']]

    send_data pdf_report_card(col_sizes, data),
              :filename => "report.pdf", 
              :type => "application/pdf" 
  end

  private
    def pdf_report_card(col_sizes, data)

      pdf = FPDF.new

      pdf.AddPage
      pdf.SetFont('Arial','B')
      pdf.SetFontSize(10)
      pdf.SetFillColor(50,50,50)
      pdf.SetTextColor(255)
      pdf.SetDrawColor(0)
      pdf.SetLineWidth(0.2)

      # Table Header
      i = 0   
      col_sizes.each do
        pdf.Cell(col_sizes[i],7,data[0][i],1,0,'C',1)
        i += 1
      end
      pdf.Ln()

      pdf.SetFillColor(218,206,255)
      pdf.SetTextColor(0)
      pdf.SetFont('Arial')

      fill = 0
      # Table Data
      data[1..-1].each do row
          pdf.Cell(col_sizes[0],6,row[0],'LR',0,'L',fill)
          pdf.Cell(col_sizes[1],6,row[1],'LR',0,'L',fill)
          pdf.Cell(col_sizes[2],6,row[2],'LR',0,'L',fill)
          pdf.Cell(col_sizes[3],6,row[3],'LR',0,'C',fill)
          pdf.Ln()
          fill = (fill-1).abs % 2
      end

      # Bottom Table Border
      total = 0
      col_sizes.each {x total += x}
      pdf.Cell(total,0,'','T');

      pdf.Output
    end
end

The index. rhtml simply creates a link that generates a PDF report card:

app/views/reports/index.rhtml :

<h1>Report</h1>

<%= link_to 'Make PDF', :action => 'pdf_report' %>

Discussion

The solution displays a 'Make PDF' link. Clicking this link calls the pdf_report action of the Reports Controller when clicked. pdf_report defines an array of four integers that are the column widths of the table to be generated. The actual data to be output is defined as a two-dimensional array and stored in data . The PDF version of the report is returned to the user with the send_data method, which itself calls pdf_report_card to create the PDF. send_data also takes the :filename and :type options, which help browsers render or save the file.

pdf_report_card takes two array arguments; the column widths and a structure of the data to be output. The function creates a new FPDF object and then sets up display properties for the table header, including font and background color . The contents of data is then iterated over, and the body of the table is created. The final call to pdf.Cell draws the bottom border to the table.

Figure 15-2 shows the solution's PDF output.

Figure 15-2. A PDF containing a list of classes with exam scores

See Also

  • Documentation for Ruby FPDF doesn't exist other than the examples included in the source download. This is because the PHP version of FPDF's documentation http://www.fpdf.org/en/doc/index.php is almost completely applicable to Ruby FPDF's API.