ActiveReports for .NET 18.0J
データベース
ActiveReportsユーザーガイド > よくある質問 > セクションレポート > データベース

計算や集計を行う

ActiveReports for .NETでは、データベースから取得したデータの集計や加工を行う方法が、いくつか提供されています。それは、データの構成やレポートのレイアウトによって方法が異なってきます。DataInitialize、FetchData、BeforePrintの各イベント、SummaryXXXX、DataFieldの各プロパティが、集計処理を行うために重要となります。また、グルーピングや改ページなどのレイアウトはNewPage、KeepTogether、GroupKeepTogetherなどのプロパティに影響されます。

複数のテーブルを持ったDataSetのデータを表示する

通常、1つのレポートレイアウトファイルは、1つのテーブルのみを参照することができます。複数のテーブルを1つの帳票に出力する方法としては、サブレポートを使用する方法がございます。

テーブル内のフィールドとリレーションをもつ別のテーブル内のデータを取得し、1つの帳票内に出力することができます。詳細については、製品付属の[サブレポート サンプル]内の「サブレポートを使用して複数のテーブルを持ったDataSetを表示する」などをご参照ください。

データが1件も存在しない場合の処理

バウンドレポートとアンバウンドレポートのどちらを作成するかによって、処理が異なります。

バウンドレポートの場合

データが存在しない場合には、NoDataイベントが発生します。
NoDataイベント内でCancelメソッドを実行することで、レポートの生成処理をキャンセルし、ページヘッダ/フッタのみのレポートが出力されることを回避することが可能です。

Visual Basic

Visual Basic コード
コードのコピー
Private Sub SectionReport1_NoData(sender As Object, e As System.EventArgs) Handles MyBase.NoData  
    Me.Cancel()  
End Sub

C#

C# コード
コードのコピー
private void SectionReport1_NoData(Object sender, System.EventArgs e)
{
    this.Cancel();
}

Cancelメソッドによりレポートの生成処理がキャンセルされた場合、CurrentPageプロパティがNothingのままになりますので、下記のコードのような処理でデータが無かったことを判断することが可能です。

Visual Basic

Visual Basic コード
コードのコピー
Dim rpt As New SectionReport1  
rpt.Run()  
If (rpt.CurrentPage Is Nothing)
    Then  
    Console.WriteLine("データが存在しません。")  
End If

C#

C# コード
コードのコピー
SectionReport1 rpt = new SectionReport1();  
rpt.Run();  
if (rpt.CurrentPage == null)  
{  
    Console.WriteLine("データが存在しません。");  
}

アンバウンドレポートの場合

レポート生成(Runメソッドを実行)前に、データベース接続を行いデータが存在するかどうかを判定します。存在しない場合に、必要な処理を行ってください。

Visual Basic

Visual Basic コード
コードのコピー
Dim m_cnnString As String  
Dim sqlString As String  
Dim m_cnn As System.Data.OleDbOleDb.OleDbConnection  
Dim m_reader As System.Data.OleDbOleDb.OleDbDataReader  
Private Sub Form1_Load(ByVal sender As _
System.Object, ByVal e As System.EventArgs) Handles MyBase.Load  
    Dim rpt As New SectionReport1()  
    m_cnnString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source= ..Data\\Nwind.mdb; Persist Security Info=False"  
    SqlString = "SELECT * FROM Products where ProductID = 100"  
    m_cnn = New OleDb.OleDbConnection(m_cnnString)  
    Dim m_Cmd As New OleDb.OleDbCommand(SqlString, m_cnn)  
    If m_cnn.State = ConnectionState.Closed 
        Then  
        m_cnn.Open()  
    End If  
    m_reader = m_Cmd.ExecuteReader()  
    If m_reader.Read = False
        Then  
        MessageBox.Show("データが存在しません。")  
    Else  
        m_reader.Close()  
        m_reader = m_Cmd.ExecuteReader()  
        Me.Viewer1.Document = rpt.Document  
        rpt.Run()  
    End If  
End Sub

C#

C# コード
コードのコピー
private static System.Data.OleDb.OleDbConnection m_cnn;  
private static System.Data.OleDb.OleDbDataReader m_reader;  
private void Form1_Load(object sender, EventArgs e)  
{  
    SectionReport rpt = new SectionReport();  
    string m_cnnString = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=..Data\\Nwind.mdb; Persist Security Info=False";  
    string sqlString = "SELECT * FROM Products where ProductID = 100";  
    m_cnn = new System.Data.OleDb.OleDbConnection(m_cnnString);  
    System.Data.OleDb.OleDbCommand m_Cmd = new System.Data.OleDb.OleDbCommand(sqlString, m_cnn);  
    if (m_cnn.State == ConnectionState.Closed)  
    {  
        m_cnn.Open();  
    }  
    m_reader = m_Cmd.ExecuteReader();  
    if (m_reader.Read() == false)  
    {  
        MessageBox.Show("データが存在しません。");  
    }  
    else  
    {  
        m_reader.Close();  
        m_reader = m_Cmd.ExecuteReader();  
        this.viewer1.Document = rpt.Document;  
        rpt.Run();  
    }  
}

ページヘッダに次レコードのデータが出力される

ページヘッダセクションは基本的に、各ページの先頭に表示する必要のあるカラムヘッダやページ番号、またはページタイトルといった、レコードの内容に関係しない情報を出力します。ページヘッダやページフッタ上に、レコードごとに値が変化するバウンドコントロール(データベースに連結したコントロール)を配置することはお勧めしません。

改ページやグループの切り替わりは該当レコードを読み込むまで判断できない為、改ページ時やグループ変化時にはデータの先読みが発生します。このような理由から、ページヘッダにレコードのデータを出力しているような場合には、そのページの1レコード目ではなく2レコード目の内容が出力される場合があります。

レコードの内容を各ページの先頭に表示したい場合には、ページヘッダセクションではなくグループヘッダセクションを使用します。グループヘッダセクションの RepeatStyle プロパティを OnPage や OnPageIncludeNoDetail に設定することで、グループヘッダセクションは各ページの先頭に出力されます。

重複したデータを非表示にする

セクションが描画される直前に発生するBeforePrintイベントや、描画された後に発生するAfterPrintイベントを利用することで、重複データの非表示動作が可能です。

たとえば下記のコードでは、重複データは非表示にした上で、各ページの描画処理が完了したときに発生するPageEndイベントを利用し、改ページ後最初のデータは必ず出力するようにしています。こちらを参考にご検討ください。

Visual Basic

Visual Basic コード
コードのコピー
Dim strBuff As String

Private Sub Detail1_BeforePrint(sender As System.Object, e As System.EventArgs) Handles Detail1.BeforePrint
    strBuff = ""
    If (TextBox1.Text <> strBuff)
        Then
        TextBox1.Visible = True
    Else
        ' 重複データは非表示にします。
        TextBox1.Visible = False
    End If
    strBuff = TextBox1.Text
End Sub

Private Sub ActiveReport1_PageEnd(ByVal sender As Object, ByVal e As System.EventArgs) Handles MyBase.PageEnd
    ' 改ページ後、最初のデータは必ず出力します。
    strBuff = ""
End Sub

C#

C# コード
コードのコピー
string strBuff;

private void Detail_BeforePrint(object sender, System.EventArgs eArgs)
{
    strBuff = "";
    if (TextBox1.Text != strBuff)
    {
        TextBox1.Visible = true;
    }
    else
    {
        // 重複データは非表示にします。
        TextBox1.Visible = false;
    }
    strBuff = TextBox1.Text;
}

private void rptSimpleGroup_PageEnd(object sender, System.EventArgs eArgs)  
{
    // 改ページ後、最初のデータは必ず出力します。
    strBuff = "";
}

ODBCデータ ソースを使用する

設計時に直接ODBCデータソースをレポートに設定することができます。ODBCデータソースに接続する前に、ODBCドライバをインストールしてODBCデータソースを設定する必要があります。詳細については、「レポートとデータソースの連結」を参照してください。

また、実行時に .NET Framework Data Provider for ODBCを使用してデータソースを取得する方法で使用することができます。[プロジェクト] メニューの [参照の追加] をクリックし、System.Data.ODBCに対する参照を設定します。

Visual Basic

Visual Basic コード
コードのコピー
Private Sub SectionReport1_ReportStart(sender As System.Object, e As System.EventArgs) Handles MyBase.ReportStart
    ' データベースと連結します。
    Dim m_cnn As OdbcConnection
    Dim m_cnnString As String = ("Dsn=Nwind;trusted_connection=Yes;app=Microsoft® Visual Studio® 2010;wsid=SystemID;database=Northwind")
    Dim sqlString As String = "SELECT * FROM Products"
    m_cnn = New OdbcConnection(m_cnnString)
    Dim m_Cmd As OdbcCommand = New OdbcCommand(sqlString, m_cnn)
    m_cnn.Open()
    ' DataReaderと連結します。
    Dim m_reader As OdbcDataReader
    m_reader = m_Cmd.ExecuteReader()
    Me.DataSource = m_reader
End Sub

C#

C# コード
コードのコピー
private void SectionReport1_ReportStart(object sender, EventArgs e)
{
    // データベースと連結します。
    OdbcConnection m_cnn = default(OdbcConnection);
    string m_cnnString = ("Dsn=Nwind;trusted_connection=Yes;app=Microsoft® Visual Studio® 2010;wsid=SystemID;database=Northwind");
    string sqlString = "SELECT * FROM Products";
    m_cnn = new OdbcConnection(m_cnnString);
    OdbcCommand m_Cmd = new OdbcCommand(sqlString, m_cnn);
    m_cnn.Open();
    // DataReaderと連結します。
    OdbcDataReader m_reader = default(OdbcDataReader);
    m_reader = m_Cmd.ExecuteReader();
    this.DataSource = m_reader;
}

レポートのデータソースにストアドプロシージャを使用する

ActiveReportsから直接ストアドプロシージャを呼び出すことはできません。しかしながら、ActiveReportオブジェクトのDataSourceプロパティには、.NET FrameworkのDataSetをセットできます。あらかじめ、DataSetにストアドプロシージャの結果セットを格納しておき、それをActiveReportオブジェクトDataSourceプロパティにセットすることで、ストアドプロシージャで取得したデータを元に、レポートを作成できます。

DataSetをデータソースとしてレポートを作成する方法については、「サブレポート サンプル」を参照してください。

DataSetの作成方法については、マイクロソフト社のWebサイトで公開しているサポート技術情報をご覧ください。

CSVや配列データを元にレポートを作成する

ActiveReportsの基本的なレポート生成方法には、データソースとレポートを直接接続するバウンドレポートと、コード上でデータをセットするアンバウンドレポートがあります。

バウンドレポートの場合、.NET Framework標準の下記データソースとの接続が可能です。

たとえば、ArrayListクラスは、IListインターフェイスを実装していますので、CSVファイルや、配列に格納されたデータをあらかじめArrayListに格納しておけば、これをレポートのデータソースとして使用することが可能です

アンバウンドレポートの場合、データソースへの接続やレコードの移動、データのセット等の処理は、すべてコードで行うことになりますので、一般的なデータソース以外にも、たとえばテキストファイルや配列に格納されたデータなど、さまざまなデータを元にレポートを生成することが可能です。

詳細情報は、製品付属の「IListバインドサンプル」および「アンバウンドサンプル」を参照してください。

パラメータ付きレポートを実行すると、「System.Data...」例外が発生する

パラメータ付きレポートを実行すると、'System.Data.OleDb.OleDbException'のハンドルされていない例外が発生します。

レポートをアクセスデータベースに接続したとき、パラメータを含むSQLクエリで日付フィールドの場合は「#」、または、文字列フィールドの場合は引用符を設定する必要があります。詳細は、以下のSQLクエリをご参照ください。

SQLクエリ
コードのコピー
#%InvoiceDate | Choose invoice date: | 11/2/04 | D | True%#

または、

SQLクエリ
コードのコピー
"%Country | Country: | Germany | S | True%"

パラメータを設定すると、レポートエクスプローラのフィールドにエラーが発生する

SQLクエリでパラメータを設定するときデフォルト値が設定されていない場合は、レポートエクスプローラのテキスト型フィールドおよび日付型フィールドでエラーが発生します。以下の構文をSQLクエリに設定し、エラーを回避できます。

SQLクエリ
コードのコピー
%Name | PromptString | DefaultValue | DataType | PromptUser%

または、

SQLクエリ
コードのコピー
%Name | | DefaultValue | |%

該当レコードまでの累積値を出力する

以下のように、該当レコードまでの累積値(累計)を表示する方法は、レポートの形式によって異なります。

データ 累積値
10 10
20 30
30 60
40 100
50 150

 

TextBoxコントロールの集計機能(Summary***プロパティ)を Detailセクション上に配置することで、その行(レコード)までの累積値を出力できます。

出力したい値に応じてTextBoxコントロールの各プロパティを以下のように設定してください。


レポート全体の累積値を出力する場合
 

  DataField = (対象のフィールド名)
 SummaryFunc = Sum
 SummaryGroup = (空白)
 SummaryRunning = Group または All
 SummaryType = GrandTotal


グループ単位の累積値を出力する場合


 DataField = (対象のフィールド名)
 SummaryFunc = Sum
 SummaryGroup = (対象グループのグループヘッダ名)
 SummaryRunning = Group または All
 SummaryType = SubTotal

レポートのデータソース(接続文字列やSQL文など)を動的に変更する

セクションレポートのデータソースは、レポートの作成前(Runメソッド実行前またはReportStartイベント内)に動的に設定することが可能です。

関連トピック