CodeZine(コードジン)

特集ページ一覧

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

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

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

目次

データソースとして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で送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:5分でわかるActiveReports帳票

もっと読む

著者プロフィール

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

    株式会社システムインテグレータ 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