Create Parent/Child Power Query

Skybluekid

Well-known Member
Joined
Apr 17, 2012
Messages
1,231
Office Version
  1. 365
Platform
  1. Windows
Hi All,

Is it possible to create a Parent Child table in PQ? All the values I have are text
 

Excel Facts

Create a chart in one keystroke
Select the data and press Alt+F1 to insert a default chart. You can change the default chart to any chart type
Is it possible to create a Parent Child table in PQ? All the values I have are text
As long as you have matching fields in the source tables, you can join the parent and child tables (one-to-one, one-to-many, etc.) by using the Merge feature explained in the following Excel Article.

Parent & Child Relationship Between Sources in Power Query

Edit: I moved the generic Parent & Child Relationship content I posted to the Excel Article section since it is not related to these question.
 
Last edited:
Upvote 0
Thanks @smozgur for the above. Not quite what I was looking for. What I have is illustrated below.
Book1
ABCDEFGHIJ
1Input ValuesExpected Resuts
2Top AssblyABC-1000ABC-1000
3Sub Assbly 1ABC-1000-1ABC-1001-1
4Sub Assbly 2ABC-1000-2ABC-1100-1
5Sub Assbly 3ABC-1000-3ABC-1200-1
6Sub Assbly 4ABC-1000-4ABC-1300-1
7Sub Assbly 5ABC-1000-5ABC-1000-2
8ABC-2100-1
9Sub Assbly ABC-1000-10085-00971
10PartABC-1100-10085-00972
11PartABC-1200-1ABC-2200-1
12PartABC-1300-1ABC-2300-1
13ABC-1000-3
14Sub Assbly ABC-1000-2ABC-1000-4
15PartABC-2100-1ABC-4100-1
16PartABC-2200-1ABC-4200-1
17PartABC-2300-1ABC-4300-1
18ABC-1000-5
19Sub Assbly ABC-2100-1
20Part0085-00971
21Part0085-00972
22
23Sub Assbly ABC-1000-4
24PartABC-4100-1
25PartABC-4200-1
26PartABC-4300-1
Sheet1


I have a top level part and all the components for that make up this part. The list comes as the Input Values and I was wondering if, the help of PQ to created the he expected result. Just to give some sort of perspective, the sub assemblies could go to 4 generations, not just the two that I have shown.
 
Upvote 0
Aha! Extremely unexpected data model and desired result. I think I should move my previous post to the Excel Articles forum as a generic Join implementation in Power Query since it has nothing to do with your question. :)

Now, looking at your sample data and now I agree with @ExcelToDAX about asking for the sample data first. I am not available to look at this at the coding level today but maybe tomorrow. I am sure other PQ users will be also interested and probably even post solutions before I can make it. I am wondering one thing about the data input. Is it loaded exactly as it is shown in the sample data with "Sub Assbly ABC-XXXX-Y" headers? Since the keys must be parsed from headers, can you confirm the same pattern will be used all the time?

I was wondering if, the help of PQ to created the he expected result.
I believe it can be done.
 
Upvote 0
@smozgur Yes, I can confirm that the format will be the same. I am able to control the output format. The actual key looks like

B of M: XXXXX-XXXX-XX ABC

Thank you for looking into this
 
Upvote 0
I am able to control the output format.
Just curious since you mentioned this, can you change the output as shown below as it will dramatically reduce the data cleansing steps in Power Query? Even without the first row with "Input Values" (the first row is not a big deal but if you have total control on it, why not).
Input Values
Top AssblyABC-1000
ABC-1000ABC-1000-1
ABC-1000ABC-1000-2
ABC-1000ABC-1000-3
ABC-1000ABC-1000-4
ABC-1000ABC-1000-5
ABC-1000-1ABC-1100-1
ABC-1000-1ABC-1200-1
ABC-1000-1ABC-1300-1
ABC-1000-2ABC-2100-1
ABC-1000-2ABC-2200-1
ABC-1000-2ABC-2300-1
ABC-2100-10085-00971
ABC-2100-10085-00972
ABC-1000-4ABC-4100-1
ABC-1000-4ABC-4200-1
ABC-1000-4ABC-4300-1
 
Upvote 0
No, I cant do that but I could write a VBA Script to get it in that state.
 
Last edited:
Upvote 0
The following is the sample data I used. I basically created a table named Data by selecting this range (including the empty cell next to the first cell).
Note: I believe G3 in your sample result should be ABC-1000-1.

Input ValuesColumn1
Top AssblyABC-1000
Sub Assbly 1ABC-1000-1
Sub Assbly 2ABC-1000-2
Sub Assbly 3ABC-1000-3
Sub Assbly 4ABC-1000-4
Sub Assbly 5ABC-1000-5
Sub Assbly ABC-1000-1
PartABC-1100-1
PartABC-1200-1
PartABC-1300-1
Sub Assbly ABC-1000-2
PartABC-2100-1
PartABC-2200-1
PartABC-2300-1
Sub Assbly ABC-2100-1
Part0085-00971
Part0085-00972
Sub Assbly ABC-1000-4
PartABC-4100-1
PartABC-4200-1
PartABC-4300-1


Here is the M code:
Power Query:
let
    // The worksheet table name is Data
    Source = Excel.CurrentWorkbook(){[Name="Data"]}[Content],
   
    PhraseSub = "Sub Assbly",
    PhrasePart = "Part",
   
    ColumnNames = Table.ColumnNames(Source),
    ChangeType = Table.TransformColumnTypes(Source, List.Transform(ColumnNames, each {_, type text})),
    Root = Record.Field(ChangeType{0}, ColumnNames{1}),
    Subs = Table.RenameColumns(Table.SelectRows(ChangeType, each Text.StartsWith(Record.Field(_, ColumnNames{0}), PhraseSub) and Record.Field(_, ColumnNames{1}) <> null),  {ColumnNames{0}, "ID"}),
    Tops = Table.TransformColumns(Subs, {"ID", each Root, type text}),
    Parts = Table.SelectRows(ChangeType, each Text.StartsWith(Record.Field(_, ColumnNames{0}), "Part") or (Text.StartsWith(Record.Field(_, ColumnNames{0}), PhraseSub) and Record.Field(_, ColumnNames{1}) = null)),
    GroupSubs = Table.FillDown(Table.AddColumn(Parts, "Col", each if Record.Field(_, ColumnNames{0}) = PhrasePart then null else Record.Field(_, ColumnNames{0})), {"Col"}),
    RemoveNulls = Table.SelectRows(GroupSubs, each (Record.Field(_, ColumnNames{1}) <> null)),
    SubIDs = Table.SelectColumns(Table.AddColumn(RemoveNulls, "ID", each Text.Replace([Col], PhraseSub & " ", ""), type text),{"ID", ColumnNames{1}}),
    AddTops = Table.Combine({Tops, SubIDs}),
    ReorderColumns = Table.InsertRows(Table.ReorderColumns(Table.RenameColumns(AddTops,{{ColumnNames{1}, "Children"}}), {"Children", "ID"}), 0, {[Children = Root, ID = null]}),
   
    fnAddParent = (Table as table, ColumnName as text, i as number) =>
        let
            ForeignKey = "Parent" & Number.ToText(i),
            TableWithParent = Table.ExpandTableColumn(Table.NestedJoin(Table, ColumnName, Table, "Children", "Join", JoinKind.LeftOuter), "Join", {"ID"}, {ForeignKey}),
            Result = if Table.RowCount(Table.SelectRows(TableWithParent, each (Record.Field(_, ForeignKey) <> null))) = 0 then
                        Table
                    else
                        @fnAddParent(TableWithParent, ForeignKey, i + 1)
        in
            Result,

    ParentChild = fnAddParent((ReorderColumns), "ID", 0),
    FinalColumnNames = List.Sort(Table.ColumnNames(ParentChild), Order.Descending),
    ReverseColumns = Table.ReorderColumns(ParentChild, FinalColumnNames),
    AlignNulls = Table.FromRecords(List.Transform(List.Transform(Table.ToRows(ReverseColumns), List.RemoveNulls), each Record.FromList(_, List.FirstN(Table.ColumnNames(ReverseColumns), List.Count(_)))), FinalColumnNames, MissingField.UseNull),
    Sort = Table.Sort(AlignNulls, List.Transform(FinalColumnNames, each {_, Order.Ascending})),

    EmptyDups = List.Accumulate(
            {1..(List.Count(FinalColumnNames) - 1)},
            Sort,
            (state, current) =>
                let
                    Result = Table.FromRecords(Table.TransformRows(state,
                                    (r) => Record.TransformFields(r,
                                            {FinalColumnNames{current - 1}, each if Record.Field(r, FinalColumnNames{current}) = null then _ else null})))
                in
                    Result
        ),
    Result = Table.RenameColumns(EmptyDups, List.Zip({FinalColumnNames, List.Transform({1..Table.ColumnCount(EmptyDups)}, each "Assembly" &  Number.ToText(_))}))
in
    Result
And the result:
Assembly1Assembly2Assembly3Assembly4
ABC-1000
ABC-1000-1
ABC-1100-1
ABC-1200-1
ABC-1300-1
ABC-1000-2
ABC-2100-1
0085-00971
0085-00972
ABC-2200-1
ABC-2300-1
ABC-1000-3
ABC-1000-4
ABC-4100-1
ABC-4200-1
ABC-4300-1
ABC-1000-5

Phrase identifiers (variables) at the beginning are for identifying the key positions.
The code works dynamically. So it doesn't matter how many assembly generations exist.
 
Upvote 0

Forum statistics

Threads
1,223,947
Messages
6,175,562
Members
452,652
Latest member
eduedu

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