DOBON.NET DOBON.NETプログラミング掲示板過去ログ

CrystalReportについて

環境/言語:[OS:XPpro PG:VB.net DB:SQL Server ]
分類:[.NET]

PG:VB.net2003
DB:SQL Server2000
いつもお世話になっております。
現在ストアドで取得した顧客情報をCrystalReportsを用いて
表示を試みているのですが、ストアドでデータを取得後
ReportsのSection3 TextObjectに表示の際に1件しか表示されないのです。
それもそのはずTextObjectはReport側には1個しか用意してないですから・・・
聞きたい事はTextObjectは1個でも取得したレコード数に応じて
TextObjectも動的に生成されるような方法をご存知の方がいらしたら教えていただきたいのです。
このままだとレコード数に応じてTextObject毎に座標を取得しSizeを決めて
出力といった感じになります。
楽で便利な方法があればご教授いただけませんでしょうか?
また以下のコードで"わたしならこうする!"といった指摘があれば合わせてお願い致します。
vb,net側
Sub CUSTOMER_MANAGE_VIEW()
Dim SQLcd As New SqlCommand
Dim SQLdr As SqlDataReader
Dim ParamBankName As SqlParameter
Dim ReportCus As New CustomerReport
Dim ReportSec As Section
Dim CodeText As TextObject

Try

SQLcd.CommandText = "SE_CUSTOMER"
SQLcd.Connection = ClassAccessSQL.SQLcn
SQLcd.CommandType = CommandType.StoredProcedure

ParamBankName = SQLcd.Parameters.Add("@CUSTOMER_NAME", SqlDbType.VarChar, 100)
ParamBankName.Value = Me.txtCustomerName.Text

'接続の為のクラス
ClassAccessSQL.OpenCnSSPI(ServerName, DataBase, False)

SQLdr = SQLcd.ExecuteReader
ReportView.ReportSource = ReportCus
ReportSec = ReportCus.ReportDefinition.Sections("section3")
CodeText = ReportSec.ReportObjects("txtCode")

'データが存在する間データを取得します。
Do While SQLdr.Read()
CodeText.Text = SQLdr!customer_code
Loop

'接続を閉じる
ClassAccessSQL.CloseSQL(False)
Catch ex As SqlException

MsgBox(ex.ToString, 4112, "ERR")

Catch ex As Exception

MsgBox(ex.ToString, 4112, "ERR")

Finally

If ClassAccessSQL.SQLcn.State = 1 Then

SQLdr.Close()
ClassAccessSQL.CloseSQL(False)
Me.txtCustomerName.Focus()

End If

End Try

End Sub

SQL Server側
--ストアドの作成
CREATE PROCEDURE SE_CUSTOMER
(
@CUSTOMER_NAME VARCHAR(100) = NULL
)
AS

--ユーザー名がNULL値なら全行を返します。
IF @CUSTOMER_NAME IS NULL

BEGIN
SELECT
CUSTOMER_CODE,
CUSTOMER_NAME,
ZIP_CODE,
ADDRESS1,
ADDRESS2,
CLOSE_DATE,
PAY_MODE,
PAY_MONTH,
PAY_DAY,
BANK_CODE,
BANK_NAME,
SUB_CODE,
SUB_NAME,
ACCOUNT_TYPE,
ACCOUNT_NO,
CARRYING_FORWARD
FROM CUSTOMER_MANAGE
ORDER BY
CUSTOMER_CODE
END

--NULL値以外ならあいまい検索を実行!
ELSE

BEGIN
SELECT
CUSTOMER_CODE,
CUSTOMER_NAME,
ZIP_CODE,
ADDRESS1,
ADDRESS2,
CLOSE_DATE,
PAY_MODE,
PAY_MONTH,
PAY_DAY,
BANK_CODE,
BANK_NAME,
SUB_CODE,
SUB_NAME,
ACCOUNT_TYPE,
ACCOUNT_NO,
CARRYING_FORWARD
FROM CUSTOMER_MANAGE
WHERE
CUSTOMER_NAME LIKE '%' + @CUSTOMER_NAME + '%'
ORDER BY
CUSTOMER_CODE
END
■No17709に返信(りこさんの記事)
> PG:VB.net2003
> DB:SQL Server2000
> いつもお世話になっております。
> 現在ストアドで取得した顧客情報をCrystalReportsを用いて
> 表示を試みているのですが、ストアドでデータを取得後
> ReportsのSection3 TextObjectに表示の際に1件しか表示されないのです。
> それもそのはずTextObjectはReport側には1個しか用意してないですから・・・
> 聞きたい事はTextObjectは1個でも取得したレコード数に応じて
> TextObjectも動的に生成されるような方法をご存知の方がいらしたら教えていただきたいのです。
> このままだとレコード数に応じてTextObject毎に座標を取得しSizeを決めて
> 出力といった感じになります。
> 楽で便利な方法があればご教授いただけませんでしょうか?
> また以下のコードで"わたしならこうする!"といった指摘があれば合わせてお願い致します。
> vb,net側
> Sub CUSTOMER_MANAGE_VIEW()
> Dim SQLcd As New SqlCommand
> Dim SQLdr As SqlDataReader
> Dim ParamBankName As SqlParameter
> Dim ReportCus As New CustomerReport
> Dim ReportSec As Section
> Dim CodeText As TextObject
>
> Try
>
> SQLcd.CommandText = "SE_CUSTOMER"
> SQLcd.Connection = ClassAccessSQL.SQLcn
> SQLcd.CommandType = CommandType.StoredProcedure
>
> ParamBankName = SQLcd.Parameters.Add("@CUSTOMER_NAME", SqlDbType.VarChar, 100)
> ParamBankName.Value = Me.txtCustomerName.Text
>
> '接続の為のクラス
> ClassAccessSQL.OpenCnSSPI(ServerName, DataBase, False)
>
> SQLdr = SQLcd.ExecuteReader
> ReportView.ReportSource = ReportCus
> ReportSec = ReportCus.ReportDefinition.Sections("section3")
> CodeText = ReportSec.ReportObjects("txtCode")
>
> 'データが存在する間データを取得します。
> Do While SQLdr.Read()
> CodeText.Text = SQLdr!customer_code
> Loop
>
> '接続を閉じる
> ClassAccessSQL.CloseSQL(False)
> Catch ex As SqlException
>
> MsgBox(ex.ToString, 4112, "ERR")
>
> Catch ex As Exception
>
> MsgBox(ex.ToString, 4112, "ERR")
>
> Finally
>
> If ClassAccessSQL.SQLcn.State = 1 Then
>
> SQLdr.Close()
> ClassAccessSQL.CloseSQL(False)
> Me.txtCustomerName.Focus()
>
> End If
>
> End Try
>
> End Sub
>
> SQL Server側
> --ストアドの作成
> CREATE PROCEDURE SE_CUSTOMER
> (
> @CUSTOMER_NAME VARCHAR(100) = NULL
> )
> AS
>
> --ユーザー名がNULL値なら全行を返します。
> IF @CUSTOMER_NAME IS NULL
>
> BEGIN
> SELECT
> CUSTOMER_CODE,
> CUSTOMER_NAME,
> ZIP_CODE,
> ADDRESS1,
> ADDRESS2,
> CLOSE_DATE,
> PAY_MODE,
> PAY_MONTH,
> PAY_DAY,
> BANK_CODE,
> BANK_NAME,
> SUB_CODE,
> SUB_NAME,
> ACCOUNT_TYPE,
> ACCOUNT_NO,
> CARRYING_FORWARD
> FROM CUSTOMER_MANAGE
> ORDER BY
> CUSTOMER_CODE
> END
>
> --NULL値以外ならあいまい検索を実行!
> ELSE
>
> BEGIN
> SELECT
> CUSTOMER_CODE,
> CUSTOMER_NAME,
> ZIP_CODE,
> ADDRESS1,
> ADDRESS2,
> CLOSE_DATE,
> PAY_MODE,
> PAY_MONTH,
> PAY_DAY,
> BANK_CODE,
> BANK_NAME,
> SUB_CODE,
> SUB_NAME,
> ACCOUNT_TYPE,
> ACCOUNT_NO,
> CARRYING_FORWARD
> FROM CUSTOMER_MANAGE
> WHERE
> CUSTOMER_NAME LIKE '%' + @CUSTOMER_NAME + '%'
> ORDER BY
> CUSTOMER_CODE
> END
>
すみません!
レスがついてないので
解決していないのですが、
別のCrystalReportのサイトに掲載してみますので
解決済みとさせていただきます。
ありがとうございました。
解決済み!
どちらへ投稿されたのか、教えていただければ幸いです。また、解決していませんので、解決済みにはしないでください(別のサイトで解決されたということであれば、どのように解決されたのか教えていただければ幸いです)。
■No17709に返信(りこさんの記事)
> 現在ストアドで取得した顧客情報をCrystalReportsを用いて
> 表示を試みているのですが、ストアドでデータを取得後
> ReportsのSection3 TextObjectに表示の際に1件しか表示されないのです。
> それもそのはずTextObjectはReport側には1個しか用意してないですから・・・

まず、Section3 と言われているセクションが、'何であるのか' 全くわかりません。
詳細セクションではないのだから、繰り返し出力されないのは当然と仰りたいのでしょうか?

では、詳細セクションを使わないのはなぜでしょうか?

> 聞きたい事はTextObjectは1個でも取得したレコード数に応じて
> TextObjectも動的に生成されるような方法をご存知の方がいらしたら教えていただきたいのです。

仮に、あるグループ ヘッダーのセクションに配置したとしても、
そのグループにキーを設けていなければ、繰り返し処理されます。

ここまで読んで予想できることは、DataSource を使っていないという基本的なミステイクです。
ミステイクというよりは、CrystalReports の基本的な仕組みがおわかりになっていないという印象です。

> Sub CUSTOMER_MANAGE_VIEW()

COBOL じゃないのですから全部大文字にするのはやめた方が良いでしょう。
なるべく、一般的な名前付けのガイドラインに従うようにしましょう。
http://msdn2.microsoft.com/ja-jp/library/ms229002.aspx

> Dim ReportSec As Section
> Dim CodeText As TextObject
>
> (snip)
>
> ReportSec = ReportCus.ReportDefinition.Sections("section3")
> CodeText = ReportSec.ReportObjects("txtCode")

やはり、DataSource を使わずに直接レポート フィールドに埋めようとしていますね。
これでは、単票形式のレポートしか出力できないです。

> レスがついてないので

なぜ、レスがつかないのかを逆に考えたことはありますでしょうか?
じゃんぬねっとさんレスありがとうございます。
> ミステイクというよりは、CrystalReports の基本的な仕組みがおわかりになっていないという印象です。
↑そのとおりです。書籍(書籍自体も少ないんですね。)をよんではみたもののコードで実現する内容ではなくあちこちのサイトを拝見し勉強中です。
>>Sub CUSTOMER_MANAGE_VIEW()
> COBOL じゃないのですから全部大文字にするのはやめた方が良いでしょう。
> なるべく、一般的な名前付けのガイドラインに従うようにしましょう。
> http://msdn2.microsoft.com/ja-jp/library/ms229002.aspx
↑失礼しました。参考になります。

> やはり、DataSource を使わずに直接レポート フィールドに埋めようとしていますね。
Datasetを使用してDataSourceに渡すという感じになるのでしょうか?

> これでは、単票形式のレポートしか出力できないです。
↑帳票形式を目指してます。
今、別の方法を思案中ですが・・・正直行き詰ってます。
追伸です。
管理人さん別のサイトへは現在投稿しておりませんので
ご報告させていただきます。
■No17746に返信(りこさんの記事)
> ↑そのとおりです。書籍(書籍自体も少ないんですね。)をよんではみたもののコードで実現する内容ではなくあちこちのサイトを拝見し勉強中です。

確かに、日本語圏では情報は少ないですよね。(つらいところです)
ほとんどフィーリングがモノを言うと思います。

> Datasetを使用してDataSourceに渡すという感じになるのでしょうか?

そのとおりですね。
わかっていらっしゃるじゃないですか。(^^)

> 今、別の方法を思案中ですが・・・正直行き詰ってます。

上記方法で良いです。

デザイナで作成した帳票は、ReportDocument クラスです。(実際には違いますが、そう考えてください)
そのメンバに SetDataSource メソッドがありますので、ここで DataSet を渡してください。
リコです。
みなさん今一度チカラを貸して下さい。
データセットの中に以下のようにストアドでとってきた値を格納してますが
中身が空になってしまいます?!
データグリッドでも確認したのですがやはり空です。
CrystalReportsにはデザイナで作成したデータセットからフィールドをセットしてます。
Dim SQLcd As New SqlCommand
Dim SQLdr As SqlDataReader
Dim SQLds As New CustomerDS
Dim SQLdt As New CustomerDS.T_CUSTOMERDataTable
Dim SQLro As CustomerDS.T_CUSTOMERRow
Dim ParamBankName As SqlParameter
Dim ReportCus As New CustomerReport

Try

SQLcd.CommandText = "SE_CUSTOMER"
SQLcd.Connection = ClassAccessSQL.SQLcn
SQLcd.CommandType = CommandType.StoredProcedure

'パラメータの生成
ParamBankName = SQLcd.Parameters.Add("@CUSTOMER_NAME", SqlDbType.VarChar, 100)
ParamBankName.Value = Me.txtCustomerName.Text

'接続用のクラス
ClassAccessSQL.OpenCnSSPI(ServerName, DataBase, False)

SQLdr = SQLcd.ExecuteReader

'データが存在する間データを取得します。
SQLds.Clear()

Do While SQLdr.Read()
SQLro = SQLdt.NewRow()
SQLro.BeginEdit()
SQLro("CUSTOMER_CODE") = 1 'SQLdr!CUSTOMER_CODE
SQLro("CUSTOMER_NAME") = 2 'SQLdr!CUSTOMER_NAME
SQLro.EndEdit()
SQLdt.Rows.Add(SQLro)
Loop

ReportCus.SetDataSource(SQLds)
ReportView.ReportSource = ReportCus

'接続を閉じます。
ClassAccessSQL.CloseSQL(False)

'エラー処理
Catch ex As SqlException

MsgBox(ex.ToString, 4112, "ERR")

Catch ex As Exception

MsgBox(ex.ToString, 4112, "ERR")

Finally

If ClassAccessSQL.SQLcn.State = 1 Then

SQLdr.Close()
ClassAccessSQL.CloseSQL(False)
Me.txtCustomerName.Focus()

End If

End Try
■No17776に返信(りこさんの記事)
リコです。
やっとやっとできました!!!
感激です!
Datasetを一からつくり直して、コードを書き直しました。
結果を掲載します!
それから じゃんぬねっと さんありがとうございました。
結果の報告が遅れたことをこの場をかりてお詫びします。
Private Sub Vendor_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

Dim SQLcd As New SqlCommand
Dim SQLdr As SqlDataReader
Dim ParamBankName As SqlParameter
Dim ParamSubName As SqlParameter
Dim ds As New CustomerDs
Dim dt As DataTable
Dim dtrow As DataRow
Dim Cr As New CustomerReport
Try
dt = ds.CustomerManage

SQLcd.CommandText = "SE_CUSTOMER"
SQLcd.Connection = ClassAccessSQL.SQLcn
SQLcd.CommandType = CommandType.StoredProcedure
'BANK_NAME
ParamBankName = SQLcd.Parameters.Add("@CUSTOMER_NAME", SqlDbType.VarChar, 100)
ParamBankName.Value = Me.txtCustomerName.text
'接続するためのクラス
      ClassAccessSQL.OpenCnSSPI(ServerName, DataBase, False)

SQLdr = SQLcd.ExecuteReader

'データが存在する間データを取得します。
Do While SQLdr.Read()
dtrow = ds.CustomerManage.NewRow()
dtrow("CustomerCode") = SQLdr!CUSTOMER_CODE
dtrow("CustomerName") = SQLdr!CUSTOMER_NAME
dtrow("ZipCode") = SQLdr!ZIP_CODE
dt.Rows.Add(dtrow)
Loop

Cr.SetDataSource(ds)
Me.CustomerReportViewer.ReportSource = Cr
    
    'エラー処理
Catch ex As SqlException

MsgBox(ex.ToString, 4112, "ERR")

Catch ex As Exception

MsgBox(ex.ToString, 4112, "ERR")

Finally
'接続を閉じます。
If ClassAccessSQL.SQLcn.State = 1 Then

SQLdr.Close()
ClassAccessSQL.CloseSQL(False)
Me.txtCUSTOMER_CODE.Focus()

End If

End Try

End Sub
End Class
■No17976に返信(りこさんの記事)
> ■No17776に返信(りこさんの記事)
リコです。
解決済みにCheckをわすれました!
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板