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

Datasetへの項目セットについて

環境/言語:[環境xp 使用言語VB.NET ]
分類:[.NET]

お世話になります。
テーブル2つに対して、項目をセットをしているのですが、table(1)だけ
一度の命令で全行に同じ値がセットされてしまいます。

table(0)の場合
dr = Dataset.Tables(0).NewRow() '列をあたらしく作る
dr(2) = strTemp(intCnt)     '項目をセットする
Dataset.Tables(0).Rows.Add(dr)  'データセットに行を追加
結果
111
222
333
実際に命令の1行目から3行目はループさせていて、それぞれ別の項目が入っています。

table(1)の場合
ds = Dataset.Tables(1).NewRow() '列をあたらしく作る
ds(0) = "*****"         '項目をセットする
Dataset.Tables(1).Rows.Add(ds) 'データセットに行を追加
結果
***** 
*****
*****
1回しか命令を通ってないはずなんですが、行数分だけ同じ項目がセットされています。私の想定では、1行目だけ"*****"が表示されると思うのですが・・・
列へのセットの仕方が間違っているのでしょうか?
■No22883に返信(KYOUさんの記事)
プログラムを1行実行する毎に Tables(1) のデータを
確認して、どの命令でデータが変更されているか調べて
ください。
■No22884に返信(るしぇさんの記事)
> ■No22883に返信(KYOUさんの記事)
> プログラムを1行実行する毎に Tables(1) のデータを
> 確認して、どの命令でデータが変更されているか調べて
> ください。
るしぇさんお返事ありがとうございます。

1行実行毎に確認してみたのですが、やはりtable(1)はds(0) = "*****"でセット
しているだけで、行数分セットされていました。
なぜかわからいないのですが、table(0)で作った行数分、table(1)が作られています。
■No22892に返信(KYOUさんの記事)
> なぜかわからいないのですが、table(0)で作った行数分、table(1)が作られています。
ですから、分からないなら調べてください。
少なくとも Table が作成されたコードから1行1行確認すれば
どの命令で行数が増えてるかは特定できるでしょう?

どの命令の前でどのように確認した結果がどうなっており、
その命令の後で結果がどうかわっているのですか?
省略せず、こちらで再現できるように説明してください。

> 1行実行毎に確認してみたのですが、やはりtable(1)はds(0) = "*****"でセット
この表現も正確ではないと思います。ds の変数宣言が抜けているので妙なことを
している可能性もありますが、DataRow で宣言してあると仮定して、新しい行に
"*****"でセットしただけではデータはテーブルに反映されません。

Dataset.Tables(1).Rows.Add(ds)の前後で Tables(1) に反映されるはずです。
Add の前でどのようなコードでデータを確認し、実行後に同じコードで確認すると
どう変わっていましたか?こちらでコピペするだけで動作確認できるサンプルコード
が理想です。
2008/09/02(Tue) 16:15:54 編集(投稿者)
2008/09/02(Tue) 16:13:12 編集(投稿者)
2008/09/02(Tue) 16:13:10 編集(投稿者)
2008/09/02(Tue) 16:12:51 編集(投稿者)

るしぇさんお返事ありがとうございます。

長文になりますが、サンプルコードを張らせていただきます。

Dim strLine As String '
Dim ictr As Integer 'インプットカウンタ
Dim strTemp() As String  ' 
Dim intCnt As Integer 'カラム用カウンタ
Dim dr As DataRow
Dim ds As DataRow

'CSVの取り込みボタンを押して、DataSet.Tables(0)に取り込みます。

Private Sub ButtonDlog_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonDlog.Click
On Error Resume Next
Dim MyDialog As New OpenFileDialog
MyDialog.Filter = "CSVファイル (*.csv)|*.csv"
MyDialog.InitialDirectory = "C:\"
MyDialog.ShowDialog()
If MyDialog.FileName.Trim <> vbNullString Then TextBoxPath.Text = MyDialog.FileName
MyDialog.Dispose()
SendKeys.Send(Constants.vbTab)
'参照されたファイルを読込む
Dim objFile As New System.IO.StreamReader(MyDialog.FileName, System.Text.Encoding.Default)


dr = Dataset.Tables(0).NewRow()
strLine = objFile.ReadLine()

While (strLine <> "")

'フィールドを分割して、配列にセット
strTemp = Split(strLine, ",")

'列のあたらしく作る
dr = Dataset.Tables(0).NewRow()

For intCnt = 0 To UBound(strTemp)

'フィールド毎にレコードを分解
Select Case intCnt
Case 0
dr(2) = strTemp(intCnt) 'カラム毎に項目セット
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
dr(40) = strTemp(intCnt)
End Select

Next
'データセットに行を追加
Dataset.Tables(0).Rows.Add(dr)
End While
End Sub


'エラー情報のデータをDataSet.Tables(1)に追加する。
' 項目チェック
Private Sub ButtonRun_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonRun.Click
'エラー情報用に行をあたらしく作る
ds = DataSet.Tables(1).NewRow()
ds(0) = "*****"
'エラー情報用にデータセットに行を追加()
DataSet.Tables(1).Rows.Add(ds)
End Sub



☆の時点でデータセットを確認してみますと、
結果
111・・・・・ (DataSet.Tables(0)(0))
222・・・・・ (DataSet.Tables(0)(1))
333・・・・・ (DataSet.Tables(0)(2))
のようにCSVデータが正しく入っています。

★の時点でみてみると
結果
111・・・・・ (DataSet.Tables(0)(0))
*****・・・・ (DataSet.Tables(1)(0))
222・・・・・ (DataSet.Tables(0)(1))
*****・・・・ (DataSet.Tables(1)(1))
333・・・・・ (DataSet.Tables(0)(2))
*****・・・・ (DataSet.Tables(1)(2)) とデータセットに入っております。
CHECKのモジュールは1度だけしか通らないことは確認しました。
1回しか命令を通らなければ、
111・・・・・ (DataSet.Tables(0)(0))
*****・・・・ (DataSet.Tables(1)(0))
222・・・・・ (DataSet.Tables(0)(1))

333・・・・・ (DataSet.Tables(0)(2))

となると思いますが、一気に3行分追加されています。
1行ずつみていくと、最後の”DataSet.Tables(1).Rows.Add(ds)”
で一気に追加されています。なぜ一気に3行分追加されるのかご教授願えないでしょうか?
KYOUさん

> ' 項目チェック
> Private Sub ButtonRun_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonRun.Click
> 'エラー情報用に行をあたらしく作る
> ds = DataSet.Tables(1).NewRow()
> ds(0) = "*****"
> 'エラー情報用にデータセットに行を追加()
> DataSet.Tables(1).Rows.Add(ds)
> End Sub
この部分でのみTables(1)にセットされているのでしたら、
この部分にブレイクポイントを設定したりして、
・1回のみ行われているのか。
・実行後に複数行書かれているか。
を試して見てください。
きいよさんお返事ありがとうございます。

ブレークポイントを置いて、ステップインで進めていったのですが、
以下のように動いていました。

************************************
Form1.vbの
ds(0) = "*****"
に飛びます

DataSet1.vbに飛んで
Private Sub DataTable2DataTable_ColumnChanging
  (ByVal sender As System.Object, ByVal e As System.Data.DataColumnChangeEventArgs)
   Handles Me.ColumnChanging 
(ちなみになにも入ってません)
に飛びます

DataSet1.Designer.vbに飛んで 以下のGet,Return文を実行して
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute()> _
Public ReadOnly Property _c_MarubatuColumn() As Global.System.Data.DataColumn
Get
Return Me._columnc_Marubatu
End Get
End Property


DataSet1.vbに戻ってきて(?)
Private Sub DataTable2DataTable_ColumnChanging(ByVal sender As System.Object, ByVal e As System.Data.DataColumnChangeEventArgs) Handles Me.ColumnChanging
If (e.Column.ColumnName = Me._c_MarubatuColumn.ColumnName) Then

もう一度
ds(0) = "*****"
に飛びます

Form1.vbの
Dataset.Tables(1).Rows.Add(ds)
に飛びます

DataSet1.Designer.vbに飛んで 以下のGet,Return文を実行して
<Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.ComponentModel.DesignerSerializationVisibilityAttribute(Global.System.ComponentModel.DesignerSerializationVisibility.Hidden)> _
Public Shadows ReadOnly Property Tables() As Global.System.Data.DataTableCollection
Get
Return MyBase.Tables
End Get
End Property
に飛びます


また
Dataset.Tables(1).Rows.Add(ds)
に飛んでいました。


デバッグが慣れてないのですが、示されたところが実行されているのだとしたら、
今回の現象も納得できます。原因はDataSet1.vbになにも入ってないものを作っていたからでしょうか?
KYOUさん
> また
> Dataset.Tables(1).Rows.Add(ds)
> に飛んでいました。
このへんが良くわからないのですが、

> Dataset.Tables(1).Rows.Add(ds)
は、ButtonRun.Clickのイベントのみで記入されているんですよね。
そのイベントが複数回発生していると言うことでしょうか?
きいよさんお返事ありがとうございます。

■No22910に返信(きいよさんの記事)
> KYOUさん
>>また
>> Dataset.Tables(1).Rows.Add(ds)
>>に飛んでいました。
> このへんが良くわからないのですが、
>
>> Dataset.Tables(1).Rows.Add(ds)
> は、ButtonRun.Clickのイベントのみで記入されているんですよね。
> そのイベントが複数回発生していると言うことでしょうか?

ボタンクリックのイベントでのみ記入しています。
デバッグのステップインでみたところ、一度" Dataset.Tables(1).Rows.Add(ds)"
に飛んで、デザイナー飛んで、もう一度" Dataset.Tables(1).Rows.Add(ds)"
に戻ってきていました。デザイナーではtableをgetしているようなことが
書いてありました。

デバッグ時のローカルの変数の内容を確認するところで、Datasetの内容を確認できたらいいのですが、パラメータ(?)が多くてデータの中身がみれません。
KYOUさん
> デバッグのステップインでみたところ、一度" Dataset.Tables(1).Rows.Add(ds)"
> に飛んで、デザイナー飛んで、もう一度" Dataset.Tables(1).Rows.Add(ds)"
> に戻ってきていました。デザイナーではtableをgetしているようなことが
> 書いてありました。
ここでデザイナーに飛ぶのは、Datadet.tables(1)
を参照している為にそれを取得しに行っているのではないですか?

デザイナーに何も手を加えていないのであれば、デザイナに飛ぶところより、
ボタンクリックのイベント一回のみで複数かかれているのかを確認してみてはいかがでしょう。
きいよさんお返事ありがとうございます。

本質問内容と異なってしまうのですが、My Projectのアセンブリ名とルート名前空間を別の名前に変えたところ、データベースログインの画面がでてきて、ログインidとパスワードを求められます。サーバのidパスを入れてもログインに失敗します。ログイン失敗の時に”crystal レポート windows フォームビューア”と出てくるのでクリレポ関連なのでしょうか?

質問内容を確認しようとしているのですが、上記の為確認できません。 
2008/09/03(Wed) 11:56:54 編集(投稿者)


Re{10}について自己解決しました。名前を直したらなおりました。

本題のほうですが、やはり”Dataset.Tables(1).Rows.Add(ds)”
の1命令で全て行に*****行が出来てました。
KYOUさん

ボタンクリック時のイベント内のコードでは、
> Private Sub ButtonRun_Click(ByVal sender As System.Object, ByVal e As
> System.EventArgs) Handles ButtonRun.Click
> 'エラー情報用に行をあたらしく作る
> ds = DataSet.Tables(1).NewRow()
> ds(0) = "*****"
> 'エラー情報用にデータセットに行を追加()
> DataSet.Tables(1).Rows.Add(ds)
> End Sub
一行しかレコード書き込まれないと思います。
何度かClickイベントが発生しているとか、
他のコードから、ButtonRun_ClickをCallしているとかありませんか。
きいよさんありがとうございます。

実は下記のようにDatasetの中身をクリスタルレポートに
出力した結果を見て複数行でていると判断しています。
クリスタルレポートは詳細にDataset1,Dataset2の該当項目
をセットしています。

-------------------------------------
aaaa (Dataset1の1行目)
**** (Dataset2の1行目)

bbbb (Dataset1の2行目)
**** (Dataset2の2行目)

cccc (Dataset1の3行目)
**** (Dataset2の3行目)


どこかの掲示板で見たのですが、Datasetにセットした
レコードは順番が決まっておらず、sql文で抜き取るのが
普通という書き込みがありましたが、そのためでしょうか?
KYOUさん

クリスタルレポートの結果ではなく。
DataSetのの中身を見られたらいかがでしょうか?
Tables(1)にデータをセットするところに問題があるのかどうか切り分け
出来るとおもいます。

Tables(1)に複数行はセットされていないのではないでしょうか?
きいよさんありがとうございます。

Tables(1)について下記のようにDISPLAY文を入れてみました。

*********************************************************
If K = 0 Then   'K= 入力レコード数
ds(0) = "11111"
End If
If K = 1 Then
ds(0) = "22222"
End If
If K = 2 Then
ds(0) = "33333"
End If
If K = 3 Then
ds(0) = "44444"
End If

MessageBox.Show(Me.ds.Item(0), "TEST")

*********************************************************
結果、"11111""22222""33333""44444"で表示されます。
他の領域は壊してなさそうなのですが・・・

DATASETの領域をダンプするようなものはないでしょうか?
KYOUさん
> *********************************************************
> If K = 0 Then   'K= 入力レコード数
> ds(0) = "11111"
> End If
> If K = 1 Then
> ds(0) = "22222"
> End If
> If K = 2 Then
> ds(0) = "33333"
> End If
> If K = 3 Then
> ds(0) = "44444"
> End If
>
> MessageBox.Show(Me.ds.Item(0), "TEST")
>
> *********************************************************
> 結果、"11111""22222""33333""44444"で表示されます。
> 他の領域は壊してなさそうなのですが・・・
>
> DATASETの領域をダンプするようなものはないでしょうか?
この表示で何を見たかったのか不明なのですが、
For Each とかで、
Table(1)の行数分ループさせながら、Debug.write等で表示させたらいかがでしょうか?
きいよさん返信ありがとうございます。

1行目しか値が入ってないはずなので、他の行に値が入ってないか
確認しています。

下記のようにDatasetの中を確認しています。
”1行目から4行目まで表示”の部分でエラーコードがでてしまいます。
ds(2)(0)はDatasetの項目を指すので、System.stringです。
Datasetの定義をみてみましたが、DefaultValueも<DBNull>でした。
値はセットしていないので、DBNullで入っていると思うのですが・・・



'1行目に1要素目に"11111"をセット
ds(0) = "11111"

'1行目から4行目まで表示
Debug.Write(ds(0)(0))
Debug.Write(ds(1)(0))
Debug.Write(ds(2)(0))
Debug.Write(ds(3)(0))


エラーコード
System.MissingMemberException はハンドルされませんでした。
Message="既定メンバが型 'DBNull' に見つかりませんでした。"
Source="Microsoft.VisualBasic"
KYOUさん

KYOUさんの書かれたソースをみると、
dsとはDataRowですよね。
ds(2)とすると行のカラム2個目のデータを意味するので、
それがDBNULLになります。
DBNull(0)としているために、
> System.MissingMemberException はハンドルされませんでした。
> Message="既定メンバが型 'DBNull' に見つかりませんでした。"
> Source="Microsoft.VisualBasic"
のエラーになると思います。

以下のようなソースで表示させてみてはいかがでしょう。

--------------------------------------------------------
Debug.WriteLine("行数" & CStr(DataSet1.Tables(1).Rows.Count))
For Each oRow As DataRow In DataSet1.Tables(1).Rows
Debug.WriteLine(oRow.Item(0))
Next
きいよさんアドバイスありがとうございます。

教えていただいたデバグ文を、入れてみましたが
イミディエイトウィンドウには、”行数0”としか
でませんでした。

同じデバグ文をデータ行側(こちらは書かれているはず)
にも試してみましたが、”行数0”としかでません。

Datasetには入っているはずなのですが・・・
KYOUさん

> 同じデバグ文をデータ行側(こちらは書かれているはず)
> にも試してみましたが、”行数0”としかでません。
>
> Datasetには入っているはずなのですが・・・
どの部分にどのようにデバック入れられていているのか
わかりませんので、原因の考えようがないのですが。


> Private Sub ButtonRun_Click(ByVal sender As System.Object, ByVal e As
> System.EventArgs) Handles ButtonRun.Click
> 'エラー情報用に行をあたらしく作る
> ds = DataSet.Tables(1).NewRow()
> ds(0) = "*****"
> 'エラー情報用にデータセットに行を追加()
> DataSet.Tables(1).Rows.Add(ds)

Debug.WriteLine("行数" & CStr(DataSet.Tables(1).Rows.Count))
For Each oRow As DataRow In DataSet.Tables(1).Rows
Debug.WriteLine(oRow.Item(0))
Next

> End Sub

と、ButtonRun_Clickにいれてみてはいかがでしょう。
きいよさんアドバイスありがとうございます。

結果、思った通りのダンプが取れました。

下記のようにデータセット行をADDした後に追加しました。
はじめは、ADDする前に入れたいたので、0行になっていました。
これでDATASET側は正しく入っており、クリスタルレポート側で
何か起きていることがわかりました。あとはクリスタルレポートを
調べてみます。

きいよさん、るしぇさん、分りやすいアドバイスありがとうございました。




' 登録実行
'  配列を参照して、フォーマットをチェック ○×付け
' ○のものについては更新処理
' 全てのレコードの結果リストの出力
Private Sub ButtonRun_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ButtonRun.Click

Call CHECK()

End Sub


' 項目チェック
Sub CHECK()

'エラー情報用に列をあたらしく作る
ds = Dataset.Tables(1).NewRow()

ds(0) = "11111"

'エラー情報用にデータセット行を追加()
Dataset.Tables(1).Rows.Add(ds)

'行数、行の内容をダンプ
Debug.WriteLine("行数" & CStr(Dataset.Tables(1).Rows.Count))
For Each oRow As DataRow In Dataset.Tables(1).Rows
Debug.WriteLine(oRow.Item(0))
Next

End Sub
解決済み!

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