akishin999の日記

調べた事などを書いて行きます。

Ruby で PDF にフッタを埋め込む

Pdftk を使用して Ruby から PDF にフッタを埋め込む方法を調べてみました。
ちなみに Ruby のバージョンは以下です。

# ruby -v
ruby 1.9.3p194 (2012-04-20 revision 35410) [x86_64-linux]

Pdftk のインストール

Pdftk は大抵のディストリビューションでパッケージが用意されているのでインストールは簡単です。

RPMForge にパッケージが用意されています。

Index of /pdftk
http://pkgs.repoforge.org/pdftk/

ここでは yum からインストールしました。

# yum install -y http://pkgs.repoforge.org/pdftk/pdftk-1.44-2.el6.rf.x86_64.rpm

Ubuntu の場合は以下のように apt でインストールすることができます。

$ sudo apt-get install -y pdftk

以下のように pdftk コマンドが実行できるようになっていればインストールは完了です。

$ pdftk --version

pdftk 1.44 a Handy Tool for Manipulating PDF Documents
Copyright (C) 2003-10, Sid Steward - Please Visit: www.pdftk.com
This is free software; see the source code for copying conditions. There is
NO warranty, not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

gem のインストール

以下の gem をインストールします。

$ gem install pdf-toolkit prawn --no-rdoc --no-ri
$ gem install activesupport -v 3.1.0 --no-rdoc --no-ri

pdftk を Ruby から使うためのラッパーとして、pdf-toolkit ライブラリを使用しました。

PrawnRuby で PDF を生成するためのライブラリです。
pdftk で既存の PDF ファイルにフッタを埋め込むには、予め用意しておいたフッタ文字列のみが入った PDF ファイルと合成する必要があります。
ここではフッタ文字列の PDF を作成するために Prawn を使用しています。

ActiveSupport のバージョン 3.1.0 についてですが、これはどうやら pdf-toolkit が依存しているようで、これ以降のバージョンを使用すると以下のエラーが出てしまいます。

$ ruby pdf_footer.rb
/usr/local/lib/ruby/gems/1.9.1/gems/pdf-toolkit-0.5.0/lib/pdf/toolkit.rb:200:in `<class:Toolkit>': undefined method `class_inheritable_accessor' for PDF::Toolkit:Class (NoMethodError)
        from /usr/local/lib/ruby/gems/1.9.1/gems/pdf-toolkit-0.5.0/lib/pdf/toolkit.rb:67:in `<top (required)>'
        from /usr/local/lib/ruby/1.9.1/rubygems/custom_require.rb:60:in `require'
        from /usr/local/lib/ruby/1.9.1/rubygems/custom_require.rb:60:in `rescue in require'
        from /usr/local/lib/ruby/1.9.1/rubygems/custom_require.rb:35:in `require'
        from pdf_footer.rb:5:in `<main>'

この問題を回避するために明示的にバージョンを指定しています。
もし古いバージョンの gem を使用するのが嫌な人は Ruby から直接 pdftk コマンドを実行しても問題ないと思います。

Ruby から Pdftk を使う

今回使用する pdftk のコマンドは background か stamp です。
background では元となる PDF の背面に、stamp では前面に重ねられる点が異なりますが、フッタのみの場合は余り関係がないと思うのでどちらでも OKです。

ここでは pdf_footer.rb というファイル名で以下のようなコードを書きました。

# -*- coding: utf-8 -*-
gem 'activesupport', '<= 3.1.0'
require 'active_support/core_ext/class/inheritable_attributes'
require 'pdf/toolkit'
require 'prawn'

Prawn::Document.generate("footer.pdf",
                         :page_layout   => :portrait,
                         :page_size     => 'A4') do
  text "Footer Example", :size => 10, :align => :center, :valign => :bottom
end

PDF::Toolkit.pdftk(*%W(source_file.pdf stamp footer.pdf output result.pdf))

ソースコードと同じ場所に適当な PDF ファイルを source_file.pdf として配置し、以下のように実行します。

$ ruby pdf_footer.rb
DEPRECATION WARNING: class_inheritable_attribute is deprecated, please use class_attribute method instead. Notice their behavior are slightly different, so refer to class_attribute documentation first. (called from require at /usr/local/lib/ruby/1.9.1/rubygems/custom_require.rb:60)
DEPRECATION WARNING: class_inheritable_attribute is deprecated, please use class_attribute method instead. Notice their behavior are slightly different, so refer to class_attribute documentation first. (called from require at /usr/local/lib/ruby/1.9.1/rubygems/custom_require.rb:60)
DEPRECATION WARNING: class_inheritable_attribute is deprecated, please use class_attribute method instead. Notice their behavior are slightly different, so refer to class_attribute documentation first. (called from require at /usr/local/lib/ruby/1.9.1/rubygems/custom_require.rb:60)
DEPRECATION WARNING: class_inheritable_attribute is deprecated, please use class_attribute method instead. Notice their behavior are slightly different, so refer to class_attribute documentation first. (called from require at /usr/local/lib/ruby/1.9.1/rubygems/custom_require.rb:60)

ActiveSupport の DEPRECATION WARNING が若干気になりますが、動作上は問題がないのでここでは気にしない事にします。

成功すると同じディレクトリに result.pdf という名前で「Footer Example」という文字列がフッタに埋め込まれた PDF が生成されているはずです。

Prawn は高機能なので、フォントや位置を変更したりしてもっと高度なフッタを作成する事も可能です。

こちらの記事で紹介されていた PDFTK Builder も Pdftk を使っているようなので、その気になれば同じ事を Ruby から行う事も可能だと思います。
大量に処理したり自動化したりしたい場合は Ruby から使う方が便利ですよね。