- PR -

ODBC経由ではないCrystalReportsのDBへの接続

投稿者投稿内容
りんご
ベテラン
会議室デビュー日: 2006/12/21
投稿数: 51
投稿日時: 2007-06-05 15:40
こんにちは。
VB.NET、Visual Studio 2005付属のCrystalReportを使って帳票作成予定です。
またトライアルとしてCrystalReportsのXIも試験使用しており、
データベースはFirebirdです。

どうしても分からないのでここでお尋ねします。
CrystalReportsは、データベースエキスパートからいろいろな接続手段がでて
きますが、左側の利用可能なデータソース欄に、Firebird .Net DATA Providerを
表示することはできないでしょうか?
実際、ODBC接続もできますが、速度テストを行った結果、ODBC経由よりも
Firebirdの.Net DATA Providerを使用した方が早かったのです。
(接続文字列をXMLファイルから読み込む方法です)

そこで、開発に時間がかからないデザイン画面からの開発となれば
ODBCを奨められますが、実際の接続にかかる時間(SELECTやUPDATEなど)は
Providerの方が短いのです。

また、どうしてもデザイナ画面にDBの情報が出ないのであれば(ODBC以外で)、
VBのソースコードをダラダラと書くことになってしまうのですが、
プロジェクトにできるCrystalReports1.rptの中に書いてもいいのでしょうか?
( 触らない方がいいと別のサイトで見ましたが。。)
また、この中に書けないのであれば、Form側に記述するのでしょうか?

ODBCを使用して簡単にレポートができる場合と、Providerを使用して
こんなにソースコードがいるよ という比較をしなければならず、
困惑しています。

更に、DataSetをReportSourceにしている例は見ましたが、
DataSetも結局はODBC経由でつながるため、使えそうにないです・・

コードを使用しているサンプルがあればヒントかURLを
教えて欲しいです。
非連結フィールドにダラダラ書くことになりそうですが・・

どなたかご教授ください。
よろしくお願いいたします。

じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-06-05 16:00
引用:

りんごさんの書き込み (2007-06-05 15:40) より:

また、どうしてもデザイナ画面にDBの情報が出ないのであれば(ODBC以外で)VBのソースコードをダラダラと書くことになってしまうのですが、プロジェクトにできるCrystalReports1.rptの中に書いてもいいのでしょうか?
( 触らない方がいいと別のサイトで見ましたが。。)
また、この中に書けないのであれば、Form側に記述するのでしょうか?


何のために Generator が生成してくれたコードに手を加えたいのでしょうか? DataSource が欲しいのであれば別の場所で実装すべきだと思います。かといって、"Form 側" に記述しなければならないという制約はありません。たとえば、何らかのビジネス ロジック系のクラスの中で記述して頂いても問題ありません。

引用:

ODBCを使用して簡単にレポートができる場合と、Providerを使用してこんなにソースコードがいるよ という比較をしなければならず、困惑しています。


"こんなに" にあたる内容は、Connection の確立、Command の生成、Adapter の生成、DataSet へ Fill。(あとはいくつかの using) これだけだと思います。

引用:

更に、DataSetをReportSourceにしている例は見ましたが、DataSetも結局はODBC経由でつながるため、使えそうにないです・・


意味が良くわからなかったです。何か勘違いしていないでしょうか? FireBird .Net Data Provider を利用して DataSet にデータを汲み出したとします。その後、何かをする必要などはなく CrystalReports に対して参照を渡すだけです。汲み出した後 ODBC の出る幕はありません。DataSet は非接続型のオブジェクトです。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
りんご
ベテラン
会議室デビュー日: 2006/12/21
投稿数: 51
投稿日時: 2007-06-05 16:29
引用:
"こんなに" にあたる内容は、Connection の確立、Command の生成、Adapter の生成、DataSet へ Fill。(あとはいくつかの using) これだけだと思います。



じゃんぬねっと様、ご返信ありがとうございます。
以下にソースを載せましたが、これで接続もFillも実行しています。
が・・実際のReportsのフィールドはどれを使えばいいのか?迷っています。
ODBC経由だと、データベースから該当テーブルのフィールドをドラッグすればいいだけですが、以下のようなソースでは、抽出されたデータをレポートのフィールドに
どうやってリンクするのか悩んでいます。。
式フィールド?を使うのでしょうか?または非連結フィールドにするのでしょうか?


コード:
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        'DATA PROVIDER経由
        If fOpen_XML("STDMST_F", m_hcon) = 0 Then
            MessageBox.Show("DATA PROVIDER STDMST_F 接続成功♪")

            Dim fbconnection1 As New FirebirdSql.Data.FirebirdClient.FbConnection(m_hcon.ConnectionString)
            Dim bbstr As String = "SELECT TAB423.BUMONCD, TAB423.DATE1, TAB423.GOODSCD, TAB423.DAILYCNT, TAB423.DAILYAMT, TAB401SEL.GOODSKJNAME, TAB104SEL.NAME, TAB401SEL.PRICE, TAB423.PRICE"
            bbstr = bbstr & " FROM   TAB401SEL TAB401SEL INNER JOIN (TAB104SEL TAB104SEL INNER JOIN TAB423 TAB423 ON TAB104SEL.KUBUN=TAB423.BUMONCD) ON (TAB401SEL.BUMONCD=TAB423.BUMONCD) AND (TAB401SEL.GOODSCD=TAB423.GOODSCD)"
            bbstr = bbstr & " ORDER BY TAB423.DATE1, TAB423.BUMONCD, TAB423.GOODSCD"

            If fbconnection1.State = ConnectionState.Closed Then
                fbconnection1.Open()
            End If

            Dim _da As New FirebirdSql.Data.FirebirdClient.FbDataAdapter
            _da = New FirebirdSql.Data.FirebirdClient.FbDataAdapter(bbstr, fbconnection1)

            Dim _ds As New DataSet()
            _da.Fill(_ds, "TAB423")

            Dim bs As New BindingSource()
            bs.DataMember = "TAB423"
            bs.DataSource = _ds
            Dim cr1 = New CrystalReport1
            cr1 = Me.CrystalReport11
      cr1.SetDataSource(_ds)

       'Dim row As DataRow
            'For Each row In _ds.Tables("TAB423").Rows
            '    Console.WriteLine(row("GOODSCD").ToString())
            '    CrystalReportsHelper.SetFormulaFieldsText(cr1, "GOODSCD", row("GOODSCD").ToString())
            'Next row

End Sub



非連結フィールドを作成して、以下を適用させましたが、非連結フィールドを、詳細セクション上に配置しても
データがある限り表示するはずもなく、最終レコードのみが適用されてしまいました。。

コード:
Public Shared Function SetFormulaFieldsText(ByVal oReportClass As Cr.ReportClass, ByVal stFieldName As String, ByVal stSetText As String) As Boolean
        Dim oReportObject As Cr.ReportObject = oReportClass.ReportDefinition.ReportObjects(stFieldName)

        ' 該当するフィールドが存在しない場合
        If oReportObject Is Nothing Then
            Return False
        End If

        Dim oFieldObject As Cr.FieldObject = DirectCast(oReportObject, Cr.FieldObject)
        Dim oFormulaField As Cr.FormulaFieldDefinition = DirectCast(oFieldObject.DataSource, Cr.FormulaFieldDefinition)

        oFormulaField.Text = """" & stSetText & """"
        Return True
    End Function




最初にデザイナからODBC経由で全て作成して、そのSQLクエリーを表示して取得したのを、
今度はコードから実行しようとしたのですが、上手くいきません・・
デザイナから作成したCrystalReportsの内部処理(どのフィールドがリンクされているとか、
グループ化されているとか)は何らかの方法で見ることはできないのでしょうか?

CrystalReports初心者です。どうぞよろしくお願いいたします。

じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-06-05 17:22
引用:

りんごさんの書き込み (2007-06-05 16:29) より:

以下にソースを載せましたが、これで接続もFillも実行しています。
が・・実際のReportsのフィールドはどれを使えばいいのか?迷っています。
ODBC経由だと、データベースから該当テーブルのフィールドをドラッグすればいいだけですが、以下のようなソースでは、抽出されたデータをレポートのフィールドにどうやってリンクするのか悩んでいます。式フィールド?を使うのでしょうか?または非連結フィールドにするのでしょうか?


アンバウンド レポートの場合でかつ保守という観点から考えると以下のような方法があると思います。型付 DataSet のまま使うことが望ましいです。

ところで、

引用:

何のために Generator が生成してくれたコードに手を加えたいのでしょうか? DataSource が欲しいのであれば別の場所で実装すべきだと思います。かといって、"Form 側" に記述しなければならないという制約はありません。たとえば、何らかのビジネス ロジック系のクラスの中で記述して頂いても問題ありません。

引用:

意味が良くわからなかったです。何か勘違いしていないでしょうか? FireBird .Net Data Provider を利用して DataSet にデータを汲み出したとします。その後、何かをする必要などはなく CrystalReports に対して参照を渡すだけです。汲み出した後 ODBC の出る幕はありません。DataSet は非接続型のオブジェクトです。


このあたりについては問題なかったでしょうか? 状況を予想して回答しておりますので、意図しない答えになっているのではないかと心配しております。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
りんご
ベテラン
会議室デビュー日: 2006/12/21
投稿数: 51
投稿日時: 2007-06-06 09:38
じゃんぬねっと様、ご返信ありがとうございます。
リンクされているURLを拝見しました。

引用:
デザイン時にはスキーマ (型付 DataSet) を使用してデザインを完了させ、Report に渡す DataSet は型付でない普通の DataSet のインスタンスを渡すなんてのはどうでしょうか?
フィールド数を超えていないか、あるいは式フィールドでの期待した型が一致していれば、Crystal Report Engine 的には問題なく動作するハズです。
これならばデザイン時の可読性もある程度確保できます。



私もこれで悩んでいるのですが、デザイン時にDataSet作成から入り該当するフィールドををデザイナ上から
ドロップしたいのですが、.Net Frame WorkではDataSet作成時には「接続DSN」を聞いてきますよね?
(データソース構成ウィザード⇒新しい接続⇒データソース(ODBC)選択画面)
これはODBC経由で接続しますよ?という意味ではないのでしょうか?

試しにODBC経由で接続して、該当するテーブル1つとビューを2つ選択して、新たにDataSet1を作成しました。
そしてデザイナ上からフィールドをドラッグしてみて、コードを以下のようにしました。

コード:
 Dim fbconnection1 As New FirebirdSql.Data.FirebirdClient.FbConnection(m_hcon.ConnectionString)
            Dim bbstr As String = "SELECT TAB423.BUMONCD, TAB423.DATE1, TAB423.GOODSCD, TAB423.DAILYCNT, TAB423.DAILYAMT, TAB401SEL.GOODSKJNAME, TAB104SEL.NAME, TAB401SEL.PRICE, TAB423.PRICE"
            bbstr = bbstr & " FROM   TAB401SEL TAB401SEL INNER JOIN (TAB104SEL TAB104SEL INNER JOIN TAB423 TAB423 ON TAB104SEL.KUBUN=TAB423.BUMONCD) ON (TAB401SEL.BUMONCD=TAB423.BUMONCD) AND (TAB401SEL.GOODSCD=TAB423.GOODSCD)"
            bbstr = bbstr & " ORDER BY TAB423.DATE1, TAB423.BUMONCD, TAB423.GOODSCD"

            If fbconnection1.State = ConnectionState.Closed Then
                fbconnection1.Open()
            End If

            Dim _da As New FirebirdSql.Data.FirebirdClient.FbDataAdapter
            _da = New FirebirdSql.Data.FirebirdClient.FbDataAdapter(bbstr, fbconnection1)

            Dim _ds As New DataSet1()	’←作成したDataSetです
            _da.Fill(_ds, "TAB423")

            Dim bs As New BindingSource()
            bs.DataMember = "TAB423"
            bs.DataSource = _ds
            Dim cr1 = New CrystalReport1
            cr1 = Me.CrystalReport11



結果は何も表示されませんでした・・

DataSet作成時に、クエリを追加するとかやらないといけないのでしょうか?
また、表示したいフィールドが2つ以上のテーブル(またはビュー)になる場合、
コード:
bs.DataMember = "TAB423"


これではいけないのでしょうか??

引用:
何のために Generator が生成してくれたコードに手を加えたいのでしょうか? DataSource が欲しいのであれば別の場所で実装すべきだと思います。かといって、"Form 側" に記述しなければならないという制約はありません。たとえば、何らかのビジネス ロジック系のクラスの中で記述して頂いても問題ありません。



すみません。イメージ的に、CrystalReports内には、例えばFields_Format とか Reports_Loadとかのイベントが
発生したときのコードを記述する場所はないのかな?と思いまして。。(Accessの帳票のように)

引用:
DataSet は非接続型のオブジェクトです。 このあたりについては問題なかったでしょうか? 状況を予想して回答しておりますので、意図しない答えになっているのではないかと心配しております。



ご心配、大変ありがとうございます。

CrystalReportsを使って、ODBC経由で作成した場合の方法 と .Net DATA Providerを使用する場合の方法を
調査して提出しなければならず、今までCOReportsにVB6でコードをガリゴリ書いてきた社員達に
デバッグする場合はどうやるのだ?から始まってコード以外の場合で作成した場合に
どうすればいいのか困惑しています。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-06-06 10:24
引用:

りんごさんの書き込み (2007-06-06 09:38) より:

私もこれで悩んでいるのですが、デザイン時にDataSet作成から入り該当するフィールドををデザイナ上からドロップしたいのですが、.Net Frame WorkではDataSet作成時には「接続DSN」を聞いてきますよね?(データソース構成ウィザード⇒新しい接続⇒データソース(ODBC)選択画面)これはODBC経由で接続しますよ?という意味ではないのでしょうか?


すみません、手元に環境がないもので確認できないのですが、これは DataSet デザイナ上でのお話でしょうか? それとも CrystalReports デザイナ上でのお話でしょうか? 後者であると思っておりますが、後者であればもともと 「アンバウンド レポート」 なのですから関係ないです。

引用:

結果は何も表示されませんでした・・


それは、

引用:

Dim bs As New BindingSource()
bs.DataMember = "TAB423"
bs.DataSource = _ds
Dim cr1 = New CrystalReport1
cr1 = Me.CrystalReport11


これが無意味だからです。
  1. BindingSource はいつどこで誰に対して使っていますか?
  2. BindingSource はなぜ必要なのですか?
  3. cr1 の DataSource の設定がないのにどうやってデータを表示しますか?
DataSource を作っても何も紐づいていなければ、CrystalReports は何を出力して良いのかわかりません。

引用:

DataSet作成時に、クエリを追加するとかやらないといけないのでしょうか?


いいえ。ソースに問題があるだけだと思います。

引用:

また、表示したいフィールドが2つ以上のテーブル(またはビュー)になる場合、

コード:

bs.DataMember = "TAB423"


これではいけないのでしょうか??


上記にも書きましたが、BindingSource の出番がないです。ReportDocument 側の DataSource と DataMember をご利用ください。

引用:

すみません。イメージ的に、CrystalReports内には、例えばFields_Format とか Reports_Loadとかのイベントが発生したときのコードを記述する場所はないのかな?と思いまして。。(Accessの帳票のように)


それは ActiveReports 的な考え方ですね。CrystalReports の場合、デザイナ側で多く対応するというスタンスを取っています。そのため式フィールドなどでイベント処理を実行するのが一般的です。

引用:

CrystalReportsを使って、ODBC経由で作成した場合の方法 と .Net DATA Providerを使用する場合の方法を調査して提出しなければならず、今までCOReportsにVB6でコードをガリゴリ書いてきた社員達にデバッグする場合はどうやるのだ?から始まってコード以外の場合で作成した場合にどうすればいいのか困惑しています。


ActiveReports の方が良かったのではないでしょうか。Visual Studio 2005 に付属しているという理由で CrystalReports になったのでしょうけど...

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
りんご
ベテラン
会議室デビュー日: 2006/12/21
投稿数: 51
投稿日時: 2007-06-06 12:03
以下でやってみました。

コード:
Dim _da As New FirebirdSql.Data.FirebirdClient.FbDataAdapter
            _da = New FirebirdSql.Data.FirebirdClient.FbDataAdapter(bbstr, fbconnection1)
            Dim _ds As New DataSet1()
            '_da.Fill(_ds, "TAB423")
            _da.Fill(_ds.Tables("TAB423"))
            Dim i, j As Integer
            For i = 0 To _ds.Tables(0).Rows.Count() - 1
                For j = 0 To _ds.Tables(0).Columns.Count() - 1
                    Debug.Write(_ds.Tables(0).Rows(i)(j) & ControlChars.Tab)
                Next
                Debug.Write(ControlChars.NewLine)
            Next

            'Dim bs As New BindingSource()
            'bs.DataMember = "TAB423"
            'bs.DataSource = _ds
            Dim crReportDocument = New CrystalReport1()
            crReportDocument.SetDataSource(_ds)
            CrystalReportViewer1.ReportSource = crReportDocument




レポートのフィールドを、データベースエキスパートから「ADO.NETデータセット」⇒
「プロジェクト内のDataSet1」を選択して、該当するフィールドを一つ配置しました。

結果:帳票のレポートにデータが表示できました。

ですが・・・
そのDataSet1にはテーブルが一つ(TAB423)、ビューが二つ(TAB104SEL、TAB401SEL)が
あり、フィールドでリンクもしているのですが、TAB401SELからフィールドをドロップしても今度は帳票に何も表示されませんでした。。
TAB423(テーブル)のフィールドだけなら表示OKなのです。
これはやはり、Fillの部分がいけないのでしょうか?
DataSet作成では、TAB423TableAdapterが作成され、ソースコードで記述してある
SELECT・・・を記述してFillAAというものを作成しましたが、
これをDirectCast(FBDataAdapter,TAB423TableAdapter)とはできませんでした・・

申し訳ありませんが、もう少しお知恵をお貸しくださいませんか?


引用:
BindingSource の出番がないです。ReportDocument 側の DataSource と DataMember をご利用ください。



すみません・・ReportDocumentにDataSourceもDataMemberもメンバがないのですが・・
私が勘違いしていたようで、BindingSourceは外しました。


引用:
DataSet デザイナ上でのお話でしょうか


そのつもりでしたが・・
CrystalReportsからデザイナを使用して行った場合に、アンバンウンドだから関係ないとおっしゃるのは分かりました。
ありがとうございます。

引用:
ActiveReports の方が良かったのではないでしょうか。


バーコード印刷もあるし、ActiveReportsも候補にあがったのですが・・何しろライセンス料が・・・(−−;)
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2007-06-06 12:28
引用:

りんごさんの書き込み (2007-06-06 12:03) より:

そのDataSet1にはテーブルが一つ(TAB423)、ビューが二つ(TAB104SEL、TAB401SEL)が
あり、フィールドでリンクもしているのですが、TAB401SELからフィールドをドロップしても今度は帳票に何も表示されませんでした。。TAB423(テーブル)のフィールドだけなら表示OKなのです。


ドロップしたところで CrystalReports のエンジンからすれば、リレーションがわからないので何ともできないという理屈はおわかりでしょうか? 関係を持つのであれば、それは明示しなくてはいけません。

引用:

これはやはり、Fillの部分がいけないのでしょうか?


Fill する条件となる SQL コマンドがすべてです。ここで結合された DataTable になるようにすれば良いだけですよね。View で実現できるならば、もう 1 つ View を作って対応しても良いでしょう。(動的な条件であれば、SQL コマンドになります)

引用:

DataSet作成では、TAB423TableAdapterが作成され、ソースコードで記述してあるSELECT・・・を記述してFillAAというものを作成しましたが、これをDirectCast(FBDataAdapter,TAB423TableAdapter)とはできませんでした・・


DataSet デザイナで自動で作成される DataAdapter は、FireBird 専用のデータプロバイダではないため、利用する必要がありません。最初から FBDataAdapter を利用するようにしましょう。

引用:

すみません・・ReportDocumentにDataSourceもDataMemberもメンバがないのですが・・
私が勘違いしていたようで、BindingSourceは外しました。


申し訳ありません。書き込み専用なので SetDataSource メソッドでしたね。ActiveReports の方と混同しておりました。

引用:

引用:

DataSet デザイナ上でのお話でしょうか


そのつもりでしたが・・


だったみたいですね。今回の返答にあった DataAdapter のところを見て気付きました。これは確かに Firebird 専用のデータ プロバイダを使っていません。りんごさんの仰っていたとおりです。

道理で話が噛みあわないと思っていました。私の方でりんごさんが伝えたかった内容を正しく解釈できなかったようです。これに関しては謝罪致します。

引用:

バーコード印刷もあるし、ActiveReportsも候補にあがったのですが・・何しろライセンス料が・・・(−−;)


(私は Grapecity さんの回しものではありません。Grapecitry さんは好きですけど)
ランタイム フリーと考えれば格安だと思いますよ。開発者数にもよりますけど、インストーラを作る端末以外は試用版を使うという手もあります。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌

スキルアップ/キャリアアップ(JOB@IT)