孫階層まであるレコードセットをつくるには?

解決


Saturn  2005-10-19 22:29:49  No: 126497

はじめまして。
VB6.0SP5 + Access2000にてDBアプリケーションを作成しています。
受注した案件を登録し、それに付随する形で見積もりを登録、その見積もりに商品を登録する形になっています。

案件A-----見積1-----商品a
        |         |_商品b
        |         |_商品c
        |
        |_見積2-----商品b
                  |_商品c
                  |_商品d

案件B-----見積1-----商品b
        |         |_商品e
        |
        |_見積2-----商品a
                  |_商品b

上記のような感じです(ずれてなければいいのですが)。
ひとつの画面(form)の中に、DataGridで
案件一覧
その案件に従属する見積一覧
その見積に従属する商品一覧
の3つを表示し、DataGridの中で別の案件をクリックするとそれに従属する見積もりが表示され、
見積もりが複数ある時は各々の見積もりをクリックした時にそれぞれ従属する商品が表示される、というふうにしたいと思っています。

DataEnvironmentやShapeコマンドで階層レコードセットを作ると一応希望を満たせるのですが、親レコードセットだけでは孫のDataGridの表示が更新されません。
そこで子レコードセットと孫レコードセットも作ったのですが、その際に
親レコードセットのカレントレコードに子レコードがない場合、子レコードセットは作れるのですが孫レコードセットが
「実行時エラー3021 EOFかBOFがTrueになっているか、現在のレコードが削除されています」となってレコードセットが作れません。

こういった動作を期待する場合はどのように処理するものなのでしょうか。

長文で申し訳ありませんがよろしくお願いいたします。


葉月  2005-10-19 22:34:30  No: 126498

むかぁぁし
グレープシティのTrueDBGでやったような気がするなぁ
それだとGRIDでツリー構造作れるから

VBにくっついてるGRIDだと無理じゃね?


魔界の仮面弁士  2005-10-19 23:51:23  No: 126499

>> 某葉月さん
MSHFlexGrid が、階層型 Recordset に対応していますね。

>> Saturnさん
> ずれてなければいいのですが
IEの標準フォントだと、ずれて見えますね。(^^;

ただ、ずれていないにしても、各階層の具体的なフィールド定義が
見えてこないので、親/子/孫 の構造が、あまり把握できませんでした。
(まぁ、なんとなく想像はできますけれども)

> 親レコードセットだけでは孫のDataGridの表示が更新されません。
えぇと。れは子が無いのに孫がある、という状況でしょうか。
『親:受注した案件』はあるけれど、『子:見積り』を作らずに、
『孫:受注商品』を登録するという状況……かな?
もしそれがありうるなら、孫ではなく『子2:受注商品』になるべきかも。

> そこで子レコードセットと孫レコードセットも作ったのですが、
商品(孫階層)を登録するための、見積り(子階層)を組んだのですね。

> レコードセットが作れません。
以前、 Data Provider=none の状態の Connection に対して、
SHAPE APPEND で階層を組んだ事がありますが、そのような問題は
経験していません。

可能であれば、お使いの SHAPE コマンドと、データの登録部のコードを
見せていただけませんか? たとえば、Updata / UpdateBatch は
おのおのの内部レコードセットそれぞれに対して適用しなければ
なりませんが、その点は大丈夫でしょうか。


Saturn  2005-10-20 00:46:26  No: 126500

早速のご返答ありがとうございます。

>> 葉月さん
おぉ、これならチェックボックスもできるしいいかも。
ありがとうございます。
あとは値段との相談です。。

>> 魔界の仮面弁士さん
わかりにくい表現で申しわけありません。

> えぇと。れは子が無いのに孫がある、という状況でしょうか。
いえ、子(見積)がなければ孫(商品)はない状況です。
Form_Loadでレコードセットを作っています。
たとえば案件が3つあり、最後に登録した案件(仮に案件3とします)に見積が登録されておらず、案件のみ登録してある場合、
次回起動時に孫レコードセットを作る際に「BOFまたはEOFがTrue・・・」のエラーが出ます。
案件3に見積が登録されておればエラーを出さずに起動します。

ちょっと長いのですがForm_Loadのコードを転記させていただきます。
※下記にある「案件別仕様」とは「商品」のことです。

Private Sub Form_Load()

  Set cn = New ADODB.Connection
  cn.Provider = "MSDataShape"
  cn.ConnectionString = "Data Provider=Microsoft.Jet.OLEDB.4.0;" _
  & "Data Source=C:"DBまでのパス";Persist Security Info=True"
  cn.Open

  '案件一覧レコードセット生成
  Set rsMatterManagement = New ADODB.Recordset
  With rsMatterManagement
    .CursorType = adOpenStatic
    .LockType = adLockPessimistic
    .CursorLocation = adUseClient
  End With
  
  strSQLShape = " SHAPE {select * from 案件管理 order by 案件ID DESC}  AS MatterManagement"
  strSQLShape = strSQLShape & " APPEND (( SHAPE {SELECT * FROM 見積管理 ORDER BY 見積ID DESC}  AS ESTManagement APPEND ({select * from 案件別仕様管理 order by 案件別仕様ID ASC}  AS CategoryList"
  strSQLShape = strSQLShape & " RELATE '案件ID' TO '案件ID','見積ID' TO '見積ID') AS CategoryList) AS ESTManagement"
  strSQLShape = strSQLShape & " RELATE '案件ID' TO '案件ID') AS ESTManagement"
 
  rsMatterManagement.Open strSQLShape, cn

  '見積一覧レコードセット生成
  Set rsESTManagement = New ADODB.Recordset
  With rsESTManagement
    .CursorType = adOpenStatic
    .LockType = adLockPessimistic
    .CursorLocation = adUseClient
  End With
  Set rsESTManagement = rsMatterManagement.Fields!ESTManagement.Value
  
  '案件別仕様管理レコードセット生成
  Set rsCategoryList = New ADODB.Recordset
  With rsCategoryList
    .CursorType = adOpenStatic
    .LockType = adLockPessimistic
    .CursorLocation = adUseClient
  End With
  
  Set rsCategoryList = rsESTManagement.Fields!CategoryList.Value
 
End Sub

一部省略(他のレコードセットなど)していますが、上記のようになります。
上記では最終行の
  Set rsCategoryList = rsESTManagement.Fields!CategoryList.Value
にて「BOFまたはEOFがTrue・・・」のエラーが出ます。

> たとえば、Updata / UpdateBatch は
> おのおのの内部レコードセットそれぞれに対して適用しなければ
> なりませんが、その点は大丈夫でしょうか
説明不足で申し訳ありません。登録時ではなく画面(DataGrid)への表示の時点(DataGridへ連結するレコードセットの生成)で問題が発生しております。
ちなみにデータの登録時にはSQLでUPDATEしcn.Execute後、rsMatterManagementをrequeryしています。

あと、DBのフィールドですが、
案件管理:案件ID
見積管理:案件ID,見積ID
案件別仕様管理:案件ID,見積ID,案件別仕様ID
がそれぞれ主キーになっています。

# VBを触り始めたばかりで、DelphiにおけるDataSetのMasterFieldsと同じ動作を期待してShapeを使ってみたのですが、
# 根本的に使い方を間違っているんでしょうか・・

お手数をおかけいたしますが、よろしくお願いいたします。


葉月α  2005-10-20 01:46:24  No: 126501

魔界の仮面弁士さん
>>MSHFlexGrid が、階層型 Recordset に対応していますね。
調査不足ごめんなさい

Saturnさん
案件A  見積もり1  商品a
案件A  見積もり1  商品b
案件A  見積もり1  商品c
案件A  見積もり2  商品b
案件A  見積もり2  商品c
案件A  見積もり2  商品d
案件B  見積もり1  商品b
案件B  見積もり1  商品e
案件B  見積もり2  商品a
案件B  見積もり2  商品b

をすっきりさせたいということですよね?


Saturn  2005-10-20 02:10:03  No: 126502

> 葉月αさん

そうですね、できれば案件一覧、見積、商品、をそれぞれ別のgridに表示したいと考えています。
案件一覧Gridにて案件Aを選択した際、見積Gridには案件Aの見積1と見積2が表示され(この時にどちらの見積もりがカレントになってもかまいません)、
カレントの見積に登録してある商品が商品一覧に表示される状況を望んでいます。

よろしくお願いいたします。


葉月α  2005-10-20 02:30:52  No: 126503

別のグリッド・・・

ならば案件Aを選択した時に案件Aの見積もりを検索するSQLを発行し
グリッドなりリストビューなりに表示

表示された見積もりを選択したときに再度商品を検索するSQLを発行し
同じくグリッドなりリストビューなりに表示すれば良いのでは?

リストを3つ使えば出来ると思うのですけど


AAA  2005-10-20 03:18:58  No: 126504

葉月αさんのやり方が一番スマートではないでしょうか?
Gridをひとつで作るよりもコーディングが簡単そうですし。

しかし、あえて別の解釈をするのであれば。。。

1.初期表示で案件Aと案件BをそれぞれGridA(Col0,Row0),GridA(Col0,Row1)に表示
2.案件Aを選択時に、選択した案件Aに紐付く見積もり1と見積もり2をそれぞれGridA(Col1,Row0),GridA(Col1,Row1)に表示
    このとき案件BはGridA(Col0,Row2)に移動
3.見積もり1を選択時に、選択した見積もり1に紐付く商品aと商品bと商品cをそれぞれGridA(Col2,Row0),GridA(Col2,Row1),GridA(Col2,Row2)に表示
    このとき案件BはGridA(Col0,Row4)に移動し、見積もり2はGridA(Col1,Row3)に移動
※注釈(一応)
  GridA(Col0,Row0)等は、あくまで座標として書いています。こんな関数はないです(多分)

とりあえず、この辺を参考にすると良いかもしれませんね。
http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/vb_t10.htm

見当違いでしたらスミマセン。


AAA  2005-10-20 03:18:59  No: 126505

葉月αさんのやり方が一番スマートではないでしょうか?
Gridをひとつで作るよりもコーディングが簡単そうですし。

しかし、あえて別の解釈をするのであれば。。。

1.初期表示で案件Aと案件BをそれぞれGridA(Col0,Row0),GridA(Col0,Row1)に表示
2.案件Aを選択時に、選択した案件Aに紐付く見積もり1と見積もり2をそれぞれGridA(Col1,Row0),GridA(Col1,Row1)に表示
    このとき案件BはGridA(Col0,Row2)に移動
3.見積もり1を選択時に、選択した見積もり1に紐付く商品aと商品bと商品cをそれぞれGridA(Col2,Row0),GridA(Col2,Row1),GridA(Col2,Row2)に表示
    このとき案件BはGridA(Col0,Row4)に移動し、見積もり2はGridA(Col1,Row3)に移動
※注釈(一応)
  GridA(Col0,Row0)等は、あくまで座標として書いています。こんな関数はないです(多分)

とりあえず、この辺を参考にすると良いかもしれませんね。
http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/vb_t10.htm

見当違いでしたらスミマセン。


AAA  2005-10-20 03:19:24  No: 126506

二重送信スミマセンでした orz


魔界の仮面弁士  2005-10-20 18:12:20  No: 126507

# 階層型 Recordset を使うかどうかの判断は、Saturnさんに
# 任せるとして、とりあえず当初の質問内容に対して述べておきます。

> 次回起動時に孫レコードセットを作る際に「BOFまたはEOFがTrue・・・」のエラーが出ます。
子供ができていない時に孫を得ようとして失敗しているようですね。

>    .LockType = adLockPessimistic
仕組上、排他ロックはまずいでしょう。もし、更新可能な階層型 Recordset を
使いたいのであれば、オプティミスティックロックタイプか、
バッチオプティミスティックロックタイプを使うようにしましょう。
(更新が不要ならば、もちろん読取専用という選択肢も使えます)

>  '見積一覧レコードセット生成
>  Set rsESTManagement = New ADODB.Recordset
> (中略)
>  Set rsESTManagement = rsMatterManagement.Fields!ESTManagement.Value
……これ、親階層のチャプタを受け取る仕組みになっているのですから、
その直前の New (および、With ブロック)は無意味ですよね。

> Set rsCategoryList = rsESTManagement.Fields!CategoryList.Value
この場合は、rsCategoryList への取得を行う前に、rsESTManagement.EOF の
状況をチェックするべきでしょう。子にしても孫にしても、その親が
居なければ、チャプタ列からレコードセットを取得できませんし。

> DelphiにおけるDataSet
Delphiの事は全く知らないので、これについてはわかりません。m(_ _)m


Saturn  2005-10-20 19:14:18  No: 126508

みなさんご返答いただきありがとうございます。

>> 葉月αさん
なるほど、階層型にこだわっていたので思いつきませんでした。
その方法で今一度やり直してみます。

>> AAAさん
ありがとうございます。
リンク先も見せていただいて参考にさせていただきます。

>> 魔界の仮面弁士さん
ご丁寧な返信、ありがとうございます。

>> Set rsCategoryList = rsESTManagement.Fields!CategoryList.Value
>この場合は、rsCategoryList への取得を行う前に、rsESTManagement.EOF の
>状況をチェックするべきでしょう。子にしても孫にしても、その親が
>居なければ、チャプタ列からレコードセットを取得できませんし。
このあたりがよくわからなかったのですが、今、どうわからないのかを
書いているうちになんとなくわかってきたような気がします。
(ぼんやりとですが)
もう一度レコードセットについて調べなおします。

どうもありがとうございました。
また質問させていただくかもしれませんが、その時もよろしくお願いいたします。


※返信する前に利用規約をご確認ください。




  


  このエントリーをはてなブックマークに追加