Build parent/child hierarchy

adygelber

New Member
Joined
May 22, 2012
Messages
26
Hello,

I kindly ask for your support because I have to achieve something that seems to be simple but I just can't figure it out how to do it.

Mainly, I have two columns. The first one contains some parent codes, the second one contains some child codes which can consequently become parent codes for other child codes. And so on.

Having this in mind, I want to create a hierarchy like the one from the below example. The example file was created manually with a minimum number of records but the final database can be way bigger.


ParentChild
AB00000AB00001AB00000AB00001AB00002AB00005AB00009AB00010
AB00001AB00002AB00006
AB00001AB00003AB00005
AB00001AB00004AB00007
AB00002AB00005AB00005
AB00002AB00006AB00003AB00007
AB00002AB00005AB00004AB00008
AB00002AB00007
AB00002AB00005
AB00003AB00007
AB00004AB00008
AB00005AB00009
AB00009AB00010

<colgroup><col style="width:48pt" span="9" width="64"> </colgroup><tbody>
</tbody>


Thank you in advance for your support!
A.B.

Also posted here:
[url]http://www.vbaexpress.com/forum/showthread.php?57247-Build-parent-child-hierarchy

Build parent/child hierarchy
[/URL]
 

Excel Facts

Can a formula spear through sheets?
Use =SUM(January:December!E7) to sum E7 on all of the sheets from January through December
There were some mistakes in the above table, as the same child was allocated to more than one parent and there was also a duplicate record. Please consider this:

ParentChild
AB00000AB00001AB00000AB00001AB00002AB00005AB00009AB00010
AB00001AB00002AB00006
AB00001AB00003AB00007
AB00001AB00004AB00003AB00011
AB00002AB00005AB00004AB00008
AB00002AB00006
AB00002AB00007
AB00003AB00011
AB00004AB00008
AB00005AB00009
AB00009AB00010

<colgroup><col style="width:48pt" span="9" width="64"> </colgroup><tbody>
</tbody>

Thanks!
 
Upvote 0
You could do something like this:

Insert a Class module and name it clsPCNode

Code:
' in clsPCNode class module

Public Name As String
Public Tree As clsPCTree

Public Children As Collection

Function AddChild(ChildsName As String) As clsPCNode
    Set AddChild = Tree.AddNode(ChildsName)
    On Error Resume Next
    Children.Add Item:=AddChild, Key:=AddChild.Name
    On Error GoTo 0
End Function

Sub WriteTo(ByRef StartCell As Range)
    Dim oneChild As clsPCNode
   
    StartCell.Value = Me.Name
    
    If Children.Count = 0 Then
        Set StartCell = StartCell.Offset(1, 0)
    Else
        Set StartCell = StartCell.Offset(0, 1)
        For Each oneChild In Children
            oneChild.WriteTo StartCell
        Next oneChild
        Set StartCell = StartCell.Offset(0, -1)
    End If
End Sub

Private Sub Class_Initialize()
    Set Children = New Collection
End Sub

Insert another class module and name it clsPCTree

Code:
' in clsPCTree class module

Public Nodes As Collection

Function AddNode(NodeName As String) As clsPCNode
    On Error Resume Next
    Set AddNode = Nodes(NodeName)
    If Err Then
        Set AddNode = New clsPCNode
        AddNode.Name = NodeName
        Set AddNode.Tree = Me
        Nodes.Add Item:=AddNode, Key:=NodeName
    End If
    On Error GoTo 0
End Function

Property Get Count() As Long
    Count = Nodes.Count
End Property

Private Sub Class_Initialize()
    Set Nodes = New Collection
End Sub

And then put code like this in a normal module

Code:
Sub test()
    Dim myTree As clsPCTree
    Dim dataRange As Range
    Dim oneCell As Range
    With Sheet1.Range("A:A")
        Set dataRange = Range(.Cells(2, 1), .Cells(Rows.Count, 1).End(xlUp))
    End With
    Set myTree = New clsPCTree
    For Each oneCell In dataRange.Cells
        myTree.AddNode(oneCell.Value).AddChild oneCell.Offset(0, 1).Value
    Next oneCell
    Range("P:T").ClearContents
    myTree.Nodes(1).WriteTo Range("P1")
End Sub

A child having more than one parent is not a problem, but if a person is its own n-child then there is a problem.
 
Last edited:
Upvote 0
Thank you for your quick response Mike,

Unfortunatelly, I receive an "Object variable or With block variable not set" error on line
Code:
myTree.Nodes(1).WriteTo Range("P1")

Can you figure it out?
 
Upvote 0
First, that code is more complicated than needed. I'm at work and can't simplify at the moment. (The key routine in the sum WriteTo)

Second, try naming the top node explicity
Code:
myTree.Nodes("AB00000").WriteTo Range("P1")
 
Upvote 0
I still receive the same error, on the same line, after ammending the code with
Code:
myTree.Nodes("AB00000").WriteTo Range("P1")
but thank you anyway for trying to help me.
There is no hurry so please take your time and if you will have the possibility to find a solution later, I thank you for this.
 
Upvote 0
I deeply appologise for my mistake. Your original code works just fine but by mistake I didn't copy all the lines.

I thank you very much for your solution and I will give it a try with a more complex database.

I let you know :)
 
Upvote 0
This refunded version doesn't need class modules

Code:
Sub test()
    WriteDownFrom CStr(ParentDataRange.Cells(1, 1)), Range("G1")
End Sub

Sub WriteDownFrom(ByVal aPerson As String, ByRef WriteTo As Range)
    Dim Children As Collection
    Dim oneCell As Range
    Dim i As Long
    
    Set Children = New Collection
    For Each oneCell In ParentDataRange.Columns(1).Cells
        If LCase(oneCell.Value) = LCase(aPerson) Then
            On Error Resume Next
                Children.Add Item:=oneCell.Offset(0, 1), Key:=CStr(oneCell.Offset(0, 1))
            On Error GoTo 0
        End If
    Next oneCell
    
    WriteTo.Value = aPerson
    
    If Children.Count = 0 Then
        Set WriteTo = WriteTo.Offset(1, 0)
    Else
        Set WriteTo = WriteTo.Offset(0, 1)
        For i = 1 To Children.Count
            WriteDownFrom Children(i), WriteTo
        Next i
        Set WriteTo = WriteTo.Offset(0, -1)
    End If
    
End Sub

Function ParentDataRange() As Range
    With Sheet1.Range("A:A")
        Set ParentDataRange = Range(.Cells(2, 1), .Cells(Rows.Count, 1).End(xlUp))
    End With
    Set ParentDataRange = ParentDataRange.Resize(, 2)
End Function
 
Upvote 0
Hey Mike,

Your solution works perfectly on my example but not on the big database.
Anyway, I think that is something wrong with the database so please allow me one or two working days and I will come back to you with an answer.

Thank you very much for your work,
A.B.
 
Upvote 0

Forum statistics

Threads
1,215,890
Messages
6,127,595
Members
449,386
Latest member
owais87

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top