4 Attachment(s)
Moving/Swapping values in a TREEVIEW
I appologize if this is a duplicate, but I could not find my first post.
=====================
Hello All:
I just realized this section of the forum is available.
I have a problem with some existing source code. I think I can tell you the lines that need to be modified, I just don't understand this enough to be able to make the change.
Some fine folks here have helped me get this far, but I just can't get over this hump.
I have attached the current project and associated source code, along with printscreens.
Here is a summary of the problem.
1)Run the project
2)Select 'Load Tree'
3)Select 'Sort'
4)Look at Tv1 this is where the information is sorted and redisplayed.
5)Everything NODE ending with an "*" should be sorted to the bottom of the tree, ALONG WITH everything under it.
This is where my problem comes in. The second level is sorted to the end, but not the values underneath it.
It is my understanding that when a node is moved/swapped everything under it will go with it. That is children stay with their parent. If it were working that way, my problem would be solved. However this code is moving the parent and leaving the children behind.
I believe the problem is in the SortChild Sub and in the following lines, but I can't be sure
Code:
Set chTemp = ch1(intI)
Set ch1(intI) = ch1(intRnd)
Set ch1(intRnd) = chTemp
BEFORE SORT
Attachment 30979
AFTER SORT
Attachment 30981
Should be:
Attachment 30983
Re: Moving/Swapping values in a TREEVIEW
Quote:
It is my understanding that when a node is moved/swapped everything under it will go with it. That is children stay with their parent. If it were working that way, my problem would be solved. However this code is moving the parent and leaving the children behind.
No, you should change the 'parent' in every child to the new parent key
Post the code
1 Attachment(s)
Re: Moving/Swapping values in a TREEVIEW
jggtz,
Thanks for the response.
I have been having PC problems and just now getting back online.
Here is the code.
I have also included a zip file with the project and images of what the output should look like, along with an input file.
If anyone can help with this, it is greatly appreciated. I have been battling this issue for over 2 months now.
Thanks in advance.
Code:
Option Explicit
Private Declare Function CoCreateGuid Lib "ole32.dll" (pGUID As Any) As Long
Public Function CreateGUID() As String
Dim i As Long, b(0 To 15) As Byte
If CoCreateGuid(b(0)) = 0 Then
For i = 0 To 15
CreateGUID = CreateGUID & Right$("00" & Hex$(b(i)), 2)
Next i
Else
MsgBox "Error While creating GUID!"
End If
End Function
Private Function SetSecondElement(ByRef strS() As String) As Integer
Dim intI As Integer
intI = 1
If UBound(strS) > 0 Then
Do Until strS(intI) <> vbNullString
intI = intI + 1
Loop
strS(1) = strS(intI)
End If
SetSecondElement = UBound(strS)
End Function
Private Sub Shuffle(strData() As String)
'
'Expects an array of values such as :
'AA 111111
'AB 222222
'AC 333333
'AD 444444
' and randomly 'shuffles' the numeric part
' to give, for example
'AA 333333
'AB 222222
'AC 444444
'AD 111111
'
' When complete, strData will contain the 'shuffled' data
' (Assumes there's a 'Randomize' statement in the Form Load event)
'
Dim strResult() As String
Dim strTemp As String
Dim intI As Integer
Dim intJ As Integer
Dim intOL As Integer
Dim intOL1 As Integer
Dim intRnd As Integer
Dim strS() As String
Dim strS1() As String
For intI = 0 To UBound(strData)
'
' Create a Random number within the bounds of the Array
'
intRnd = Int(Rnd * (UBound(strData) + 1))
'
' Form 2 parts of the current element's original data
' strS(0) = letters part
' rstS(1) = numeric part
'
'Debug.Print strData(intI)
'Debug.Print strData(intRnd)
strS = Split(strData(intI), " ")
intOL = SetSecondElement(strS)
'
' Save this element's numeric part
'
strTemp = strS(1)
'
' Create a pair of parts for the Random element
'
strS1 = Split(strData(intRnd), " ")
intOL1 = SetSecondElement(strS1)
'
' Swap the numeric values
'
strS(1) = strS1(1)
strS1(1) = strTemp
'
' Put the modified values back into the original array
'
For intJ = 2 To UBound(strS)
strS(intJ) = vbNullString
Next intJ
For intJ = 2 To UBound(strS1)
strS1(intJ) = vbNullString
Next intJ
strData(intI) = strS(0) & Space(intOL) & strS(1)
strData(intRnd) = strS1(0) & Space(intOL1) & strS1(1)
Next intI
End Sub
Private Function GetLevel(strData As String) As Integer
Dim intI As Integer
intI = 1
Do Until Mid$(strData, intI, 1) <> vbTab
intI = intI + 1
Loop
GetLevel = intI - 1
End Function
Private Sub cmd_LoadTree_Click()
LoadNodesFromFileWithTab
End Sub
Private Sub Cmd_Shuffle_Click()
LoadNodesFromFileWithTab
End Sub
Private Sub cmd1_Click()
Call ProcessAllChildren(tv.Nodes(1), tv.Nodes(1))
Call ShuffleChildren(tv.Nodes(1))
End Sub
Private Sub cmdSort_Click()
Call ProcessAllNodes(tv.Nodes(1), tv.Nodes(1))
Call SortChildren(tv.Nodes(1))
End Sub
Private Sub Command1_Click()
TreeviewSortSpecial
End Sub
Private Sub Form_Load()
Randomize
End Sub
Public Sub LoadNodesFromFileWithTab()
Dim text_line As String
Dim level As Integer
Dim tree_nodes() As Node
Dim num_nodes As Integer
Dim iFreefile As Integer
Dim Treefile As String
iFreefile = FreeFile
Treefile = App.Path & "\ASCII_TREE.txt"
Open Treefile For Input As iFreefile
Form1.tv.Nodes.Clear
Form1.Tv1.Nodes.Clear
Do While Not EOF(iFreefile)
Line Input #iFreefile, text_line
level = 1
Do While Left$(text_line, 1) = vbTab
level = level + 1
text_line = Mid$(text_line, 2)
Loop
If level > num_nodes Then
num_nodes = level
ReDim Preserve tree_nodes(1 To num_nodes)
End If
If level = 1 Then
Set tree_nodes(level) = Form1.tv.Nodes.Add(, , CreateGUID, text_line)
Else
Set tree_nodes(level) = Form1.tv.Nodes.Add(tree_nodes(level - 1), tvwChild, CreateGUID, text_line)
If level = 2 Then ' Show level 2
tree_nodes(level).EnsureVisible
End If
End If
Loop
Close iFreefile
Open Treefile For Input As iFreefile
Form1.Tv1.Nodes.Clear
Do While Not EOF(iFreefile)
Line Input #iFreefile, text_line
level = 1
Do While Left$(text_line, 1) = vbTab
level = level + 1
text_line = Mid$(text_line, 2)
Loop
If level > num_nodes Then
num_nodes = level
ReDim Preserve tree_nodes(1 To num_nodes)
End If
If level = 1 Then
Set tree_nodes(level) = Form1.Tv1.Nodes.Add(, , CreateGUID, text_line)
Else
Set tree_nodes(level) = Form1.Tv1.Nodes.Add(tree_nodes(level - 1), tvwChild, CreateGUID, text_line)
If level = 2 Then ' Show level 2
tree_nodes(level).EnsureVisible
End If
End If
Loop
' Form1.tv.Nodes.Item(1).EnsureVisible
Close iFreefile
End Sub
Private Sub ProcessAllChildren(ThisNode As Node, PreviousNode As Node)
Dim NextNode As Node
Dim intI As Integer
Set NextNode = ThisNode.Child
For intI = 1 To ThisNode.Children
If NextNode.Children > 0 Then
Call ProcessAllChildren(NextNode, ThisNode)
Call ShuffleChildren(NextNode)
Set NextNode = NextNode.Next
End If
Next intI
End Sub
Private Sub ShuffleChildren(TheNode As Node)
Dim ch As Node
Dim strChildList() As String
Dim intI As Integer
Dim intChildren As Integer
intChildren = TheNode.Children
If intChildren > 0 Then
ReDim strChildList(intChildren - 1)
Set ch = TheNode.Child
strChildList(0) = ch.Text
For intI = 1 To intChildren - 1
Set ch = ch.Next
strChildList(intI) = ch.Text
Next intI
Shuffle strChildList
Set ch = TheNode.Child
For intI = 0 To UBound(strChildList)
ch.Text = strChildList(intI)
Set ch = ch.Next
Next intI
End If
End Sub
Private Sub ProcessAllNodes(ThisNode As Node, PreviousNode As Node)
Dim NextNode As Node
Dim intI As Integer
Set NextNode = ThisNode.Child
For intI = 1 To ThisNode.Children
If NextNode.Children > 0 Then
Call ProcessAllNodes(NextNode, ThisNode)
Call SortChildren(NextNode)
Set NextNode = NextNode.Next
End If
Next intI
End Sub '''
Private Sub SortChildren(TheNode As Node)
Dim ch As Node
Dim ch1() As Node
Dim strChildList() As String
Dim intI As Integer
Dim intChildren As Integer
intChildren = TheNode.Children
If intChildren > 0 Then
ReDim strChildList(intChildren - 1)
ReDim ch1(intChildren - 1)
Set ch = TheNode.Child
Set ch1(0) = TheNode.Child
strChildList(0) = ch.Text
For intI = 1 To intChildren - 1
Set ch = ch.Next
Set ch1(intI) = ch.Next
strChildList(intI) = ch.Text
Next intI
SortChild strChildList, ch1
Set ch = TheNode.Child
For intI = 0 To UBound(strChildList)
ch.Text = strChildList(intI)
Set ch = ch.Next
Next intI
End If
End Sub '
Private Sub SortChild(strData() As String, ch1() As Node)
Dim strResult() As String
Dim chTemp As Node
Dim strTemp As String
Dim boSwap As Boolean
Dim intI As Integer
Dim intJ As Integer
Dim intOL As Integer
Dim intOL1 As Integer
Dim intRnd As Integer
Dim strS() As String
Dim strS1() As String
For intI = 0 To UBound(strData) - 1
boSwap = False
If Mid$(strData(intI), Len(strData(intI)), 1) = "*" Then
intJ = intI + 1
Do
If Mid$(strData(intJ), Len(strData(intJ)), 1) <> "*" Then
intRnd = intJ
strS = Split(strData(intI), " ")
intOL = SetSecondElement(strS)
strTemp = strS(1)
strS1 = Split(strData(intRnd), " ")
intOL1 = SetSecondElement(strS1)
strS(1) = strS1(1)
strS1(1) = strTemp
For intJ = 2 To UBound(strS)
strS(intJ) = vbNullString
Next intJ
For intJ = 2 To UBound(strS1)
strS1(intJ) = vbNullString
Next intJ
strData(intI) = strS(0) & Space(intOL) & strS(1)
strData(intRnd) = strS1(0) & Space(intOL1) & strS1(1)
' &&&&&
' ' The following code was an attempt to move the entire node... but it does not work.
' ' The following three lines basically don't work.
Set chTemp = ch1(intI)
Set ch1(intI) = ch1(intRnd)
Set ch1(intRnd) = chTemp
boSwap = True
Else
intJ = intJ + 1
End If
Loop Until intJ > UBound(strData) Or boSwap = True
End If
Next intI
End Sub