how to build parent-child data table in excel?

后端 未结 2 957
小鲜肉
小鲜肉 2020-12-06 13:07

I have data in this fashion:

Parent  |  Data
---------------
Root    | AAA  
AAA     | BBB  
AAA     | CCC  
AAA     | DDD  
BBB     | EEE  
BBB     | FFF  
         


        
2条回答
  •  忘掉有多难
    2020-12-06 13:53

    I have a simpler solution using TreeView object. If you don't mind the order of the nodes to be difference and using MSCOMCTL.OCX, please use below code.

    Requires MSOCOMCTL.OCX to be registered.

    Consider this data:

    Using a TreeView (adding to a UserForm for visualization, code not shown):

    Code to dump the tree data (normal module, use TreeToText):

    Option Explicit
    
    Private oTree As TreeView
    
    Private Sub CreateTree()
        On Error Resume Next ' <-- To keep running even error occurred
        Dim oRng As Range, sParent As String, sChild As String
    
        Set oRng = ThisWorkbook.Worksheets("Sheet1").Range("A2") ' <-- Change here to match your Root cell
        Do Until IsEmpty(oRng)
            sParent = oRng.Value
            sChild = oRng.Offset(0, 1).Value
            If InStr(1, sParent, "root", vbTextCompare) = 1 Then
                oTree.Nodes.Add Key:=sChild, Text:=sChild
            Else
                oTree.Nodes.Add Relative:=oTree.Nodes(sParent).Index, Relationship:=tvwChild, Key:=sChild, Text:=sChild
            End If
            '--[ ERROR HANDLING HERE ]--
            ' Invalid (Repeating) Child will have the Row number appended
            If Err.Number = 0 Then
                Set oRng = oRng.Offset(1, 0) ' Move to Next Row
            Else
                oRng.Offset(0,1).Value = sChild & " (" & oRng.Row & ")"
                Err.Clear
            End If
        Loop
        Set oRng = Nothing
    End Sub
    
    Sub TreeToText()
        Dim oRng As Range, oNode As Node, sPath As String, oTmp As Variant
    
        ' Create Tree from Data
        Set oTree = New TreeView
        CreateTree
        ' Range to dump Tree Data
        Set oRng = ThisWorkbook.Worksheets("Sheet1").Range("D2") ' <-- Change here
        For Each oNode In oTree.Nodes
            sPath = oNode.FullPath
            If InStr(1, sPath, oTree.PathSeparator, vbTextCompare) > 0 Then
                oTmp = Split(sPath, oTree.PathSeparator)
                oRng.Resize(, UBound(oTmp) + 1).Value = oTmp
                Set oRng = oRng.Offset(1, 0)
            End If
        Next
        Set oRng = Nothing
        Set oTree = Nothing
    End Sub
    

    Output of code (hard code to D2):

    If you have a very large data, you better off load the Range to memory first.

提交回复
热议问题