Thinreports に SectionReport フォーマット機能を追加する pull request を作成した

こんにちは、Misoca開発チームの日高(@hidakatsuya)です。

以前、Thinreports の SectionReport フォーマット機能を公開したという記事を書きました。

tech.misoca.jp

この度、この機能を pull request 及び issueとして、Thinreports コミュニティに提案しましたので、その内容について紹介します。また、SectionReport フォーマットでは何ができるのかを知ってもらうために、いくつかの特徴もご紹介します。

SectionReport フォーマット機能のコミュニティへの提案

提案の概要

github.com

機能の概要や使い方、SectionReport フォーマット機能の今後の開発方針などを説明しています。SectionReport フォーマットという機能がどういうもので、どのような背景があり、どのような方針で実装されているかなど、この issue を読むことでそれらを把握することができます。

内容は概ね次の通りです。

  • コミュニティで提案されている仕様 をベースに SectionReport フォーマットを実装した
  • 未実装の仕様や既知の課題が残っているが、それらについてはコミュニティと一緒に開発していきたい
  • SectionReport フォーマットの仕様の説明として、いくつかのサンプルコード (Rubyコード、テンプレート、出力結果PDF) を作成したので参考にして欲しい
  • SectionReport フォーマットの使い方として Hello World を説明
  • 私たちが実装した SectionReport フォーマットは未完成で問題もあるが、今後はコミュニティと一緒に開発を進めたい。その提案として、一旦現状で取り込み、仕様の議論とタスクの整備を行って、広く開発に参加できる環境を作って進めてはどうだろう

実装の詳細 (pull request)

Thinreports の Generator (rubygem) と Editor (テンプレートデザイナ) の実装は、それぞれの pull request として作成しています。

github.com

github.com

pull request の説明では、使い方や実装ステータス (未実装、独自実装、既知の問題) について詳しく記載しています。

ぜひご意見ください

私たちが提案した SectionReport フォーマットは、未完成でいくつかの問題もあります。SectionReport フォーマットの機能としての仕様はもちろん、今後の開発の進め方など、広くディスカッションした上で、より良い形で開発を進めたいと考えています。

issue の内容への質問や意見、実際に動かしてみた感想や質問、コードに対する指摘などなど、ぜひご意見をいただけると嬉しいです。

SectionReport フォーマットで何ができるのか

現行の Thinreports のフォーマット (以降、現行のフォーマットと呼ぶ) との比較として、SectionReport フォーマットの特徴を二つ紹介します。

そもそも、SectionReport フォーマットって何?という方は、まず Thinreports コミュニティで提案されている仕様 をご覧ください。

ヘッダーやフッター、明細行を任意の数だけ定義し、組み合わせて出力することができる

現行のフォーマットでは、ヘッダーやフッターといった概念自体がありません。近い機能として「リスト」というツールがありますが、ヘッダーやフッター、明細行は一つだけしか定義することができません。

SectionReport フォーマットでは、次のように、いずれも任意の数だけ定義することができ、名前(ID)によって、それらを組み合わせることができます。

例えば、次のようなテンプレートを用意します。

f:id:hidakatsuya:20201012180259p:plain
テンプレート (Thinreports Editor)

次のコードで PDF を生成します。

report_params = {
  type: :section,
  layout_file: 'example1.tlf',
  params: {
    groups: [
      {
        headers: {
          header1: { items: { text_block1: 'タイトル' } },
          header2: { display: false }
        },
        details: [
          { id: :detail_a, items: { text_block1: '明細1行目' } },
          { id: :detail_a, items: { text_block1: '明細2行目' } },
          { id: :detail_b, items: { text_block1: '明細3行目' } },
          { id: :detail_b, items: { text_block1: '明細4行目' } },
          { id: :detail_a, items: { text_block1: '明細5行目' } }
        ],
        footers: {
          footer1: { display: false }
        }
      }
    ]
  }
}

File.binwrite('example1.pdf', Thinreports.generate(report_params))

出力される PDF は次のようになります。

f:id:hidakatsuya:20201012174550p:plain
出力結果PDF

パラメータによって、テンプレートに定義されたヘッダーを非表示にしたり (display: false)、複数の明細の定義を組み合わせて出力するといったことが可能です。

自動的に領域の高さが伸縮する

現行のフォーマットは、設定した用紙をキャンバスとして、テキストや図形などを配置してレイアウトを作成します。そのため、出力する PDF の高さも用紙の高さで固定され、テキストや図形などの描画位置やサイズも固定です。そのため、テキストの内容によって、図形の位置を下にずらしたり、領域の高さを動的に変更することが困難です。

SectionReport フォーマットでは、ヘッダーやフッター、明細行の高さの動的伸縮をサポートしています。また、動的伸縮によって、図形などの描画位置も動的に追従することが可能です。次の例をご覧ください。

次のようなテンプレートを用意します。

f:id:hidakatsuya:20201012175515p:plain
テンプレート (Thinreports Editor)

次のコードで PDF を生成します。

report_params = {
  type: :section,
  layout_file: 'example2.tlf',
  params: {
    groups: [
      {
        headers: {
          header1: { items: { title: '長いタイトル ' * 15 } },
        },
        details: [
          { id: :detail_a, items: { detail_text: '短い明細' } },
          { id: :detail_a, items: { detail_text: '長い明細 ' * 18 } },
          { id: :detail_a, items: { detail_text: '短い明細' } }
        ]
      }
    ]
  }
}
File.binwrite('example2.pdf', Thinreports.generate(report_params))

出力される結果は次のようになります。

f:id:hidakatsuya:20201012175703p:plain
出力結果PDF

定義した領域を超えるテキストをセットした場合でも、ヘッダー1 の領域の高さが自動的に拡張し、ヘッダー2 や明細A がその下に続いて正しく描画されます。また、明細Aの二行目では、拡張した領域に合わせて四角形の高さが拡張していることがわかると思います。

最後に

興味のある方はぜひ SectionReport フォーマットで遊んでみてください。

宣伝

Misoca 開発チームでは、積極的に OSS に貢献していきたいエンジニアを募集しています。

www.wantedly.com