計算や集計を行う
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イベント内)に動的に設定することが可能です。