動的要素

このページでは、以下の帳票を作成します。

この帳票では、要素のデザインを動的に修正するという処理を行っています。 まず、数値が負数であれば赤字にしています。 さらに、数値を視覚的に表すグラフを、[四角形]要素を使って表現しています。

動的要素のサンプル
サンプルについて
完成したサンプルが example フォルダ内に以下の名前で含まれています。 帳票定義ファイル: example_render.rrpt ソースコード: ExampleRender.cs、ExampleRender.vb、ExampleRender.java

負数を赤字にする

負数を赤字にする制御については、 [フィールド(field)]要素を同じ場所に2つ重ね、片方を黒字、もう片方を赤字とした上で、 それぞれ[表示条件]を黒字の方は (>= .NUM 0) とし、 赤字の方は (< .NUM 0)とすることで実現します。

実際にレポートデザイナを開いて確認してみてください。 なおこの時、altを押しながらクリックすると重なりあったfieldの選択を切り替えることができます。

※バージョン4.13以上をお使いの場合は、この方法ではなく[カスタマイズ]プロパティを利用する方法をお勧めします。

グラフの描画

続いて、数値の右側に表示されているグラフについて説明します。 このグラフは実際には単なる[四角形(rect)]要素となっています。 帳票の出力時にデータの値に合わせてその長さと位置、そして色を動的に設定します。

カスタマイザのRenderContentメソッドを利用することで、要素に対し動的な変更を加えることができます。 カスタマイザを実装するには、DefaultCustomizerクラスを継承します。 コードは以下のようになります。

  // C#
        
  // 要素に動的な修正を加えるカスタマイザ
  private class Customizer : DefaultCustomizer
  {
      public override void RenderContent(
          Content content, 
          Evaluator evaluator, 
          Region region, 
          ElementDesigns elementDesigns)
      {
          // このメソッドはコンテントの描画が行われる直前に呼ばれます
          // "content_example"という識別子を持ったコンテントに対して処理を行います
          if ("content_example".Equals(content.Design.Id))
          {
              // "grapph"という識別子を持った要素を取得し、レイアウトと色を修正します
              ElementDesign e = elementDesigns.Find("graph");
              // ".NUM"という式を評価することで、NUM列の値を得ます
              Decimal num = (Decimal)evaluator.EvalTry(".NUM");
              if (num >= 0)
              {
                  e.Child("layout").Put("x1", 100);
                  e.Child("layout").Put("x2", 100 + num);
                  e.Put("fill_color", "lightblue");
              }
              else
              {
                  e.Child("layout").Put("x1", 100 + num);
                  e.Child("layout").Put("x2", 100);
                  e.Put("fill_color", "pink");
              }
          }
      }
  }
  ' VisualBasic

  ' 要素に動的な修正を加えるカスタマイザ
  Private Class Customizer
      Inherits DefaultCustomizer
      Public Overrides Sub RenderContent( _
        ByVal content As Content, _
        ByVal evaluator As Evaluator, _
        ByVal region As Region, _
        ByVal elementDesigns As ElementDesigns)
          ' このメソッドはコンテントの描画が行われる直前に呼ばれます
          ' "content_example"という識別子を持ったコンテントに対して処理を行います
          If "content_example".Equals(content.Design.Id) Then
              ' "graph"という識別子を持った要素を取得し、レイアウトと色を修正します
              Dim e As ElementDesign = elementDesigns.Find("graph")
              ' ".NUM"という式を評価することで、NUM列の値を得ます
              Dim num As Decimal = evaluator.EvalTry(".NUM")
              If num >= 0 Then
                  e.Child("layout").Put("x1", 100)
                  e.Child("layout").Put("x2", 100 + num)
                  e.Put("fill_color", "lightblue")
              Else
                  e.Child("layout").Put("x1", 100 + num)
                  e.Child("layout").Put("x2", 100)
                  e.Put("fill_color", "pink")
              End If
          End If
      End Sub
  End Class
  // Java

  // 要素に動的な修正を加えるカスタマイザ
  private static class Customizer extends DefaultCustomizer{
      public void renderContent(
              Content content,
              Evaluator evaluator,
              Region region,
              ElementDesigns elementDesigns) {
          // このメソッドはコンテントの描画が行われる直前に呼ばれます
          // "content_example"という識別子を持ったコンテントに対して処理を行います
          if ("content_example".equals(content.design.id)){
              // "graph"という識別子を持った要素を取得し、レイアウトと色を修正します
              ElementDesign e = elementDesigns.find("graph");
              // ".NUM"という式を評価することで、NUM列の値を得ます
              float num = Cast.toFloat(evaluator.evalTry(".NUM"));
              if (num >= 0){
                  e.child("layout").put("x1", 100);
                  e.child("layout").put("x2", 100 + num);
                  e.put("fill_color", "lightblue");
              }else{
                  e.child("layout").put("x1", 100 + num);
                  e.child("layout").put("x2", 100);
                  e.put("fill_color", "pink");
              }
          }
      }
  }

RenderContentメソッドはコンテントが描画される直前に呼ばれます。 今回の例では、"content_example"という識別子を持ったコンテントに対して処理を行います。

引数で渡されるElementDesignsオブジェクトは、このコンテントに含まれる要素定義のリストです。 この中からFindメソッドで"graph"という識別子を持った要素を検索します。

続いて、evaluatorを用いて NUM 列の値を取得し、その値に応じてlayoutとfill_colorを設定します。 要素定義はElementDesignというオブジェクトによって表されます。 childメソッドで子オブジェクトを得ることができ、putメソッドによって値を書き換えます。

ElementDesignに対する変更はこの描画でのみ有効です。 次のコンテントを描画する際には元の値にリセットされます。

帳票を出力するコードは以下のようになります。

  // C#

  // 第2引数にCustomizerオブジェクトを渡します
  Report report = new Report(Json.Read("report\\example_render.rrpt"), new Customizer());
  report.Fill(new ReportDataSource(getDataTable()));
  ReportPages pages = report.GetPages();

  // PDF出力
  using (FileStream fs = new FileStream("output\\example_render.pdf", FileMode.Create))
  {
      PdfRenderer renderer = new PdfRenderer(fs);
      renderer.Setting.ReplaceBackslashToYen = true;
      pages.Render(renderer);
  }
  ' VisualBasic
  
  ' 第2引数にCustomizerオブジェクトを渡します
  Dim report As New Report(Json.Read("report\example_render.rrpt"), New Customizer)
  report.Fill(New ReportDataSource(getDataTable))
  Dim pages As ReportPages = report.GetPages()

  ' PDF出力
  Using fs As New FileStream("output\example_render.pdf", IO.FileMode.Create)
      pages.Render(New PdfRenderer(fs))
  End Using
  // Java

  // 第2引数にCustomizerオブジェクトを渡します
  Report report = new Report(ReadUtil.readJson("report/example_render.rrpt"), new Customizer());
  report.fill(new ReportDataSource(getDataTable()));
  ReportPages pages = report.getPages();

  // PDF出力
  FileOutputStream fos = new FileOutputStream("output/example_render.pdf");
  try{
      pages.render(new PdfRenderer(fos));
  }finally{
      fos.close();
  }