TreeViewに重複する値をセット

このQ&Aのポイント
  • TreeViewにデータテーブルの値をセットして表示しています。セットする値に重複する値がある場合、ツリーの構造が崩れてしまいます。
  • ツリーの値に非表示のキーを持たせる等、何か対応法をご存知の方がいらっしゃいましたら教えて下さい。
  • VB2005Expressで開発しています。PGMは「処理内容:TreeViewにデータテーブルの値をセット」から「TreeView1.SelectedNode = Nothing」までです。
回答を見る
  • ベストアンサー

TreeViewに重複する値をセット

VB2005Expressで開発しています。 TreeViewにデータテーブルの値をセットして表示しています。 セットする値に重複する値がある場合、ツリーの構造が崩れてしまいます。左図のようにしたいのですが、右図のようになってしまいます。 あ あ |-い |-い | | | | | -う | -う お | -え |-い お | | | -え ツリーの値に非表示のキーを持たせる等、何か対応法をご存知の方が いらっしゃいましたら教えて下さい。下記がPGMです。 '処理内容:TreeViewにデータテーブルの値をセット Private Function fncTreeViewSet() As Boolean Dim dTbl As DataTable Dim Node As TreeNode Dim intMenuNo As Integer Dim strMenuName1 As String Dim strMenuName2 As String Dim strMenuName3 As String Dim strMenuName4 As String Dim strMenuName5 As String Dim i As Integer Node = TreeView1.SelectedNode dTbl = dsDataSet.Tables("Mメニュー") For i = 0 To dTbl.Rows.Count() - 1 intMenuNo = 0 strMenuName1 = "" strMenuName2 = "" strMenuName3 = "" strMenuName4 = "" strMenuName5 = "" strMenuName1 = Trim$(dTbl.Rows(i)("階層1")) intMenuNo = dTbl.Rows(i)("工程番号") strMenuName2 = Trim$(dTbl.Rows(i)("階層2").ToString) strMenuName3 = Trim$(dTbl.Rows(i)("階層3").ToString) strMenuName4 = Trim$(dTbl.Rows(i)("階層4").ToString) strMenuName5 = Trim$(dTbl.Rows(i)("階層5").ToString) If strMenuName1 = "" Then Else If strMenuName2 = "" Then TreeView1.Nodes.Add(strMenuName1) '階層1をセット Else If strMenuName3 = "" Then fncSerchNode(strMenuName1) TreeView1.SelectedNode.Nodes.Add(strMenuName2) '階層2をセット Else If strMenuName4 = "" Then fncSerchNode(strMenuName2) TreeView1.SelectedNode.Nodes.Add(strMenuName3) '階層3をセット Else If strMenuName5 = "" Then fncSerchNode(strMenuName3) TreeView1.SelectedNode.Nodes.Add(strMenuName4) '階層4をセット Else fncSerchNode(strMenuName4) TreeView1.SelectedNode.Nodes.Add(strMenuName5) End If End If End If End If End If Next TreeView1.SelectedNode = Nothing End Function '処理内容:指定ノード選択 Private Function fncSerchNode(ByVal strMenuName As String) As Boolean Dim Node As TreeNode For Each Node In fncGetAllNodes(TreeView1.Nodes) If Node.Text = strMenuName Then TreeView1.SelectedNode = Node Exit For End If Next End Function '処理内容:子ノードも含んだすべてのノードを取得 Private Function fncGetAllNodes(ByVal Nodes As TreeNodeCollection) As ArrayList Dim Ar As New ArrayList Dim Node As TreeNode For Each Node In Nodes Ar.Add(Node) If Node.GetNodeCount(False) > 0 Then Ar.AddRange(fncGetAllNodes(Node.Nodes)) End If Next Return Ar End Function

質問者が選んだベストアンサー

  • ベストアンサー
  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.4

fncSerchNodeで探しているノードが Node.Textとの比較でしか探していないのが原因でしょう 探すノードまでフルパスを検索してやれば希望通りになると思います 呼び出し側で 『階層5』を追加するための『階層4』ノードの検索に fncSerchNode(strMenuName1 & "\" & strMenuName2 & "\" & strMenuName3 & "\" & strMenuName4) と 階層1から階層4までを "\"でつないだ物をキーに探します 階層3を探すなら fncSerchNode(strMenuName1 & "\" & strMenuName2 & "\" & strMenuName3) 階層2を探すなら fncSerchNode(strMenuName1 & "\" & strMenuName2 ) 階層1を探すなら fncSerchNode(strMenuName1 ) fncSerchNodeのIf Node.Text = strMenuName Then を If Node.FullPath = strMenuName Then としてみてください

madamadahiyoko
質問者

お礼

教えていただいた「Node.Textとの比較でしか探していない」が原因 でした。上記を組み込んだところ解決しました! 本当にありがとうございました。

その他の回答 (3)

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.3

前者のような構造なら ノードを追加する際に Add( row("階層1"), row("階層1") ) といった具合に Key、Textを指定して登録します ノードの検索に 階層1の場合は pNodes = TreeView1.Nodes.Find( row("階層1"), Flase ) として pNodes.Length = 0 なら新規ノード、0以外なら既存ノードと判定できます 階層2以下は pParent = pNodes(0) pChilds = pParent.Nodes.Find( row("階層2"), False ) として pChilds.Length=0なら新規のノードなどで追加 0以外なら既存のノードなので pParntにpChilds(0)を代入 pParent = pNodes(0) m = dTbl.columns.IndexOf("階層2") for n = m to dTbl.Columns.Count - m + 1   pChilds = pParent.Nodes.Find( row(n), False )   if pChilds.Length = 0 then     pParent.Nodes.Add( row(n), row(n) )   else     ' 検索する親を付け替える     pParent = pChild(0)   end if next といった具合です

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.2

階層1、階層2、階層3などの情報は 同一レコードにあるのでしょうか データテーブルに あ あ、い あ、い、う お お、い お、い、う といった構造でしょうか それとも あ、い、う お、い、え の2レコードなのでしょうか どうも前者のように思えますが ・・・ 後者なら dim row as dataRow dim pNode as TreeNode dim n,m as integer m = dTbl.Columns.IndexOf("階層2") for each row in dTbl.rows   if row("階層1")<>"" then     pNode = treeView1.Nodes.add( row("階層1") )     for n = m to row.ItemArray.Length - m + 1       pNode = pNode.Nodes.Add( row( n ) )     next   end if Next

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

お示しのツリーが崩れてしまっているようです DataTableの内容を投稿なさった方がいいかもしれません どのデータを表示したくて、どのデータは非表示にしたいとかいった情報も書き込みましょう

madamadahiyoko
質問者

補足

回答いただきありがとうございます。 そもそも図が変ですね。すいません。(1)のようにしたいのですが、(2) のようになってしまいます。 (1) あ |-い | | |  -う お |-い | | | -え (2) あ |-い | | | -う | -え お 非表示とは上図の「い」という値にキーのようなものを持たせれば どこの「い」か判別できるかなと思ったので、それを非表示で値を 持たせることができるのかと思って質問させていただきました。 文章がわかりずらくて申し訳ありません。

関連するQ&A

  • Oracle階層問合せよりツリーノードを作成

    Oracle階層問合せの結果よりVB.NETのTreeViewを作成する方法を教えてください。 ・階層問合せのサンプル SELECT LPAD(' ', 2*level-1)||SYS_CONNECT_BY_PATH(last_name, '/') "Path" FROM employees START WITH last_name = 'Kochhar' CONNECT BY PRIOR employee_id = manager_id; Path --------------------------------------------------------------- /Kochhar /Kochhar/Greenberg /Kochhar/Greenberg/Faviet /Kochhar/Greenberg/Chen /Kochhar/Greenberg/Sciarra /Kochhar/Greenberg/Urman /Kochhar/Greenberg/Popp /Kochhar/Whalen /Kochhar/Mavris /Kochhar/Baer /Kochhar/Higgins /Kochhar/Higgins/Gietz VB.NET作成途中 Dim LEVEL_prev As Integer = 0 Dim node_prev As New TreeNode("") Dim aryNODENO(16) As Integer While (reader.Read()) NODE_NO = reader.Item("NODE_NO") LEVEL = reader.Item("LEVEL") PATH = reader.Item("PATH") NAME = reader.Item("NAME") Dim i As Integer Dim node_cur As New TreeNode("") node_cur.Expanded = True node_cur.Text = strSITE_NAME If intNODE_NO = 1 Then ' 新規ノードを準備する TreeView2.Nodes.Add(node_cur) Else If intLEVEL_prev < intLEVEL Then ' 下位層へ移動の場合、新規ノードを準備する TreeView2.Nodes(aryNODENO(intLEVEL - 1) - 1).ChildNodes.Add(node_cur) ElseIf intLEVEL_prev = intLEVEL Then '前のノードと同一階層 ' 前のノードを上位階層へ追加 TreeView2.Nodes(aryNODENO(intLEVEL - 1) - 1).ChildNodes.Add(node_cur) ElseIf intLEVEL_prev > intLEVEL Then ' '' 上位層へ移動の場合 '' ' ノードを上位階層へ追加 TreeView2.Nodes(aryNODENO(intLEVEL - 1) - 1).ChildNodes.Add(node_cur) End If End If intLEVEL_prev = intLEVEL node_prev = node_cur End While     Me.TreeView2.Nodes(0).Expand() 以上

  • VB2005 ツリービューに子ノードを追加

    VB2005 ExpressEditionにて開発しています。 フォームロード時にデータセットからツリービューにデータをセット しようとしています。 ルートノードには  Dim Node As TreeNode  Node = TreeView2.SelectedNode  TreeView2.Nodes.Add("追加したい名前") で追加できます。 子ノードを追加する時はどうしたらいいのでしょうか。 ご存知の方がいらっしゃいましたら教えて下さい。 よろしくお願いします。

  • TreeViewのTag情報取得

    VB.NET2003 を使用して、 CheckBox付のTreeViewを作成しました。 階層は3階層用意して、最下層のTextに人名・Tagにメールアドレスをセットしました。 下記のサンプルの場合、チェックを入れたDさんのメールアドレスのみを 取得したいのですが、どのよう書けばよろしいでしょうか? ご教授いただけますよう、お願い致します。 TreeViewイメージ □本部  □総務課   □Aさん   □Bさん  □人事課   □Cさん   ■Dさん   □Eさん □営業  □東京   □Fさん   □Gさん TreeView作成コード Dim parentrow As DataRow Dim ParentTable As DataTable For Each parentrow In ds.Tables("A").Rows Dim parentnode As TreeNode parentnode = New TreeNode(parentrow.Item("SHOZOKU").ToString) treeView1.Nodes.Add(parentnode) ''''child''''' Dim childrow As DataRow Dim childnode As TreeNode childnode = New TreeNode For Each childrow In parentrow.GetChildRows("A") childnode = parentnode.Nodes.Add(childrow("BUSHO_NAME").ToString) ''''child2'''' Dim childrow2 As DataRow Dim childnode2 As TreeNode childnode2 = New TreeNode For Each childrow2 In childrow.GetChildRows("B") childnode2 = childnode.Nodes.Add(childrow2("NAME").ToString) childnode2.Tag = childrow2("MAIL").ToString Next childrow2 '''''''''''''''''''''''' Next childrow ''''''''''''''' Next parentrow treeView1.CheckBoxes = True

  • .NETのTreeViewの項目が一つの場合の画面遷移

    .NETのTreeViewの項目が一つの場合の画面遷移がうまくできません。 'Dim Node As TreeNode 'Dim form2 As New あああ 'Node = TreeView2.SelectedNode 'Select Case Node.Text ' Case "あああ" ' form2.Show() ' Me.Hide() 'End Select とすると、他画面から、TreeViewを経由して遷移させたくても、TreeView内に一つしか選択要素がない場合の画面へは行かず、すぐ上のTreeView内にいくつもの選択要素がある画面へ飛んでしまいます。 単体で動かしたくても、TreeView内に選択項目が一つの場合は動きません。 どなたか、回避する方法をご存知の方お教えください

  • 実行画面が消えてしまう?

    WindowsXP、VB6.0でデレクトリをTreeViewに表示するプログラムです。 フォームにTreeViewコントロールとコマンドボタンを貼り付け、 下記のプログラムを実行します。 curFolder.Name に "System Volume Information" がでると エラーになり、それを回避するために "On Error Resume Next"をいれて EXEファイルを作り、実行するとフォームが消えてしまいます。 どなたか教えて下さい。 Private Sub Command1_Click() ' Microsoft Scripting Runtime を参照設定する。 Dim item1 As Node, FsoObj As New scripting.FileSystemObject Set item1 = TreeView1.Nodes.Add(, , , "c:") Call SearchFolder(FsoObj.GetFolder("c:\"), item1) End Sub Private Sub SearchFolder(NextFolder As scripting.Folder,               itemX As Node) On Error Resume Next Dim TreeItem As Node, curFolder As scripting.Folder For Each curFolder In NextFolder.SubFolders ' Debug.Print curFolder.Path Set TreeItem = TreeView1.Nodes.Add(itemX.Index,                tvwChild, , curFolder.Name) Call SearchFolder(curFolder, TreeItem) Next End Sub

  • 配列のセットの仕方

    度々質問してすいません。 英文の単語を抽出して頻度順に並べるプログラムをVBで作りたいと思っております。下記URLのVB版です。 (http://gamp.c.u-tokyo.ac.jp/archive/perl.htm) 以下が作成したソースです。これとQuickSortのソース(http://www.geocities.co.jp/SilkRoad/4511/vb/sort.htm) を繋げて終わりたいと思うのですが、 どうつなげたらいいのかわかりません。 アドバイスをお願いいたします。 Private Sub Command1_Click() Dim strTarget As String Dim strResult As String Dim cha As String Dim chaList() As String Dim word As String Dim wordList() As Long Dim i As Long, j As Long Dim EndFlg As String strTarget = Me.Text1.Text i = 0 EndFlg = "" Do Until EndFlg = "END" i = i + 1 cha = Mid(strTarget, i, 1) If cha <> "" Then ReDim Preserve chaList(i) chaList(i - 1) = cha Else EndFlg = "END" End If Loop For i = 0 To UBound(chaList) - 1 If chaList(i) = "." Then chaList(i) = " " End If Next Text2 = "" For i = 0 To UBound(chaList) - 1 Text2 = Text2 & chaList(i) Next Text3 = "" word = "" For i = 0 To UBound(chaList) - 1 If chaList(i) = " " Then If i = 0 Then Else If chaList(i - 1) = " " Then Else Text3 = Text3 & Chr(13) & Chr(10) & word word = "" End If End If Else word = word & chaList(i) End If Next If word <> "" Then Text3 = Text3 & Chr(13) & Chr(10) & word End If

  • TreeViewのスクロール制御

    VB6でTreeViewコントロールのスクロールをプログラム側から制御する物を作っているのですが分からなくて困っています。 TreeViewでNodeが増えれば自動的に表示されるスクロールバーは表示をしないように「Scrollプロバティ」にFalseを入力してSendMessageで下記の方法で行ったのですがスクロールしません。 Private Sub Command1_Click() Call SendMessage(TreeView1.hwnd, WM_VSCROLL, MAKEWPARAM(SB_THUMBPOSITION, sPos), 0) End Sub Private Function MAKEWPARAM(LOWWORD As Long, HIWORD As Long) As Long MAKEWPARAM = (LOWWORD And &HFFFF&) Or (HIWORD * &H10000) End Function 「Scrollプロパティ」にTrueを設定すると問題なくできるのですが、どなたか分かる方がいましたら宜しくお願い致します。

  • エクセルVBA 重複を表示したい2

    エクセルVBA 重複を表示したい2 以下ではたいへんお世話になりありがとうございました。 http://okwave.jp/qa/q5849885.html 上記に関連する質問をさせていただきます。 下記に提示したコードを修正して、以下のようなコードに変えたいと考えています。 「B列で重複したデータがあれば、そのすべてを左隣のデータと一緒に表示したい」 添付した図だと、 1小沢一郎 7〃 8〃 4鈴木一郎 6〃 以上のような感じです。 アドバイスよろしくお願いします。 Sub TEST() Dim myRange As Range Dim 同一flag As Boolean Dim MsgStr As String m_Rows = Range("b" & Rows.Count).End(xlUp).Row For Each myRange In Range("b2:b" & m_Rows) If WorksheetFunction.CountIf(Range("b2:b4000"), myRange) > 1 Then If 同一flag = False Then 同一flag = True If InStr(1, MsgStr, myRange) = 0 Then MsgStr = MsgStr & myRange.Offset(0, -1).Value & myRange & vbCrLf End If End If Next If 同一flag = True Then MsgBox "同姓同名あり" & Chr(13) & _ "確認してください" & Chr(13) & _ vbCrLf & MsgStr Else End If End Sub

  • 連続して同じ値が入ってるなら削除したいのですが

    指定した値なおかつ連続して同じ値が入ってるなら削除したいのですが A列に 紅葉 紅葉 桜 桜 紅葉 とはいっていて、 Sub Sample() Dim i As Long Dim mystr As String mystr = "桜" For i = Cells(Rows.Count, "A").End(xlUp).Row To 2 Step -1 If Cells(i, 1) = Cells(i - 1, 1) = mystr Then Rows(i).Delete End If Next i End Sub をしても、削除されません。 4行目の桜が削除されてもいいと思うのですが コードのどこが間違えてますか?

  • DelphiのTreeViewでの+ボタンの出し方

    WindowsXP、Delphi2009で開発しています。 TTreeViewのAdvancedCustomDrawItemで下記の様に動的にノードの描画を行っていますが、ノードを展開・折りたたみする際に使う+ボタンが表示できなくて困っています。 +ボタンを表示させる方法が分かる方、ご教示願います。 ------------------------------------------------------------ procedure TForm3.TreeView1AdvancedCustomDrawItem(Sender: TCustomTreeView; Node: TTreeNode; State: TCustomDrawState; Stage: TCustomDrawStage; var PaintImages, DefaultDraw: Boolean); var Rect :TRect; begin defaultdraw := false; Rect := Node.DisplayRect(True); if Node.Selected = true then begin Sender.Canvas.Font.Color := clWhite; end else begin if Copy(Node.Text,pos('\',Node.Text) + 1, length(Node.Text)) = 'False' then begin Sender.Canvas.Font.Color := clWindowText; end else begin Sender.Canvas.Font.Color := clRed; end; end; Sender.Canvas.TextOut(Rect.Left,Rect.Top,Copy(Node.Text,1,pos(',',Node.Text) - 1)); end; ------------------------------------------------------------

専門家に質問してみよう