Thinreportsでの帳票作成をより手軽に

## rubyで手軽に帳票が作成できるThinreports
Thinreportsを使用した帳票作成ステップは以下の通りです。

* Thinreports-editorでレイアウトファイルを作る
* rubyで
   * レイアウﾄの各項目に値を設定
   * generateメソッドでPDFを出力

今回はレイアウトファイルの情報を利用して各項目への設定ロジックのひな型を作成します。

## レイアウトファイル(.tlf)はJSON
Thinreports-Editorで作成されるレイアウトファイルはJSONなので、
情報を取り出してみます。

レイアウトファイルの構造(の雰囲気)は以下の通りです。

* items
   * item
     * id
     * type "text-block"
   * item
     * id
     * type "list"
     * items
        * detail
            * items
                * item

今回のお題として簡単な帳票(collection_list.tlf)を作成しました。
![collection_list.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284224/7049112d-1ae7-a5cc-1283-372d35f1930a.png)


## tlfから情報を取り出そう(1) text-block
可変テキストを設定するのはtype: text-block なので、このIDを取り出します。

````ruby
require 'json'

@layout="collection_list.tlf"

File.open(@layout) do |j|
    tlf = JSON.load(j)

    @text_blocks = []

    tlf["items"].each do |item|
        if item["type"] == "text-block"
            @text_blocks.push item["id"]
        end
    end

    @text_blocks.each do |i|
        puts i
    end
end
````

実行してみます。

````
PS thinreports> ruby .\extract_text_block.rb
name
birthday
````
まずはベタなtext-blockのIDが取り出せました。

## tlfから情報を取り出そう(2) listのtext-block
次にリストの中のtype: text-block を取り出します。
リストの項目は取り扱いを変えたいので別の配列に格納します。

````ruby
require 'json'
@layout="collection_list.tlf"

File.open(@layout) do |j|
    tlf = JSON.load(j)

    @text_blocks = []
    @list_text_blocks = []

    tlf["items"].each do |item|
  
        if item["type"] == "text-block"
            @text_blocks.push item["id"]
        end

        if item["type"] == "list"
            item["detail"]["items"].each do |l_item|
                if l_item["type"] == "text-block"
                  @list_text_blocks.push l_item["id"]
                end
            end
        end

    end

    @text_blocks.each do |i|
        puts i
    end

    @list_text_blocks.each do |i|
        puts i
    end
end
````

````
PS thinreports> ruby .\extract_text_block.rb
name
birthday
item_name
date
shop
````

リストの中のtext-blockもOKです。

## erbでrubyソース生成

ではソース生成に参りましょう。
erbを作成します。

リスト内のtext-blockはCSVを読み込んで値を設定するように組みました。

````erb
require 'thinreports'
require 'csv'

Thinreports::Report.generate filename: 'result.pdf', layout: '<%= @layout %>' do

  start_new_page

% @text_blocks.each do |item|
  page.item(:<%= "#{item}" %>).value = ""
% end

  CSV.foreach("data.csv") do |csv_row|
    page.list.add_row do |row|
%   @list_text_blocks.each_with_index do |l_item,i|
      row.item(:<%= "#{l_item}" %>).value = csv_row[<%= "#{i}" %>]
%   end
    end
  end
end
````

rubyにはerbでの生成ロジックを追加

````ruby
require 'json'
require 'erb'

@layout="collection_list.tlf"

# 省略

erb = ERB.new(IO.read("./extract_text_block.erb"), nil, "%" )
File.open("./src.rb", "w" ) { |f|
  f.write( erb.result(binding) )
}

````

実行するとこんなソースが生成されました。

````ruby
require 'thinreports'
require 'csv'

Thinreports::Report.generate filename: 'result.pdf', layout: 'collection_list.tlf' do

  start_new_page

  page.item(:name).value = ""
  page.item(:birthday).value = ""

  CSV.foreach("data.csv") do |csv_row|
    page.list.add_row do |row|
      row.item(:item_name).value = csv_row[0]
      row.item(:shop).value = csv_row[1]
      row.item(:date).value = csv_row[2]
    end
  end
end

````
## さあ、PDFの時間だ

データとなるdata.csvを用意して(ヘッダは要りません)

|アイテム|ショップ|日付|
|---|---|---|
|タイタン|○○屋|197X|
|スパイマジシャン|△△屋|197X|
|コマンド|□屋|197X|


src.rbを実行すると・・・！

![pdf.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/284224/d1a8a6be-8c50-024e-2fac-e32babb433be.png)


一部設定してないところもありますが、簡単にPDFが作成できました。
コーディングだけでなくドキュメント作成等にも応用できると思います。
（ドキュメント作成は標準装備されてます）

テンプレート処理は面白いです。