帳票にデータを渡す方法

ReportオブジェクトのFillメソッドを呼ぶことで、帳票にデータを渡すことができます。 Fillメソッドには、データソースとデータプロバイダという2つの引数を渡します。

データソースは常に指定する必要がありますが、データプロバイダは必要な場合のみ指定します。

  // C#
  report.Fill(dataSource);
  report.Fill(dataSource, dataProvider);
  ' VisualBasic
  report.Fill(dataSource)
  report.Fill(dataSource, dataProvider)
  // Java
  report.fill(dataSource);
  report.fill(dataSource, dataProvider);

データソース

主要なデータはデータソースオブジェクトを通じてReportに渡されます。 渡されるデータの形式は、列と行からなる表形式です。 例えば、データベースへのクエリの結果をそのまま帳票に渡すことができます。

Reportはデータソースオブジェクトからデータを受け取ると、 グループのプロパティに設定された条件でそれを分割します。 続いて、分割されたデータの数だけグループオブジェクトが作成され、 それぞれにデータが割り当てられます。 さらに、グループに属するコンテントが子グループを持っていた場合は、 再帰的にデータの分割と割り当てが行われます。

データソースオブジェクトは、 IReportDataSourceというインターフェースを実装している必要があります。 独自のデータソースを作成することも可能ですが、標準でいくつかの実装クラスが用意されています。

ReportDataSource

ReportDataSourceはデータソースの標準的な実装です。 データベースへのクエリの結果をReportに渡すには、 特に問題がなければこのクラスを利用します。

.NET版におけるReportDataSourceのコンストラクタにはDataTableまたは、IListを渡します。 IListの要素はHashtableか、または各列に対応したプロパティを持ったオブジェクトである必要があります。

  // C#
  DataTable dataTable = ....
  report.Fill(new ReportDataSource(dataTable));

  List<XXX> dataList = ...
  report.fill(new ReportDataSource(dataList));
  ' VisualBasic
  Dim dataTable As DataTable = ....
  report.Fill(New ReportDataSource(dataTable))

  Dim dataList As List(Of XXX) = ...
  report.fill(new ReportDataSource(dataList));

Java版におけるReportDataSourceのコンストラクタにはResultSetもしくはListを渡します。 Listの要素はMapか、またはJavaBeansである必要があります。

  // Java
  ResultSet resultSet = ...
  report.fill(new ReportDataSource(resultSet));

  List<XXX> dataList = ...
  report.fill(new ReportDataSource(dataList));

DummyDataSource

DummyDataSourceは全ての列がNULLを返す1行のデータを表すオブジェクトです。 このオブジェクトのインスタンスはNewではなく、 GetInstanceというクラスメソッドで得てください。

  // C#
  report.Fill(DummyDataSource.GetInstance());
  ' VisualBasic
  report.Fill(DummyDataSource.GetInstance)
  // Java
  report.fill(DummyDataSource.getInstance());

BlankDataSource

BlankDataSourceは行が1つもないデータを表すオブジェクトです。 このオブジェクトのインスタンスはNewではなく、 GetInstanceというクラスメソッドで得てください。

このオブジェクトをReport.Fillメソッドに渡した場合、 ページが1つも作られないためにその帳票は出力できません。 このオブジェクトは主に後述するデータプロバイダを実装する際に利用します。

SubPageDataSource

SubPageDataSourceは、サブページを含んだ帳票に与えるためのデータを表すオブジェクトです。 コンストラクタには以下の引数を与えます。

1つ目の引数には、サブページを表すReportPagesオブジェクトを指定します。

2つ目の引数には、改ページ条件となるグループの識別子を指定します。 指定する必要がなければ、NULLを指定します。

3つ目以降の引数には、サブページのページ数を返す列名を指定します。 この引数は可変個指定することができます。

このメソッドはReportのAddSubPagesメソッドと共に利用します。

  // C#
  ReportPages subPages = subReport.GetPages();
  report.AddSubPages("subpage", subPages);
  report.Fill(new SubPageDataSource(subPages, "group_id", "page1", "page2"));
  ' VisualBasic
  Dim subPages As ReportPages = subReport.GetPages()
  report.AddSubPages("subpage", subPages)
  report.Fill(New SubPageDataSource(subPages, "group_id", "page1", "page2"))
  // Java
  ReportPages subPages = subReport.getPages();
  report.addSubPages("subpage", subPages);
  report.fill(new SubPageDataSource(subPages, "group_id", "page1", "page2"));

機能サンプルの「サブページ」に、 サブページを利用したサンプルの説明があります。

IReportDataSourceインターフェース

IReportDataSourceインターフェースを実装することで、 独自のデータソースを作成することができます。 これにより、様々な形式のデータを帳票に渡すことができます。

IReportDataSourceは以下のように定義されています。

  ' .NET (VisualBasic)
  Public Interface IReportDataSource
    Function [Get](ByVal i As Integer, ByVal key As String) As Object
    Function Size() As Integer
  End Interface
  // Java
  public interface IReportDataSource {
    Object get(int i, String key) throws UnknownFieldException;
    int size();
  }  

Sizeメソッドでデータの総行数を返し、 Getメソッドで値を返します。 Getに渡される引数は、iが行番号で、keyが列名です。

UnknownFieldException例外クラス

存在しない列(key)がGetメソッドに渡された場合は、UnknownFieldExceptionを発生させるよう実装してください。 これにより、帳票デザイン内の式で、列名を書き間違えるなどした場合に、 IReportLoggerのUnknownFieldErrorメソッドが呼ばれるようになります。

UnknownFieldExceptionのコンストラクタには、データソース、行番号、列名を渡してください。以下にthrow文の例を示します。

  // .NET (C#)
  throw new UnknownFieldException(this, i, key);
  ' .NET (VisualBasic)
  Throw New UnknownFieldException(Me, i, key)
  // Java
  throw new UnknownFieldException(this, i, key);

機能サンプルの「CSVデータソース」に、 IReportDataSourceを実装するサンプルの説明があります。

データプロバイダ

Reportはデータソースから受け取ったデータを分割しながら子孫のグループへと割り当てていきます。 その際、Fillメソッドにデータプロバイダを指定した場合、 特定のグループ以下に別のデータを割り当てることができます。

データプロバイダのオブジェクトは、 IGroupDataProviderインターフェースを実装する必要があります。 標準でGroupDataProviderという実装クラスが用意されています。

GroupDataProvider

GroupDataProviderオブジェクトを利用するには、 以下のように、グループの識別子と割り当てるデータソースの組を、 GroupDataMapというハッシュに登録します。

  // C#
  GroupDataProvider groupDataProvider = new GroupDataProvider();
  groupDataProvider.GroupDataMap.Add("group_id", new ReportDataSource(data));
  ' VisualBasic
  Dim groupDataProvider As New GroupDataProvider
  groupDataProvider.GroupDataMap.Add("group_id", New ReportDataSource(data))
  // Java
  GroupDataProvider dataProvider = new GroupDataProvider();
  groupDataProvider.groupDataMap.put("group_id", new ReportDataSource(data));

割り当てられたデータはまず、 指定されたグループとその祖先のグループで定義されている[ブレーク条件キー]の単位で分割されます。 そして、元々そのグループに割り当てられるはずだったデータと[ブレーク条件キー]列の比較が行われ、 値が一致するものが割り当てられます。

グループへのデータの割り当て方を、 GroupDataMapへ登録する際にEGroupDataModeという値で指定することができます。

  // C#
  GroupDataProvider groupDataProvider = new GroupDataProvider();
  groupDataProvider.GroupDataMap.Add("group_id", New ReportDataSource(data),
    Report.EGroupDataMode.NO_SPLIT); //データを分割しない
  ' VisualBasic
  Dim groupDataProvider As New GroupDataProvider
  groupDataProvider.GroupDataMap.Add("group_id", New ReportDataSource(data), _
    Report.EGroupDataMode.NO_SPLIT) 'データを分割しない
  // Java
  GroupDataProvider dataProvider = new GroupDataProvider();
  groupDataProvider.groupDataMap.put("group_id", new ReportDataSource(data),
    Report.EGroupDataMode.NO_SPLIT); //データを分割しない

EGroupDataModeの一覧を以下に示します。

説明
DEFAULT_BLANK データを[ブレーク条件キー]に基づいて分割します
グループに割り当てるべきデータが1行もなければ
グループは作られません
この値がデフォルトです
DEFAULT_DUMMY データを[ブレーク条件キー]に基づいて分割します
グループに割り当てるべきデータが1行もなければ
DummyDataSourceが割り当てられたグループが作られます
NO_SPLIT データ分割を行わずに
全てのグループにデータを丸ごと割り当てます

機能サンプルの「データの部分割り当て」に、GroupDataProviderを利用した例があります。

IGroupDataProviderインターフェース

以下のように定義されているIGroupDataProviderインターフェースを実装することで、 独自のデータプロバイダを作成できます。

  ' .NET (VisualBasic)
  Public Interface IGroupDataProvider
    Function GetGroupDataSource(ByVal groups As Groups, ByVal data As ReportData) As IReportDataSource
  End Interface
  // Java
  public interface IGroupDataProvider {
    IReportDataSource getGroupDataSource(Groups groups, ReportData data);
  }

Fillメソッドにデータプロバイダが指定されていた場合、 グループにデータが割り当てられるたびに、GetGroupDataSource()メソッドが呼ばれます。 このメソッドの戻り値の型はIReportDataSourceであり、 ここで返した値がグループに割り当てられます。

デフォルトのデータは引数dataで与えられます。 データの上書きをしないならば、このdataをそのまま戻り値とします。

  // C#
  public class ExampleDataProvider : IGroupDataProvider
  {
      public IReportDataSource GetGroupDataSource(Groups groups, ReportData data)
      {
          // "example_id"という識別子を持ったグループならば
          if ("example_id".Equals(groups.Design.Id))
          {
              // グループに割り当てるデータソースを生成して返します
              return new ReportDataSource(...);
          }
          else
          {
              // それ以外ならばdataを返します
              return data;
          }
      }
  }
  ' VisualBasic
  Public Class ExampleDataProvider
      Implements IGroupDataProvider
      Public Function GetGroupDataSource(groups As Groups, data As ReportData) As IReportDataSource _
        Implements IGroupDataProvider.GetGroupDataSource
          ' "example_id"という識別子を持ったグループならば
          If "example_id".Equals(groups.Design.Id) Then
              ' グループに割り当てるデータソースを生成して返します
              Return New ReportDataSource(...)
          Else
	      ' それ以外ならばdataを返します
              Return data
          End If
      End Function
  End Class  
  // Java
  public class ExampleDataProvider implements IGroupDataProvider{
      @Override
      public IReportDataSource getGroupDataSource(Groups groups, ReportData data) {
          // "example_id"という識別子を持ったグループならば
          if ("example_id".equals(groups.design.id))
          {
              // グループに割り当てるデータソースを生成して返します
              return new ReportDataSource(...);
          }
          else
          {
              // それ以外ならばdataを返します
              return data;
          }
      }
  }

ReportData

グループに割り当てるデータソースを生成する際に、 引数dataに含まれた値を得る必要があることも多いはずです。

dataは、ReportDataというクラスのオブジェクトです。 ここから値を得るには以下のように書きます。

  // C#

  // 行数を得る
  count = data.Size();

  // 最初の行の値を得る
  v = data.GetRecord.Get("col");

  // 全行の値を得る
  foreach(ReportDataRecord r in data.GetRecords())
  {
      v = r.Get("col");
  }

  // 指定した行の値を得る
  v = data.Get(10, "col"); // 10行目
  v = data.Get( 0, "col"); //  0行目 (data.GetRecord.Get("col")と等価)
  ' VisualBasic

  ' 行数を得る
  count = data.Size()

  ' 最初の行の値を得る
  v = data.GetRecord.Get("col")

  ' 全行の値を得る
  For Each r As ReportDataRecord In data.GetRecords
    v = r.Get("col")
  Next

  ' 指定した行の値を得る
  v = data.Get(10, "col") ' 10行目
  v = data.Get( 0, "col") '  0行目 (data.GetRecord.Get("col")と等価)
  // Java

  // 行数を得る
  count = data.size();

  // 最初の行の値を得る
  v = data.getRecord().get("col");

  // 全行の値を得る
  for(ReportDataRecord r: data.getRecords()){
    v = r.get("col");
  }

  // 指定した行の値を得る
  v = data.get(10, "col"); // 10行目
  v = data.get( 0, "col"); //  0行目 (data.getRecord().get("col")と等価)