RapidReport 製品ドキュメント

動的画像(グラフ)の表示

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

この帳票の上半分には花の画像と名前が一覧で表示されており、下半分にはグラフの画像が表示されています。 いずれも、表示される画像の内容は動的に決まります。

画像とグラフのサンプル

完成したサンプルが example フォルダ内に以下の名前で含まれています。

帳票定義ファイル: example_image.rrpt
ソースコード: ExampleImage.cs、ExampleImage.vb、ExampleImage.java

※ グラフ出力機能のサンプルは.NET Framework版にのみ含まれています。
※ .NET5以降/.NET CoreおよびJavaでもイメージローダを利用して動的画像を出力することは可能ですので、 動的に生成する画像の出力が必要な場合は、本ページの.NET Framework向けコードを読み替えてください。

RapidReportのレポートデザイナでは、[画像(Image)]要素を追加することによって画像を帳票内に出力することができます。 RapidReportで利用可能な画像の形式はBMP/PNG/JPEG/GIFです。

[画像]要素には静的な画像データを埋め込むことが可能ですが、 動的な画像を出力する場合は各種レンダラのImageLoaderMapメンバにイメージローダというオブジェクトを生成して設定します。

イメージローダはその名が示す通り帳票に出力すべき画像データを取得するためのオブジェクトで、[画像]要素を描画する際に呼び出されます。 イメージローダから画像を取得できなかった場合は、[画像]プロパティに設定された静的な画像がもしあればそれを表示します。

ImageLoaderMapはハッシュなので、複数のイメージローダを設定することができます。 要素がどのイメージローダを利用するかは [キー] というプロパティで指定することができます。 [キー]を省略した場合、イメージローダは利用されません。

イメージローダはレンダラ毎に用意された以下のインターフェースを満たす必要があります。 さらに、それぞれのインターフェースには標準実装クラス(後述)が用意されています。

レンダラ イメージローダの
インターフェース/標準実装クラス
PdfRenderer IPdfImageLoader
PdfImageLoader
XlsRenderer IXlsImageLoader
XlsImageLoader
XlsxRenderer IXlsxImageLoader
XlsxImageLoader
Printer IGdiImageLoader
GdiImageLoader

イメージローダを利用するには標準実装クラスを利用する方法と、 独自のイメージローダクラスを実装する方法の2通りがあります。 今回のサンプルでは両方の方法で画像を帳票に表示してみます。

イメージローダの標準実装クラス

サンプル帳票の上にある花の写真と名前の一覧は、あらかじめ複数の画像をロードしておき、 データの値に応じて表示する画像をその中から選択するという方法で表示しています。 このような場合はイメージローダの標準実装クラスを利用することができます。

まず、この帳票には以下のデータを与えます。 [code]列の値によって表示される画像が選択されるようにします。

  // C#

  private static DataTable getDataTable()
  {
      DataTable ret = new DataTable();
      ret.Columns.Add("code", typeof(int));
      ret.Columns.Add("name", typeof(String));
      ret.Rows.Add(1, "ハクサンイチゲ");
      ret.Rows.Add(2, "ニッコウキスゲ");
      ret.Rows.Add(3, "チングルマ");
      ret.Rows.Add(4, "コマクサ");
      return ret;
  }
  ' VisualBasic

  Private Function getDataTable() As DataTable
      Dim ret As New DataTable
      ret.Columns.Add("code", GetType(Integer))
      ret.Columns.Add("name", GetType(String))
      ret.Rows.Add(1, "ハクサンイチゲ")
      ret.Rows.Add(2, "ニッコウキスゲ")
      ret.Rows.Add(3, "チングルマ")
      ret.Rows.Add(4, "コマクサ")
      Return ret
  End Function

表示される候補となる画像はImageMapというオブジェクトに登録しておきます。 ImageMapは [jp.co.systembase.report.renderer] という名前空間に定義されています。 登録すべき画像データの型は以下になります。

※ バージョン5.16から.NET5以降/.NET Coreでは画像をByte配列で登録するように仕様変更となりました。

環境 画像データの型
.NET5以降/.NET Core Byte配列
.NET Framework System.Drawing.Image
Java java.awt.image.BufferedImage

サンプルコードを以下に示します。

  // C# (.NET5以降/.NET Core)

  // イメージマップを生成します
  private static ImageMap getImageMap()
  {
      ImageMap ret = new ImageMap();
      ret.Add(1, File.ReadAllBytes("report\\image1.jpg"));
      ret.Add(2, File.ReadAllBytes("report\\image2.jpg"));
      ret.Add(3, File.ReadAllBytes("report\\image3.jpg"));
      ret.Add(4, File.ReadAllBytes("report\\image4.jpg"));
      return ret;
  }
  ' VisualBasic (.NET5以降/.NET Core)

  ' イメージマップを生成します
  Private Function getImageMap() As ImageMap
      Dim ret As New ImageMap
      ret.Add(1, File.ReadAllBytes("report\image1.jpg"))
      ret.Add(2, File.ReadAllBytes("report\image2.jpg"))
      ret.Add(3, File.ReadAllBytes("report\image3.jpg"))
      ret.Add(4, File.ReadAllBytes("report\image4.jpg"))
      Return ret
  End Function
  // C# (.NET Framework)

  // イメージマップを生成します
  private static ImageMap getImageMap()
  {
      ImageMap ret = new ImageMap();
      ret.Add(1, new Bitmap("report\\image1.jpg"));
      ret.Add(2, new Bitmap("report\\image2.jpg"));
      ret.Add(3, new Bitmap("report\\image3.jpg"));
      ret.Add(4, new Bitmap("report\\image4.jpg"));
      return ret;
  }
  ' VisualBasic (.NET Framework)

  ' イメージマップを生成します
  Private Function getImageMap() As ImageMap
      Dim ret As New ImageMap
      ret.Add(1, New Bitmap("report\image1.jpg"))
      ret.Add(2, New Bitmap("report\image2.jpg"))
      ret.Add(3, New Bitmap("report\image3.jpg"))
      ret.Add(4, New Bitmap("report\image4.jpg"))
      Return ret
  End Function
  // Java

  // イメージマップを生成します
  private static ImageMap getImageMap() throws IOException {
      ImageMap ret = new ImageMap();
      ret.put(1, ImageIO.read(new File("report\\image1.jpg")));
      ret.put(2, ImageIO.read(new File("report\\image2.jpg")));
      ret.put(3, ImageIO.read(new File("report\\image3.jpg")));
      ret.put(4, ImageIO.read(new File("report\\image4.jpg")));
      return ret;
  }

花の画像を表示する要素の[式]プロパティには ".code" と指定します。 これにより、[code]列の値が画像を選択するキーとなります。 さらに、利用するイメージローダを指定するキーとして [キー] プロパティに "image" と指定します。

イメージローダの標準実装クラスは、コンストラクタの引数にImageMapオブジェクトを受け取ることができます。 生成したイメージローダのオブジェクトは "image" というキーで ImageLoaderMap に登録します。 ここでは、.NET(C#/VB)ではプレビュー表示、JavaではPDF出力を行う場合のサンプルコードを提示しますが、 exampleフォルダ以下のサンプルプロジェクトには、 その他の出力形式に対応したコードも含まれています。

  // C#

  // イメージマップを生成します
  ImageMap imageMap = getImageMap();

  ...

  // プレビュー画面表示
  {
      Printer printer = new Printer(pages);

      // イメージローダを登録します
      printer.ImageLoaderMap.Add("image", new GdiImageLoader(imageMap));
      printer.ImageLoaderMap.Add("graph", new GdiGraphImageLoader());

      FmPrintPreview preview = new FmPrintPreview(printer);
      preview.StartUpZoomFit = true;
      preview.ShowDialog();
  }
  ' VisualBasic

  ' イメージマップを生成します
  Dim imageMap As ImageMap = getImageMap()

  ...

  ' プレビュー画面表示
  With Nothing
      Dim printer As New Printer(pages)

      ' イメージローダを登録します
      printer.ImageLoaderMap.Add("image", New GdiImageLoader(imageMap))
      printer.ImageLoaderMap.Add("graph", New GdiGraphImageLoader())

      Dim preview As New FmPrintPreview(printer)
      preview.StartUpZoomFit = True
      preview.ShowDialog()
  End With

  // Java

  // イメージマップを生成します
  ImageMap imageMap = getImageMap();

  ...

  // PDF出力
  {
      FileOutputStream fos = new FileOutputStream("output/example_image.pdf");
      try {
          PdfRenderer renderer = new PdfRenderer(fos);
          // イメージローダを登録します
          renderer.imageLoaderMap.put("image", new PdfImageLoader(imageMap));
          pages.render(renderer);
      } finally {
          fos.close();
      }
  }

イメージローダの実装(グラフの表示)

この帳票の下の部分にに表示されているグラフの画像は、実行時に生成しています。 このように、画像をあらかじめ用意しておくことができない場合はイメージローダのクラスを独自に実装し、 その中で画像を生成します。

実装する必要があるのは GetImage(param) という1つのメソッドのみです。 このメソッドの引数 param には要素の[式]を評価して得られた値が渡されるので、 その値を元に画像を生成して返します。 (ただし、今回の例では簡単のため、固定の内容のグラフ画像を生成しています)

なお、レンダラは画像を取得する必要が生じるたびに GetImage メソッドを呼ぶので、 同じ画像が何度も生成されないように、生成した画像はキャッシュされるよう実装してください。

以下に、直接印刷・プレビューのレンダラから利用可能なイメージローダの実装を示します。 この中でgetGraphImageというメソッドを呼んでいますが、これはグラフの画像を生成して返すメソッドです。 本題から外れるのでその内容は示しませんが、exampleフォルダ以下のサンプルプロジェクトには完全な実装があります。 さらにPDF,Excel(XLS)レンダラ向けのイメージローダの実装もサンプルプロジェクトに含まれています。

  // C#

  // グラフの画像を直接印刷・プレビューに埋め込むためのイメージローダ
  private class GdiGraphImageLoader : IGdiImageLoader
  {
      // 画像をキャッシュするためのDictionary
      private Dictionary<Object, Image> cachedImage = new Dictionary<object, Image>();
      public Image GetImage(object param)
      {
          if (param == null)
          {
              return null;
          }
          // 画像がキャッシュになければ生成します
          if (!this.cachedImage.ContainsKey(param))
          {
              this.cachedImage.Add(param, getGraphImage(param));
          }
          return this.cachedImage[param];
      }
  }
  ' VisualBasic

  ' グラフの画像を直接印刷・プレビューに埋め込むためのイメージローダ
  Private Class GdiGraphImageLoader
      Implements IGdiImageLoader
      ' 画像をキャッシュするためのDictionary
      Private cachedImage As New Dictionary(Of Object, Image)
      Public Function GetImage(param As Object) As Image Implements IGdiImageLoader.GetImage
          If param Is Nothing Then
              Return Nothing
          End If
          ' 画像がキャッシュになければ生成します
          If Not Me.cachedImage.ContainsKey(param) Then
              Me.cachedImage.Add(param, getGraphImage(param))
          End If
          Return Me.cachedImage(param)
      End Function
  End Class

グラフを表示するための要素のプロパティは、 [キー]を"graph"とし、[式]を"'example'"としておきます。

イメージローダのオブジェクトを生成し、"graph"というキーでImageLoaderMapに登録します。 これで、帳票出力時には先ほど実装したGetImageメソッドが "example" という文字列を引数として呼ばれるようになります。

  // C#

  // プレビュー画面表示
  {
      Printer printer = new Printer(pages);

      // イメージローダを登録します
      printer.ImageLoaderMap.Add("image", new GdiImageLoader(imageMap));
      printer.ImageLoaderMap.Add("graph", new GdiGraphImageLoader());

      FmPrintPreview preview = new FmPrintPreview(printer);
      preview.StartUpZoomFit = true;
      preview.ShowDialog();
  }
  ' VisualBasic

  ' プレビュー画面表示
  With Nothing
      Dim printer As New Printer(pages)

      ' イメージローダを登録します
      printer.ImageLoaderMap.Add("image", New GdiImageLoader(imageMap))
      printer.ImageLoaderMap.Add("graph", New GdiGraphImageLoader())

      Dim preview As New FmPrintPreview(printer)
      preview.StartUpZoomFit = True
      preview.ShowDialog()
  End With


Copyright (c) 2013, SystemBase Co.,Ltd. All rights reserved.