Rubyでどう書く?:RubyでPDF履歴書を作成する

高倉利明(KBMJ)
2008-05-07 13:00:00
  • このエントリーをはてなブックマークに追加
最新特集【一覧】

問題

 Webアプリケーションを開発していると、「PDF文書を作成してほしい」との要望をクライアントから頂くことがあります。しかし、Rubyの実際のサービスでPDFを出力しているものはあまりありませんでした。

 ここでは以前、私が行った開発を元にノウハウを紹介したいと思います。

仕様

  • Ruby on Railsを使用(実際に必要になるケースはRoRプロジェクトがほとんどと考えました)
  • Rfpdfプラグインを使用(インストール方法はRoR Wiki 翻訳 Wiki - Rfpdfを参照)
  • 出力するフォーマットは図1のイメージ
図1 イメージ画像 図1 イメージ画像

回答例

class Resume

  class << self
    # PDF出力メソッド
    def output
      pdf = Pdf.new("高倉 利明", "タカクラ トシアキ")
      file = File.open("C:\\resume.pdf", "wb")
      file.write(pdf.generate)
    end
  end

  # pdf作成クラス
  class Pdf

    IC_SJIS = Iconv.new('SJIS', 'UTF-8')

    def initialize(name, kana)
      # 出力データ
      @name, @kana = name, kana
      # マージン
      @lm, @tm = 10, 10
      # 基本となる罫線の横、縦サイズ
      @width, @height = 120, 20

      @pdf = FPDF.new
      @pdf.extend(PDF_Japanese)
      @pdf.AddSJISFont
    end

    # PDF(バイナリデータ)を作成
    def generate
      @pdf.SetMargins(@lm, @tm)
      @pdf.AddPage
      drow_format(@lm, @tm)
      drow_data(@lm, @tm)
      return @pdf.Output
    end

    # フォーマット描画
    def drow_format(left, top)
      @pdf.SetXY(left, top)
      setBoldLine
      @pdf.Cell(@width, @height, '', 1)
      @pdf.SetXY(left, top)
      setThinLine

      # 氏名(フリガナ)欄
      @pdf.SetXY(left, top)
      @pdf.SetFont('SJIS','', 8)
      @pdf.Cell(20, 5, ic('フリガナ '), 'B', 0)
      @pdf.Cell(@width - 20, 5, '', 'B', 1)

      # 氏名欄
      y = @pdf.GetY
      setBoldLine
      @pdf.Cell(@width, 15, '', 'B', 0)
      @pdf.SetXY(left, y)
      @pdf.SetFont('SJIS','', 8)
      @pdf.Cell(20, 5, ic('氏名 '), 0, 2)
      @pdf.Cell(20, 10, '', 0, 0)
      @pdf.SetXY(left + 20, y)
      @pdf.Cell(@width - 20, 15, '', 0, 1)
    end

    # データ描画
    def drow_data(left, top)
      @pdf.SetXY(left, top)
      write_string(left + 25, top + 3, 10, @kana)
      write_string(left + 25, top + 13, 14, @name)
    end

    def write_string(left, top, font_size, string)
      @pdf.SetXY(left, top)
      @pdf.SetFont('SJIS','', font_size)
      @pdf.Write(0, ic(string))
    end

    def setBoldLine
      @pdf.SetLineWidth(0.3)
    end

    def setThinLine
      @pdf.SetLineWidth(0.1)
    end

    def ic(str)
      IC_SJIS.iconv(str)
    end

  end
end

 本ソースをresume.rbとしてRoRプロジェクトののmodelディレクトリに配置し、以下のコマンドを実行することで「C:\resume.pdf」で出力されます。

ruby script/runner Resume.output

解説

本サンプルでは、

  1. マージン、枠の縦横サイズの初期化「initialize」「generate」
  2. 罫線などのフォーマットを描画「drow_format」
  3. 各項目の値を描画「drow_data」

 というステップにわけて処理をしています。

 RFPDFライブラリを使用する場合は、

  1. FPDF.newでオブジェクト生成
  2. 日本語が扱えるようにextendやAddSJISFontメソッドで指定
  3. AddPageメソッドでページを追加
  4. ページに表示する内容を描画
    • 座標:SetXY、SetX、SetY、GetX、GetYなどを利用
    • 文字フォント:SetFontで指定
    • 罫線サイズ:SetLineWidthで指定
    • 罫線:Cellメソッドで描画(第三引数に文字列を指定することで、同時に文字の描画も可能)
    • 文字:Writeメソッドで描画
  5. Outputメソッドでバイナリを出力

 という流れとなります。

 日本語を出力する際は、Iconvを使用してSJISに変換しています(ソースをUTF8で書いているため)。

 なお、RFPDFの詳しい使用方法は、FPDFのWebサイト「FPDF」を参考にしてください。

最後に──

 駆け足で説明しましたが、いかがだったでしょうか?

 実際のところ、RFPDFは1年近く更新されておらず、また日本語を扱う上でまだバグが見られるのが現状です。

 また、罫線などの枠線をプログラムで引いている関係上、直観的ではない作りになってしまうのが欠点です。

 もっと良い方法があれば、コメントやbuilderブログなどで是非教えていただきたいと思います。

  • 新着記事
  • 特集
  • ブログ