Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
Syndicate_Admin
Administrator
Administrator

Add rows to table that repeats unique column countdown starting from value in another column, for a set number of times.

Having trouble figuring out the direction I need to go for this table I want to make.  Will continue to research functions but wanted to pose the general question to the community.

I have this table built in power query->

ToolnameToollifeCurrentlifeCost
Alpha55

50

Bravo5220
Charlie3330
Delta6630

 

and need an output table like this->

part countAlphaBravoCharlieDeltatotal changestotal cost
110113110
2000000
30100120
40010130
5000000
61000150
70011260
80100120
9000000
100010130

 

Where the 1 values under the name columns are the cells in this table where cellvalue=Toollife of [columnname].  The countdown under each [Toolname] column should start from the [Currentlife] value for the same Toolname set in the original table.  With [part count] counting up from 1 to #"Default_Values"{0}[part_count] (this is another table with some default values built into it).

part countAlphaBravoCharlieDelta
15236
24125
33514
42433
51322
65211
74136
83525
92414
101333

 

TIA.

 

11 REPLIES 11
AlienSx
Super User
Super User

let
    tools_raw = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WcswpyEhU0lEyhWEDpVidaCWnosSyfKiQEQhDhJ0zEotyMlOBAsYwDJFwSc0pARljBsUg4VgA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Toolname = _t, Toollife = _t, Currentlife = _t, Cost = _t]),
    tools = Table.TransformColumnTypes(tools_raw,{{"Toollife", Int64.Type}, {"Currentlife", Int64.Type}, {"Cost", Currency.Type}}),
    // number of parts parameter
    parts_number = 10,
    // names and parts lists
    tool_names = List.Buffer(tools[Toolname]),
    parts_list = List.Buffer({1..parts_number}),
    // function calculates positions of tools and adds field with positions list to tool record
    fx_tools_add_positions = (r as record, parts as number) as record => 
        Record.AddField(
            r,
            "positions",
            List.Numbers(
                List.Max({r[Toollife] - r[Currentlife], 1}), 
                Number.RoundAwayFromZero(parts / r[Toollife]), 
                r[Toollife])
        ),
    // creates list of tools records from tools table
    tools_with_positions = 
        List.Buffer(
                List.Transform(
                    Table.ToRecords(tools),
                    each fx_tools_add_positions(_, parts_number)
                )
        ),
    // iterates list of parts then list of tools for each part to get rows of final table 
    r = List.Transform(
            parts_list,
            (x) => 
                let 
                    p = [part_count = x, total_changes = 0, total_cost = 0],
                    w = List.Accumulate(
                            List.Positions(tool_names),
                            p,
                            (s, c) => 
                                let 
                                    t_rec = tools_with_positions{c},
                                    bit = 
                                        Number.From(
                                            List.Contains(
                                                Record.Field(t_rec, "positions"), x
                                            )
                                        ),
                                    name_field = Record.AddField(s, t_rec[Toolname], bit),
                                    other_fields =
                                        Record.TransformFields(
                                            name_field,
                                            {{"total_changes", each s[total_changes] + bit},
                                            {"total_cost", each s[total_cost] + bit * t_rec[Cost]}}
                                        )
                                in other_fields
                        )
                in w
    ),
    // list of records >> table
    to_table = Table.FromRecords(r),
    // reordering columns. You may add rename columns step if you want
    reorder = Table.ReorderColumns(to_table,{"part_count"} & tool_names & {"total_changes", "total_cost"})
in
    reorder
Anonymous
Not applicable

This almost worked.  The math breaks down with larger tool life and current life values.  I adjusted the function and it looks like the values are populating correctly, EXCEPT the [part_count]=1 field is not populating with a 1 where toollife=currentlife.  I cannot figure out how to adjust it for that yet.

fx_tools_add_positions = (r as record, parts as number) as record => 
        
        Record.AddField(
            r,
            "positions",
            List.Numbers(
                r[Currentlife]+1, 
                Number.RoundAwayFromZero(parts / r[Toollife]), 
                r[Toollife])
        )
        ,

 

please give an example of toollife and currentlife values combination that gives wrong result (or error).  

I got this to work now by adjusting the custom function like so:

fx_tools_add_positions = (r as record, parts as number) as record => 
        if r[Currentlife]=r[Toollife]
        then
        Record.AddField(
            r,
            "positions",
            List.InsertRange(
                 List.Numbers(
                r[Currentlife]+1, 
                Number.RoundAwayFromZero(parts / r[Toollife]), 
                r[Toollife]),0,
                List.Numbers(1,1)
            )
        )
        else
        Record.AddField(
            r,
            "positions",
            List.Numbers(
                r[Currentlife]+1, 
                Number.RoundAwayFromZero(parts / r[Toollife]), 
                r[Toollife])
        )
        ,
Anonymous
Not applicable

When I input 100 for a tool life and 2 for a current life, the first "1" set for that tool was at part #98, then every 100 parts# after that.

need to change initial value in that function

    fx_tools_add_positions = (r as record, parts as number) as record => 
        Record.AddField(
            r,
            "positions",
            List.Numbers(
                if r[Toollife] = r[Currentlife] then 1 else r[Currentlife] + 1,
                Number.RoundAwayFromZero(parts / r[Toollife]), 
                r[Toollife])
        ),
wdx223_Daniel
Super User
Super User

wdx223_Daniel_0-1679882528259.png

let
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WcswpyEhU0lEyhWEDpVidaCWnosSyfKiQEQhDhJ0zEotyMlOBAsYwDJFwSc0pARljBsUg4VgA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Toolname = _t, Toollife = _t, Currentlife = _t, Cost = _t]),
    #"Changed Type" = Table.TransformColumnTypes(Source,{{"Toollife", Int64.Type}, {"Currentlife", Int64.Type}, {"Cost", Int64.Type}}),
    Custom1 = let PartCount=10 in #table({"Part Count"}&#"Changed Type"[Toolname]&{"Total Changes","Total Cost"},List.Transform({1..PartCount},(x)=>let a=List.Transform(Table.ToRows(#"Changed Type"),each let n=Byte.From(Number.Mod(_{1}-x+1+_{2},_{1})=0) in {n,n*_{3}}),b=List.Zip(a) in {x}&b{0}&{List.Sum(b{0}),List.Sum(b{1})}))
in
    Custom1

 

Anonymous
Not applicable

This worked but is extremely slow, my table is 40 toolnames long with 250-500 part counts.  Is this speed expected with a table that large?  Even loading 10 rows probably took 2 minutes.

let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WcswpyEhU0lEyhWEDpVidaCWnosSyfKiQEQhDhJ0zEotyMlOBAsYwDJFwSc0pARljBsUg4VgA", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Toolname = _t, Toollife = _t, Currentlife = _t, Cost = _t]),
ChangeType = Table.TransformColumnTypes(Source,{{"Toollife", Int64.Type}, {"Currentlife", Int64.Type}, {"Cost", type number}}),
Parts_number = 10,
Pattern = Table.AddColumn(ChangeType, "Pattern", each {1} & List.Repeat({0}, [Toollife]-1)),
ListRepeat = Table.AddColumn(Pattern, "List.Repeat", each List.Repeat([Pattern], Number.IntegerDivide(Parts_number, [Toollife]) +2)),
ListRange = Table.AddColumn(ListRepeat, "ListRange", each List.Range([List.Repeat], [Toollife]-[Currentlife], Parts_number)),
Table = Table.FromColumns({{1..Parts_number}} & ListRange[ListRange], {"part count"} & ListRange[Toolname]),
Quantity = Table.AddColumn(Table, "Quantity", each List.Skip(Record.ToList(_), 1)),
Changes = Table.AddColumn(Quantity, "Total changes", each List.Sum([Quantity])),
Cost = Table.AddColumn(Changes, "Cost", each List.Sum(List.Transform(List.Zip({[Quantity], ChangeType[Cost]}), List.Product))),
RemoveColumns = Table.RemoveColumns(Cost,{"Quantity"})
in
RemoveColumns

Tested with 200 toolnames and 500 parts counts. Very fast.

Stéphane 

Anonymous
Not applicable

This is still not fast for me. Could I be setting up the Source wrong? I duplicate my table then go to advanced editor and copy your code, replacing the Source = line to this: Source = #"first_tool_data"

may be add "List.Buffer"

 

let
Source = Your_Source,
ChangeType = Table.TransformColumnTypes(Source,{{"Toollife", Int64.Type}, {"Currentlife", Int64.Type}, {"Cost", type number}}),
Parts_number = 500,
ListBuffer = List.Buffer(ChangeType[Cost]),
Pattern = Table.AddColumn(ChangeType, "Pattern", each {1}&List.Repeat({0},[Toollife]-1)),
ListRepeat = Table.AddColumn(Pattern, "List.Repeat", each List.Repeat([Pattern],Number.IntegerDivide(Parts_number,[Toollife])+2)),
ListRange = Table.AddColumn(ListRepeat, "ListRange", each List.Range([List.Repeat],[Toollife]-[Currentlife],Parts_number)),
Table = Table.FromColumns({{1..Parts_number}} & ListRange[ListRange], {"part count"} & ListRange[Toolname]),
Quantity = Table.AddColumn(Table, "Quantity", each List.Skip(Record.ToList(_),1)),
Changes = Table.AddColumn(Quantity, "Total changes", each List.Sum([Quantity])),
Cost = Table.AddColumn(Changes, "Cost", each List.Sum(List.Transform(List.Zip({[Quantity],ListBuffer}),List.Product))),
RemoveColumns = Table.RemoveColumns(Cost,{"Quantity"})
in
RemoveColumns

 

3 seconds with 200 toolnames and Parts_number = 500

 

Stéphane

 

Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

Find out what's new and trending in the Fabric Community.

Top Solution Authors
Top Kudoed Authors