CodeZine(コードジン)

特集ページ一覧

5分でわかるActiveReports帳票-さまざまなデータソースの利用とデータのグラフ表示(2007年度版)

ActiveReports for .NET 3.0Jで作るサンプル帳票

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2007/12/06 14:00

 本連載では帳票作成コンポーネント「ActiveReports for .NET 3.0J」を使って帳票アプリケーションを作成していきます。今回はXMLやDBなどさまざまなデータソースの利用とグラフ表示について説明します。

編集部注

 本稿の内容を増補改訂したアップデート版が提供されています。詳しくは連載の目次「5分でわかるActiveReports帳票」をご参照ください。

はじめに

 ActiveReports for .NET(以下ActiveReports)はVisual Studioと統合された使いやすいレポートデザイナや高機能なレポートビューワ、多彩な出力形態をサポートする帳票作成コンポーネントです。

 今回は、複数のデータソースを利用した帳票作成の例と、ActiveReportsのグラフコントロールについて紹介していきます。

これまでの記事

対象読者

  • Visual Basic 2005またはVisual C# 2005を使ってプログラムを作ったことのある方。
  • 帳票作成ツールに興味のある方。

必要な環境

(注:Express EditionではActiveReportsをインストールできません)
  • Visual Studio 2005、Visual Studio .NET 2003でプログラムが作れる環境。

 本記事のサンプルコードはC# 2.0/Visual Basic 2005で記述しています。

ActiveReportsからさまざまなデータソースを利用する

最終的な完成イメージ

 今回のサンプルは、学力テストなどでおなじみの「成績一覧表」です。

成績一覧表 完成イメージ1
成績一覧表 完成イメージ1
成績一覧表 完成イメージ2
成績一覧表 完成イメージ2

 帳票には診断テストを受けた各生徒の氏名、クラスおよび志望校と、これまでの成績がグラフで表示されます。また、末尾には各テストの平均点と偏差値が表形式で表示されます。

データ構造

 今回は「複数のデータソースを組み合わせて1つの帳票を作成する」ことを目的とし、データソースとして「XMLファイル」「Accessデータベース」「SQL Serverデータベース」「Excelワークシート」の4種類を使用します。

生徒データ:XMLファイル(生徒ID、生徒名、クラス、受講科目)
XML形式の生徒データファイル(2007Student.xml)
<?xml version="1.0" encoding="Shift-JIS" ?>
<Year name="2007">
<Grade id="3">
  <student id="0001">
    <name>青木愛子</name>
    <class>A</class>
    <subject>EMJ</subject>
  </student>
  <student id="0002">
    <name>伊藤美佐子</name>
    <class>A</class>
    <subject>EM</subject>
  </student>
  <student id="0003">
    <name>遠藤修作</name>
    <class>B</class>
    <subject>EMJ</subject>
  </student>
  <student id="0004">
    <name>小野田健</name>
    <class>A</class>
    <subject>EMJ</subject>
  </student>
  <student id="0005">
    <name>斉藤はじめ</name>
    <class>A</class>
    <subject>EMJ</subject>
  </student>
  <student id="0006">
    <name>佐藤翔</name>
    <class>A</class>
    <subject>EMJ</subject>
  </student>
  <student id="0007">
    <name>佐藤祐樹</name>
    <class>B</class>
    <subject>EM</subject>
  </student>
</Grade>
</Year>
志望校データ:SQL Serverデータベース(生徒ID、第1志望校、第2志望校)
学校マスタテーブル(SCHOOLテーブル)
学校マスタテーブル(SCHOOLテーブル)
志望校テーブル(CHOICEテーブル)
志望校テーブル(CHOICEテーブル)
テスト結果データ:Accessデータベース(生徒ID、テスト月、各科目の点数)
テスト結果テーブル(ResultOfExamsテーブル)
テスト結果テーブル(ResultOfExamsテーブル)
平均偏差データ:Excelワークシート(過去のテストの平均点・平均偏差)
平均偏差データ
平均偏差データ

帳票レイアウトの概要

帳票レイアウト
帳票レイアウト

 ページヘッダには帳票タイトルを、ページフッタにはページ番号を表示します。次に「学年」単位のグループヘッダ/フッタを追加します。グループヘッダには学年を表示し、グループフッタには統計情報(平均点や偏差値など)を表示します。グループフッタに表示される表にはOleObjectコントロールを使用します。Detailセクションには生徒の氏名、クラス、受講科目、第1、第2志望校とこれまでの成績をグラフで表示するようにします。

 詳細についてはこの後のセクションで順を追って解説していきます。

データソースとしてXMLファイルを利用する

 ActiveReportsでは、RDB(リレーショナルデータベース)やExcelで使われているような「表形式」のデータだけでなく、XMLファイルをデータソースとしてそのまま利用することができます。

 データソースにXMLファイルを設定するには、これまでと同様、Detailセクションに表示されているアイコンをクリックして「レポートデータソース」ダイアログを設定します。「レポートデータソース」ダイアログでは「XML」タブを選択して、ファイルのURLとレコードセットパターンを指定します。レコードセットパターンには、基準となるノードのXPathを設定します。今回はstudentタグの部分が繰り返し項目になるので、レコードセットパターンに「//student」と入力します。

レポートデータソースにXMLを設定する
レポートデータソースにXMLを設定する

 レポートデータソースにXMLファイルとレコードセットパターンを設定すると、レポートエクスプローラの「フィールド」にXMLのデータ構造が展開され、ツリー形式で表示されます。黄色の矢印部分がレコードセットパターンとして設定した箇所です。

レポートエクスプローラに展開されたXML
レポートエクスプローラに展開されたXML

 レポートエクスプローラに表示されている「name」や「@id」などのノードをレポートデザイナにドラッグ&ドロップすると、値をバインドさせたTextBoxコントロールを配置できます。ドロップされたTextBoxコントロールにはコントロール名やプロパティが自動的に設定され、DataFieldプロパティにはバインド先のXPathが設定されます。ここではDetailセクションの「クラス」「受講科目」「氏名」のTextboxコントロールをドラッグ&ドロップで貼り付けます。

 また、他のデータソースから参照したいので生徒のIDもTextBoxとして貼り付けていますが、帳票に表示させる必要はないのでVisibleプロパティをfalseに設定し、非表示の項目とします。このような非表示項目は他の表示項目と見た目が同じでは紛らわしいため、背景色にあえて鮮やかな色を使い、区別できるようにしています。

貼り付けたコントロール例
貼り付けたコントロール例

 基準よりも上位のノードのコントロールを張り付けると、DataFieldプロパティには「../@id」のように相対パス形式でXPathが指定されます。今回はgradeHeaderセクションの「学年」の部分に上位ノードのコントロールを使用しています。

XMLファイルを動的にデータソースとして指定する

 レポートデータソースにXMLファイルを指定すると、レポートエクスプローラに表示されるノードをドラッグ&ドロップしてコントロールを配置できるため大変便利なのですが、ファイルの配置場所やレコードセットパターンがアプリケーション実行時の条件によって変更される場合、事前に固定の値を与えることができません。

 アプリケーション実行時にXML形式のデータソースを動的に設定したい場合は、ActiveReports帳票を実行するアプリケーション側でDataDynamics.ActiveReports.DataSources.XMLDataSourceのインスタンスを生成します。この場合もレポートデザイナでデータソースを設定するのと同じように、FileURLプロパティにはXMLファイルのパスを、RecordSetPatternプロパティにはレコードセットパターンをそれぞれ設定します。以下のサンプルコードでは、ボタンを押下するとビューワにXMLデータソースをバインドした帳票が表示されます。

XMLDataSourceを利用して、動的にデータソースとして指定する(C# 2.0)
private void btnExecute_Click(object sender, EventArgs e)
{
    NewActiveReport1 rpt = new NewActiveReport1();
    DataDynamics.ActiveReports.DataSources.XMLDataSource xmlds
         = new DataDynamics.ActiveReports.DataSources.XMLDataSource();
    try
    {
        // XML文書のファイル名を設定します。
        xmlds.FileURL = @"C:\ActiveReports3\Sample_05\2007Student.xml";
        //データセットパターンを設定します。
        xmlds.RecordsetPattern = "//student";
        if (xmlds.Count == 0)
        {
            rpt.Dispose();
            Console.WriteLine("NoDataError");
            return;
        }
        rpt.DataSource = xmlds;
        rpt.Show();
    }
    catch (DataDynamics.ActiveReports.ReportDataException rde)
    {
        Console.WriteLine(rde.Message);
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex.Message);
    }
}
XMLDataSourceを利用して、動的にデータソースとして指定する(VB.NET 2005)
Private Sub Button1_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) _
        Handles Button1.Click
    Dim report As New NewActiveReport1
    Dim xmlds As _
      New DataDynamics.ActiveReports.DataSources.XMLDataSource
    Try
        xmlds.FileURL = _
          "C:\\ActiveReports3\\Sample_05\\2007Student.xml"
        xmlds.RecordsetPattern = "//student"
        If xmlds.Count = 0 Then
            report.Dispose()
            Console.WriteLine("NoDataError")
            Return
        End If
        report.DataSource = xmlds
        report.Show()
    Catch rdex As DataDynamics.ActiveReports.ReportDataException
        Console.WriteLine(rdex.Message)
    Catch ex As Exception
        Console.WriteLine(ex.Message)
    End Try
End Sub

 XMLDataSourceを使用するときにRecordSetPatternプロパティを設定していないと、ReportDataExceptionが発生し「FileURLが設定されていないか、空です。」というエラーメッセージが表示されます。また、XMLファイルの中身が空であった場合もエラーになります。しかし、設定してあるRecordsetPatternが「間違っていた場合」はエラーが発生せず、データのない(白紙の)レポートが作成されてしまいます。

 この問題を回避するには、上記サンプルコードのようにXMLDataSourceのCountプロパティでデータ件数を確認するか、ActiveReport側のNoDataイベントにコードを記述して処理を停止させる必要があります。

 レポートデザイナでXMLを設定した場合は、設定後すぐにファイルの中身が確認されるので、指定したレコードセットパターンが間違っているとエラーがポップアップ表示されます。また、レポートエクスプローラーのフィールドにも赤字でエラー表示されます。

XMLの設定エラー
XMLの設定エラー

ChartControlを利用したグラフの作成

 ここからは、データソースとして指定したXMLファイルに含まれていない項目の表示部分について説明していきます。

 ActiveReportsで帳票にグラフを描画するには、ChartControlコントロールを利用します。ツールバーからレポートデザイナ上のグラフを描画したい場所へChartControlコントロールをドロップすると、自動的にグラフウィザードが起動します。グラフウィザードでは、画面の指示に従って必要な項目を設定していくことでグラフを作成できます。

 今回はグラフにバインドするデータソース(成績データを取得する部分)をまだ作っていないので、そのままの状態で「完了」ボタンを押し、いったんグラフウィザードを終了します。

グラフウィザード
グラフウィザード

 今回の帳票ではX軸(横軸)に「テスト実施月」を、Y軸(縦軸)にテストの点数を取り、科目ごとに点数をバーで表示する簡単な棒グラフを作成します。

成績グラフ
成績グラフ

 グラフを表示させるためのデータは、Accessデータベースに次のような形式で格納されています。

グラフ表示に必要な成績データ(一部)
グラフ表示に必要な成績データ(一部)

グラフに表示するためのデータを取得する

 グラフは生徒ごとに別々のものを表示する必要があるので、データを取得するには生徒のID番号を指定して試験結果を取得する、以下のようなSQLを考えます。「?」の部分は実行時に生徒のID番号がバインドされます。

グラフ描画に必要なデータを取得するSQL
  SELECT ExamName, MONTH(ExamDate) as ExamDate, StudentID,
         JapaneseScore, MathScore, EnglishScore
    FROM ExamResults
   WHERE StudentID = ?
ORDER BY ExamDate

接続文字列は設定ファイルに書こう

 前回までは便宜のため、ソースコード中に接続文字列を直接記述(ハードコーディング)していましたが、接続先データベースやアカウントの情報をハードコーディングしてしまうと、設定を変えるたびにソースを修正して再ビルドしなくてはならず、非常に不便です。

 今回は、アプリケーション設定ファイル(App.config)に接続文字列を記述しておき、実行時に読み出す方法を紹介します。App.configには接続文字列を記述するためのconnectionStringsセクションが用意されているので、ここに接続文字列と設定名を記述します。ここではAccessデータベースへの接続と、SQL Serverへの接続を追加します。

設定ファイル(App.config)の接続文字列定義例
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <connectionStrings>
    <!--Accessデータベースへの接続-->
    <add name="access"
         connectionString="Provider=Microsoft.Jet.OLEDB.4.0;
         Data Source=C:\ActiveReports3\Sample_05\Students.mdb;
         Persist Security Info=False"/>
    <!--SQL Serverデータベースへの接続-->
    <add name="sqlserver"
         connectionString="Data Source=localhost\sqlexpress;
         Database=Sample05;Trusted_Connection=SSPI;
         Persist Security Info=True;"/>
  </connectionStrings>
</configuration>

 App.configに定義した接続文字列をアプリケーション側で取得するには、System.Configuration.ConfigurationManagerクラスを使用します。ConfigurationManagerクラスを使う場合、ソースの先頭にUsing(VBの場合はImports)ディレクティブを追加するだけでなく、プロジェクトにSystem.Configuration.dllへの参照を追加する必要があります。

接続文字列の取得(C# 2.0)
string connStr
 = ConfigurationManager.ConnectionStrings["access"].ConnectionString;
接続文字列の取得(VB.NET 2005)
Dim connStr = _
 ConfigurationManager.ConnectionStrings("access").ConnectionString

グラフに必要なデータの取得処理

 App.configに接続文字列を記述したら、今度はActiveReports帳票のDetailFormatイベントに、生徒1人分のテスト結果データを取得してグラフを描画するためのコードを追加します。

DetailFormatイベント(C# 2.0)
private void detail_Format(object sender, EventArgs e)
{
    this.chartControl1.Visible = true;
    //XMLの科目コード(EMJなど)を「英・数・国」などの表記に変更
    //subjects(Dictionary型)の初期化はReportStartイベントで行う
    this.txtsubject1.Text
     = subjects[this.txtsubject1.Value.ToString()];

    //クエリの定義
    string query
    = "SELECT ExamName, MONTH(ExamDate) as ExamDate, StudentID, "
    + "JapaneseScore, MathScore, EnglishScore "
    + "FROM ExamResults "
    + "WHERE StudentID = ? "
    + "ORDER BY ExamDate ";

    //設定ファイルから接続文字列を取得する
    string connStr
  = ConfigurationManager.ConnectionStrings["access"].ConnectionString;

    //Accessデータベースに接続し、取得したデータをDataTableに格納する
    DataTable dt = new DataTable();
    using (OleDbConnection conn = new OleDbConnection(connStr))
    {
        OleDbCommand cmd = new OleDbCommand(query, conn);
        cmd.Parameters.Add(new OleDbParameter(
                                 "id", this.txtIdHidden.Value));
        OleDbDataAdapter da = new OleDbDataAdapter(cmd);
        da.Fill(dt);
    }

    //DataTableをChartControlのデータソースに設定する
    this.chartControl1.DataSource = dt;
}
DetailFormatイベント(VB.NET 2005)
Private Sub Detail_Format(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles Detail.Format

    Me.ChartControl1.Visible = True
    'XMLの科目コード(EMJなど)を「英・数・国」などの表記に変更
    'subjects(Dictionary型)の初期化はReportStartイベントで行う
    Me.TextSubject1.Text = subjects(Me.TextSubject1.Value.ToString())

    '設定ファイルから接続文字列を取得する
    Dim connStr = _
 ConfigurationManager.ConnectionStrings("access").ConnectionString

    Dim query _
    = "SELECT ExamName, MONTH(ExamDate) as ExamDate, StudentID, " _
    & "JapaneseScore, MathScore, EnglishScore " _
    & "FROM ExamResults " _
    & "WHERE StudentID = ? " _
    & "ORDER BY ExamDate "

    'Accessデータベースに接続し、取得したデータをDataTableに格納する
    Dim dt As New DataTable
    Using conn As New OleDbConnection(connStr)
        Dim cmd As New OleDbCommand(query, conn)
        cmd.Parameters.Add(New OleDbParameter( _
                                  "id", Me.TxtIdHidden.Value))
        Dim da As New OleDbDataAdapter(cmd)
        da.Fill(dt)
    End Using

    'DataTableをChartControlのデータソースに設定する
    Me.ChartControl1.DataSource = dt
End Sub

取得したデータとChartControlコントロールのマッピング

 グラフ表示に使うデータ取得処理ができあがったら、次はChartControlコントロールとグラフデータの紐付けを行います。プロパティウィンドウの右下に表示されている「グラフ デザイナ」のリンクをクリックすると、グラフデザイナが起動されます。

 グラフデザイナのウィンドウが表示されたら、左側に表示されている「系列」ボタンをクリックし、グラフに表示するアイテム(国語、数学、英語)を追加していきます。左上に表示されている「アイテム追加ボタン」をクリックしてアイテムを追加し、オブジェクト名を「Japanese」とします。また、X軸のデータバインドには「ExamDate」を、Y軸のデータバインドには「JapaneseScore」を入力します。同様の手順で数学(Math)、英語(English)の系列も追加します。

 グラフデザイナではこの他「グラフエリア」「タイトル」「凡例」「概観」などの設定項目を変更することで、グラフの見栄えを設定できます。

プロパティウィンドウの下に「グラフデザイナ」へのリンクが表示される
プロパティウィンドウの下に「グラフデザイナ」へのリンクが表示される
グラフデザイナ
グラフデザイナ
今回グラフデザイナで設定した項目
  • グラフエリア:3Dをオフにする
  • グラフエリア-軸(AxisX)「全般」タブ:種類=カテゴリ軸、最大値=6、タイトル=なし
  • グラフエリア-軸(AxisY)「全般」タブ:種類=数値軸、最大値=100、タイトル=Score
  • グラフエリア-軸(AxisY)「ラベル」タブ:「表示」にチェック
  • タイトル:ヘッダ、フッタを非表示
  • 凡例:「タイトル」タブ→ヘッダ、フッタを非表示
  • 概観:パレットを「Greens」に変更、グラフ全体の背景を白(単色)に変更

OleObjectコントロールによるExcelワークシートの貼り付け

 帳票フッタでは、これまでに実施した学力テストの平均偏差値とテストの平均点を表形式で表示しています。これは、特に複雑なことをやっているわけではなく、Excelワークシートをそのまま表示させています。ActiveReports帳票でExcelワークシートなどのOLEオブジェクトを取り込んで表示するには、OleObjectコントロールを使用します。

Excelファイル
Excelファイル

 OleObjectコントロールをレポートデザイナへドラッグ&ドロップすると、挿入オブジェクトを指定するダイアログが表示されるので、目的のファイルを読み込みます。

OleObject
OleObject
読み込み後
読み込み後

 このコントロールは実行環境にExcelがインストールされていなくてもコントロールの描画を行いますが、実行環境にActiveReports.Interop.dll がないとエラーメッセージが表示されてしまいますので注意が必要です。

OleObjectの描画エラー
OleObjectの描画エラー

 このコントロールはAccessデータベースなどのDB内のOleObjectをバインドする用途でも利用できますが、CanGrowプロパティがないので、固定幅で表示されます。

データソースとしてDataReaderを使用する

 これまではレポートデザイナの「レポートデータソース」ダイアログを利用して帳票に表示するためのデータソースを指定してきましたが、ActiveReportsでは、DataReaderを利用して実行時にデータを取得しながら動的に帳票を生成していくこともできます。ここでは、DataReaderを使用してSQL Serverデータベースに格納されている志望校データにアクセスし、「第1志望校」「第2志望校」に表示する値を取得する手順について説明します。

 DataReaderを使って1レコードづつデータを読み込む場合は、ActiveReports帳票にアンバウンドフィールドを設定し、実行時に読み込んだ値を動的にセットする必要があります。細かい点でいくつか違いはあるものの、大まかには前々回に紹介したようなテキストファイルの読み込みと似たような方法になるといえるでしょう。DataInitializeイベントでアンバウンドフィールドを作成し、FetchDataイベントでデータを1件ずつ取得していきます。

 DataReaderを使って帳票を生成していく手順を大雑把にまとめると、次のようになります。

  1. ReportStartイベントではデータベースに接続し、DataReaderを生成する。
  2. DataInitializeイベントではデータ格納用のアンバウンドフィールドを作成する。
  3. FetchDataイベントでは1件分のデータを取得し、アンバウンドフィールドへ格納する。
  4. ReportEndイベントではDataReaderとデータベース接続をクローズする。

 ここからは、各イベントごとに処理のコードを見ながら説明していきます。

ReportStartイベントの実装

 ReportStartイベントでは、設定ファイル(App.config)から読み込んだ接続文字列をもとにデータベースとの接続を確立し、SQLを発行してDataReaderのインスタンスを取得します。

ReportStartイベント(C# 2.0)
//SqlConnection, SqlDataReader, Dictionaryは
//他のメソッドから参照するのでクラスメンバとして定義
private SqlConnection conn;
private SqlDataReader dataReader;
private Dictionary<string, string> subjects
         = new Dictionary<string, string>();

private void NewActiveReport_ReportStart(object sender, EventArgs e)
{
    //科目コードを名称に変換するためのDictionaryを作る
    subjects["EMJ"] = "英・数・国";
    subjects["EM"]  = "英・数";

    //設定ファイル(App.config)から接続文字列を取得し、
    //データベースに接続する
    conn= new SqlConnection();
    ConnectionStringSettings setting
        = ConfigurationManager.ConnectionStrings["sqlserver"];
    conn.ConnectionString = setting.ConnectionString;
    conn.Open();

    //SqlCommandを生成して実行し、DataReaderを取得する
    string query
    = "SELECT C.STUDENT_ID, S1.SCHOOL_NAME AS CHOICE1, "
    + "S2.SCHOOL_NAME AS CHOICE2 "
    + "FROM CHOICE C "
    + "LEFT OUTER JOIN SCHOOL AS S1 ON S1.SCHOOL_CODE = C.CHOICE1 "
    + "LEFT OUTER JOIN SCHOOL AS S2 ON S2.SCHOOL_CODE = C.CHOICE2 "
    + "ORDER BY C.STUDENT_ID ";
    SqlCommand cmd = new SqlCommand(query, conn);

    dataReader = cmd.ExecuteReader();

}
ReportStartイベント(VB.NET 2005)
'SqlConnection, SqlDataReader, Dictionaryは
'他のメソッドから参照するのでクラスメンバとして定義
Private conn As SqlConnection
Private dataReader As SqlDataReader
Private subjects As New Dictionary(Of String, String)

Private Sub NewActiveReport1_ReportStart(_
        ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.ReportStart
    '科目コードを名称に変換するためのDictionaryを作る
    subjects("EMJ") = "英・数・国"
    subjects("EM") = "英・数"

    '設定ファイル(App.config)から接続文字列を取得し、
    'データベースに接続する
    conn = New SqlConnection
    Dim setting As ConnectionStringSettings
    setting = ConfigurationManager.ConnectionStrings("sqlserver")
    conn.ConnectionString = setting.ConnectionString
    conn.Open()

    'SqlCommandを生成して実行し、DataReaderを取得する
    Dim query _
     = "SELECT C.STUDENT_ID, S1.SCHOOL_NAME AS CHOICE1, " _
     & "S2.SCHOOL_NAME AS CHOICE2 " _
     & "FROM CHOICE C " _
     & "LEFT OUTER JOIN SCHOOL AS S1 ON S1.SCHOOL_CODE = C.CHOICE1 " _
     & "LEFT OUTER JOIN SCHOOL AS S2 ON S2.SCHOOL_CODE = C.CHOICE2 " _
     & "ORDER BY C.STUDENT_ID "
    Dim cmd As New SqlCommand(query, conn)
    dataReader = cmd.ExecuteReader()
End Sub

DataInitializeイベントの処理

 DataInitializeイベントでは、「第1志望校」「第2志望校」を格納するためのアンバウンドフィールドを生成します。ここではフィールド名を「SchoolOfChoice1」「SchoolOfChoice2」とします。

DataInitializeイベント(C# 2.0)
private void NewActiveReport1_DataInitialize(object sender, 
                                             EventArgs e)
{
    this.Fields.Add("SchoolOfChoice1");
    this.Fields.Add("SchoolOfChoice2");
}
DataInitializeイベント(VB.NET 2005)
Private Sub NewActiveReport1_DataInitialize(_
                                 ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.DataInitialize
    Me.Fields.Add("SchoolOfChoice1")
    Me.Fields.Add("SchoolOfChoice2")
End Sub

 コードの記述が終わったら、志望校を表示するTextBoxコントロールのDataFieldプロパティに、先ほど定義した「SchoolOfChoice1」「SchoolOfChoice2」を設定します。

FetchDataイベントの処理

 FetchDataイベントではDataReaderのReadメソッドを実行して、1件分のデータを取得します。データを取得できた場合は、DataInitializeイベントで生成したアンバウンドフィールドに値を設定します。次のデータがなくなったタイミングでFetchEventArgsのEOFプロパティをtrueとし、FetchDataのループ処理を終わります。

FetchDataイベント(C# 2.0)
private void NewActiveReport1_FetchData(object sender, 
                                        FetchEventArgs eArgs)
{
    if (dataReader.Read())
    {
        Fields["SchoolOfChoice1"].Value
          = dataReader["CHOICE1"].ToString();
        Fields["SchoolOfChoice2"].Value
           = dataReader["CHOICE2"].ToString();
        eArgs.EOF = false; //まだ次のデータがある
    }
    else
    {
        eArgs.EOF = true; //もう次のデータはない
    }
}
FetchDataイベント(VB.NET 2005)
Private Sub NewActiveReport1_FetchData( _
        ByVal sender As System.Object, _
        ByVal eArgs As _ 
  DataDynamics.ActiveReports. ActiveReport3.FetchEventArgs) _
        Handles MyBase.FetchData
    If datareader.Read() Then
        Me.Fields("SchoolOfChoice1").Value = _
          dataReader("CHOICE1").ToString()
        Me.Fields("SchoolOfChoice2").Value = _
          dataReader("CHOICE2").ToString()
        eArgs.EOF = False 'まだ次のデータがある
    Else
        eArgs.EOF = True 'もう次のデータはない
    End If
End Sub

ReportEndイベントの処理

 最後に、ReportEndイベントでは、SqlDataReaderとSqlConnectionをクローズします。

ReportEndイベント(C# 2.0)
private void NewActiveReport1_ReportEnd(object sender, EventArgs e)
{
    if (dataReader.IsClosed)
    {
        dataReader.Close();
    }
    if (conn.State != ConnectionState.Closed)
    {
        conn.Close();
    }
}
ReportEndイベント(VB.NET 2005)
Private Sub NewActiveReport1_ReportEnd(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles MyBase.ReportEnd
    If datareader.IsClosed Then
        datareader.Close()
    End If
    If conn.State <> ConnectionState.Closed Then
        conn.Close()
    End If
End Sub
※注意
 今回作成したサンプルでは、XMLファイルで定義されている生徒データと、SQL Serverデータベースに格納されている志望校データの間で、データの件数・順序が一致していることを前提に作成しています。データの件数や順序が保証されない場合はFetchDataイベントで取得した値を毎回チェックし、同期が取れるよう調整する必要があります。

DataReader使用時の注意点

 DataReaderを使うと、最初にデータを1件取得した時点から帳票生成を開始できるため、高速な帳票生成を実現することができます。

 しかし、帳票の生成処理が途中で異常終了するとすべてのデータが揃わず、不完全な帳票が出力されてしまうというデメリットもあります。実際の帳票アプリケーション開発では、別処理で表示するデータの件数をあらかじめ取得しておき、作成された帳票が途中で終了していないかチェックするなどの工夫が必要になります。

 また、データアクセスのコードがActiveReportsの複数のイベントにまたがって実行されるため、エラー処理が複雑になりがちです。万が一エラーが発生してもデータベース接続やDataReaderのクローズ、リソースの解放がが確実に実行されるようにしてください。

おわりに

 今回はXMLファイルやDataReaderをデータソースとして使用する方法と、ActiveReportsでのグラフ表示について紹介しました。

 次回は、今回扱えなかったネットワーク帳票の話題や、ActiveReports帳票の構造の組み方とレスポンスの違いについて紹介する予定です。

  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 宮本奈紗(ミヤモトナサ)

    株式会社システムインテグレータ ERPソリューション部所属。 ERPシステムの設計・開発に従事。業務でActiveReportsを使用。

  • 渡辺俊史(ワタナベトシフミ)

    株式会社システムインテグレータ パッケージ開発部所属。ECサイト構築パッケージの設計・開発に従事。VSUG(Visual Studio User Group) データベース・データアクセスフォーラムリーダー。 blog:t.watanabe weblog

All contents copyright © 2005-2022 Shoeisha Co., Ltd. All rights reserved. ver.1.5