- - PR -
DataSetからのCrystalReports出力について
1
投稿者 | 投稿内容 | ||||||||
---|---|---|---|---|---|---|---|---|---|
|
投稿日時: 2008-06-25 13:35
初投稿です。宜しくお願いします。
VS2005(C#)のWebアプリケーションでCrystalReports for VS2005を用いた帳票を作成しています。 以下のようにしてレポートに出力されるデータを制限しようとしたのですが、レポートファイルに定義しているSQL ServerのView全件が出力されてしまいます。 // レポートに出力するデータを取得 DataSet ds = con.ExecuteQuery("SELECT * FROM dbo.v_Test WHERE column1='01112200001'"); // 取得データのバインド CrystalDecisions.CrystalReports.Engine.ReportDocument cReport = new CrystalDecisions.CrystalReports.Engine.ReportDocument(); cReport.Load(@"Test.rpt"); cReport.SetDataSource(ds); CrystalReportViewer1.ReportSource = cReport; 何か良い解決方法があればご教示願います。 | ||||||||
|
投稿日時: 2008-06-25 14:26
まず con の型を教えてください。 Web の場合はキャッシュが悪さをしている可能性があります。 CrystalReports 側に問題があるとしたら、バウンド レポートになっていることが考えられます。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||
|
投稿日時: 2008-06-25 14:51
早速のご回答、ありがとうございます。
con は独自に開発した SQL Serverへの接続・問合せ・トランザクション処理等、DBアクセスに必要となるメソッドを提供するクラスで、con.ExecuteQueryメソッドは、引き渡されたSQL文を元にクエリを実行して結果を DataSet へ戻す仕組みになっています。 デバッグ実行したところ、ds変数には期待したSQL結果が戻ってきているので、取得データ自身は問題ないと思います。 問題は、バウンドレポートに対するデータの再セットが効かない点だとは認識しているのですが、その回避方法がわからない状態です。 「SQL ServerのViewからデータを絞り込んで、且つ任意のソート順でレポートを出力したい」 上記目的を考慮の上、ご回答頂ければ幸いです。 | ||||||||
|
投稿日時: 2008-06-25 15:53
つまり 「キャッシュ」 が原因ではないということでしょうか? バウンド レポートをやめるか、バウンド レポートに設定されているクエリを変更するほかないと思います。 DataSet を使っている時点でアンバウンド レポートでなければならないと思いますが。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 | ||||||||
|
投稿日時: 2008-06-25 17:31
レポート側でViewを直接参照することを止め、ソリューションにDataSetを追加して、そのDataSetを参照するようにしてみました。
(バウンドレポート→アンバウンドレポートへの切り替え?) @ソリューションエクスプローラの「新しい項目の追加」からデータセットを追加。(DataSet2) ADataSet2の中にDataTableを追加。(dtReport) BDataTableに、レポートが元々参照していたViewと同じ項目を追加。 C以下のようにプログラムを修正。 // レポートに出力するデータを取得 DataSet ds = con.ExecuteQuery("SELECT * FROM dbo.v_Test WHERE column1='01112200001'"); // 取得データのバインド CrystalDecisions.CrystalReports.Engine.ReportDocument cReport = new CrystalDecisions.CrystalReports.Engine.ReportDocument(); cReport.Load(@"Test.rpt"); DataSet2 ds2 = new DataSet2(); foreach (DataRow dr in ds.Tables[0].Rows) { DataSet2.dtReportRow dr2 = (DataSet2.dtReportRow)ds2.Tables[0].NewRow(); dr2.BeginEdit(); for (int iColIdx = 0; iColIdx < ds.Tables[0].Columns.Count; iColIdx++) { dr2[iColIdx] = dr[iColIdx]; } dr2.EndEdit(); ds2.dtReport.AdddtReportRow(dr2); } cReport.SetDataSource(ds2); これにより無事、抽出したデータのみをレポートへ出力することができました。 但し一つ腑に落ちない点があります。 追加した厳密な型指定のDataSetのDataTableに直接、System.Data.DataTableをセットできないのか? (foreachの処理を簡素化したい) 何か良い方法があれば教えてください。宜しくお願いします。 [ メッセージ編集済み 編集者: kuta 編集日時 2008-06-25 17:39 ] | ||||||||
|
投稿日時: 2008-06-26 10:36
自己レスです。
色々試してみましたが、厳密に型指定されたDataSet(プロジェクトに追加する方式のDataSet)へは、DataRow レベルでの値のセットしかできませんでした。 が、やりたいことは出来たので解決とさせて頂きます。 じゃんぬねっと様、適切なヒントをありがとうございました。 CrystalReports に関する技術情報を公開している箇所が少ないので、本件に至るまでに得た情報も含め、まとめとして投稿しておきます。 ◆レポートデータとして Table/View等 を割り当てて CrystalReportViewer で表示させたい場合 (1)Webページに CrystalReportViewer を配置する (2)レポートの編集へ移り、データベースエクスプローラを起動する (3)Table/View等 を割り当てる 【SQL ServerのView へ接続する場合の例】 @接続の新規作成から OLE DB(ADO) を選択し、SQL Native Client を選択する A適切な接続情報を入力 B利用可能なデータソース欄に上記で入力したDBが追加されるので、対象の Table/View等 を選択する ◆レポートデータとして Table/View等 を割り当てて CrystalReportViewer で表示する際に、ユーザ名・パスワードを都度入れるのを抑止したい場合 CrystalDecisions.CrystalReports.Engine.ReportDocument cReport = new CrystalDecisions.CrystalReports.Engine.ReportDocument(); cReport.Load(@"[レポートファイル名(フルパス)]") cReport.SetDatabaseLogon("[DBユーザ]", "[DBユーザのパスワード]"); CrystalReportViewer1.ReportSource = cReport; //(CrystalReportViewer のプロパティで AutoBind = False に設定している場合は以下のメソッドを実行) CrystalReportViewer1.DataBind(); ※SetDatabaseLogon にはいくつかのオーバーロードがあるため、サーバ1・サーバ2で同じViewを定義して切り替えるようなこともできるかも? ◆レポートデータとしてオリジナルで作成した DataSet を割り当てて CrystalReportViewer で表示させたい場合 (1)ソリューションエクスプローラから新しい項目の追加としてデータセットを追加する (2)自動的に表示されるウィザードをキャンセルする (3)ツールボックスから DataTable を選択して追加する (4)取得するデータのカラムを定義して保存する (5)Webページに CrystalReportViewer を配置する (6)レポートの編集へ移り、データベースエクスプローラを起動する (7)プロジェクトに追加した DataSet を割り当てる (8)プロジェクトデータ→ADO.NETデータセットの順に展開すると上記で作成した DataSet が表示されるので、その配下にある DataTable を選択する (9)CrystalReportViewer を配置したページで以下のようにコーディングする // SQL DataAdapter等を用いて System.Data.DataSet へデータを取得する // 例の con はオリジナルに作成したクラスで、con.ExecuteQuery は引数のSQL文の実行結果を System.Data.DataSet へ戻します DataSet ds = con.ExecuteQuery("SELECT * FROM dbo.v_Test WHERE column1='01112200001'"); // ReportDocument の DataSource へ、上記で取得した DataSet の値をセットする CrystalDecisions.CrystalReports.Engine.ReportDocument cReport = new CrystalDecisions.CrystalReports.Engine.ReportDocument(); cReport.Load(@"[レポートファイル名(フルパス)]") DataSet2 ds2 = new DataSet2(); // DataSet2はプロジェクトに追加した、厳密に型指定された DataSet foreach (DataRow dr in ds.Tables[0].Rows) { DataSet2.dtReportRow dr2 = (DataSet2.dtReportRow)ds2.Tables[0].NewRow(); dr2.BeginEdit(); for (int iColIdx = 0; iColIdx < ds.Tables[0].Columns.Count; iColIdx++) { dr2[iColIdx] = dr[iColIdx]; } dr2.EndEdit(); ds2.dtReport.AdddtReportRow(dr2); } cReport.SetDataSource(ds2); CrystalReportViewer1.ReportSource = cReport; ◆CrystalReport上で定義したパラメータフィールドに値をセットしたい場合(方式は2通りあります) @厳密なコーディングを行う方式 CrystalDecisions.Shared.ParameterField paramField = new CrystalDecisions.Shared.ParameterField(); CrystalDecisions.Shared.ParameterFields paramFields = new CrystalDecisions.Shared.ParameterFields(); CrystalDecisions.Shared.ParameterDiscreteValue paramDiscreateValue = new CrystalDecisions.Shared.ParameterDiscreteValue(); paramField = new CrystalDecisions.Shared.ParameterField(); paramDiscreateValue = new CrystalDecisions.Shared.ParameterDiscreteValue(); paramField.Name = "[CrystalReport上で定義したパラメータフィールド名称]"; paramDiscreateValue.Value = "[パラメータフィールド値]"; paramField.CurrentValues.Add(paramDiscreateValue); paramFields.Add(paramField); //(2つ目以降のパラメータ値をセットする場合) paramField = new CrystalDecisions.Shared.ParameterField(); paramDiscreateValue = new CrystalDecisions.Shared.ParameterDiscreteValue(); paramField.Name = "[CrystalReport上で定義したパラメータフィールド2名称]"; paramDiscreateValue.Value = "[パラメータフィールド2値]"; paramField.CurrentValues.Add(paramDiscreateValue); paramFields.Add(paramField); CrystalReportViewer1.ParameterFieldInfo = paramFields; ※パラメータ値は、CrystalReportViewer に DataBind された後にセットしないと適用されません A簡素なコーディングを行う方式(SetParameterValue メソッドの中身は@かも?) CrystalDecisions.CrystalReports.Engine.ReportDocument cReport = new CrystalDecisions.CrystalReports.Engine.ReportDocument(); cReport.SetParameterValue("[CrystalReport上で定義したパラメータフィールド1名称]", "[パラメータフィールド1値]"); cReport.SetParameterValue("[CrystalReport上で定義したパラメータフィールド2名称]", "[パラメータフィールド2値]"); CrystalReportViewer1.ReportSource = cReport; ※パラメータ値は、CrystalReportViewer に DataBind された後にセットしないと適用されません | ||||||||
|
投稿日時: 2008-06-26 21:56
DataTable 以上の層で手動の値変更はできないです。 アンバウンド レポートは多くの場合 DataAdapter を使って DataSet に Fill することでデータを生成することが多いです。 つまり SQL レベルで解決すべき問題かそうでないかですね。
おまとめありがとうございます。 Bind はやはり面倒くさいので (ログオンもしなくてはいけないですし) 避けたいところですね。 _________________ C# と VB.NET の入門サイト じゃんぬねっと日誌 |
1