計算や集計を行う
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= ..ActiveReportsNET11\\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=..ActiveReportsNET11\\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=MicrosoftR Visual StudioR 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=MicrosoftR Visual StudioR 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イベント内)に動的に設定することが可能です。詳細は「実行時にデータソースを変更する」を参照して下さい。