Correct Sort Order in Table

pjmorris

Well-known Member
Joined
Aug 2, 2012
Messages
2,162
Office Version
  1. 365
Platform
  1. Windows
I have some data shown below. I wish to convert that to the table shown below, but with the information in each column in alphabetical order. Note, that while the Captain doesn't have every category listed against his position in the input table he needs them all listed in the output. The current scheme creates two tblDelegations which are then combined and manipulated to create the output. The Powerquery M Code that does that is shown at the bottom. I confess I don't fully understand how the code works and, so, would be grateful for any advice on how I can get from the input to the output!

Input:
Copy of SY Ashley Accounts - TEST Ashley.xlsm
IJ
6Budget Holding PositionsCategory
7CaptainCapital Expense
8CaptainAdministration
9CaptainCharter & Sale Related
10EngineerComms & Subscription
11Chief StewardCrew
12EngineerEngineering Maintenance
13EngineerFuel/Oil
14Chief OfficerHull & Deck Maintenance
15Chief StewardInterior Maintenance
16CaptainManagement
17Chief OfficerNavigation
18CaptainPayroll
19CaptainPort Fees
20Chief OfficerSafety & Security
21Chief OfficerTenders/Toys
22CaptainYacht Insurance
23Chief StewardOwner/Guest
24EngineerRefit
25Chief StewardVIP
26Chief OfficerAshley 2
Defaults


Incorrect Output (needs column data in alphabetical order):

Copy of SY Ashley Accounts - TEST Ashley.xlsm
BCDE
1CaptainChief OfficerChief StewardEngineer
2Capital ExpenseHull & Deck MaintenanceCrewComms & Subscription
3AdministrationNavigationInterior MaintenanceEngineering Maintenance
4Charter & Sale RelatedSafety & SecurityOwner/GuestFuel/Oil
5ManagementTenders/ToysVIPRefit
6PayrollAshley 2
7Port Fees
8Yacht Insurance
9Comms & Subscription
10Crew
11Engineering Maintenance
12Fuel/Oil
13Hull & Deck Maintenance
14Interior Maintenance
15Navigation
16Safety & Security
17Tenders/Toys
18Owner/Guest
19Refit
20VIP
21Ashley 2
Delegations


Relevant PowerQuery M Code:

Rich (BB code):
let
    Source = Table.Combine({tblDelegations1, #"tblDelegations1 (2)"}),
    #"Removed Duplicates" = Table.Distinct(Source),
    FlatTable = Table.Sort(#"Removed Duplicates",{{"Budget Holding Positions", Order.Ascending}, {"Category", Order.Ascending}}),

    ColForValues = "Category",
    ColToPivot = "Budget Holding Positions",
    PivotColNames = List.Buffer(List.Distinct(Table.Column(FlatTable,ColToPivot))), 
    #"Pivoted Column" = Table.Pivot(FlatTable, PivotColNames, ColToPivot, ColForValues, each _),
    
    TableFromRecordOfLists = (rec as record, fieldnames as list) =>
    let
        PartialRecord = Record.SelectFields(rec,fieldnames),
        RecordToList = Record.ToList(PartialRecord),
        Table = Table.FromColumns(RecordToList,fieldnames)
    in
        Table

    ,#"Added Custom" = Table.AddColumn(#"Pivoted Column", "Values", each TableFromRecordOfLists(_,PivotColNames))
    ,#"Removed Other Columns" = Table.RemoveColumns(#"Added Custom",PivotColNames)
    ,#"Expanded Values" = Table.ExpandTableColumn(#"Removed Other Columns", "Values", PivotColNames)    

in
    #"Expanded Values"

Both tblDelegations are identical:

Copy of SY Ashley Accounts - TEST Ashley.xlsm
AB
1Budget Holding PositionsCategory
2CaptainAdministration
3Chief OfficerAshley 2
4CaptainCapital Expense
5CaptainCharter & Sale Related
6EngineerComms & Subscription
7Chief StewardCrew
8EngineerEngineering Maintenance
9EngineerFuel/Oil
10Chief OfficerHull & Deck Maintenance
11Chief StewardInterior Maintenance
12CaptainManagement
13Chief OfficerNavigation
14Chief StewardOwner/Guest
15CaptainPayroll
16CaptainPort Fees
17EngineerRefit
18Chief OfficerSafety & Security
19Chief OfficerTenders/Toys
20Chief StewardVIP
21CaptainYacht Insurance
Sheet1
 
Done it - wonder whether my solution is the same as yours?

Accounts - Aberlour 21yr Release -Development.xlsm
BCDE
1CaptainBosunChief StewardEngineer
2AdministrationAsahi 2CrewComms & Subscription
3Asahi 2Hull & Deck MaintenanceInterior MaintenanceEngineering Maintenance
4Capital ExpenseNavigationOwner/GuestFuel/Oil
5Charter & Sale RelatedSafety & SecurityVIPRefit
6Comms & SubscriptionTenders/Toys
7Crew
8Engineering Maintenance
9Fuel/Oil
10Hull & Deck Maintenance
11Interior Maintenance
12Management
13Navigation
14Owner/Guest
15Payroll
16Port Fees
17Refit
18Safety & Security
19Tenders/Toys
20VIP
21Yacht Insurance
Delegations


and the relevant code:

Rich (BB code):
let
    Source1 = Excel.CurrentWorkbook(){[Name="tblBdgtHoldgs"]}[Content],
    RemoveNulls = Table.SelectRows(Source1, each ([Budget Holding Positions] <> null)),
    #"Added Custom" = Table.AddColumn(RemoveNulls, "Custom", each "Captain"),
    #"Removed Columns" = Table.RemoveColumns(#"Added Custom",{"Budget Holding Positions"}),
    #"Reordered Columns" = Table.ReorderColumns(#"Removed Columns",{"Custom", "Category"}),
    #"Renamed Columns" = Table.RenameColumns(#"Reordered Columns",{{"Custom", "Budget Holding Positions"}}),

    Join = Table.Combine({RemoveNulls, #"Renamed Columns"}),
    Distinct = Table.Distinct(Join),

    ColForValues = "Category",
    ColToPivot = "Budget Holding Positions",

    PivotColNames = List.Buffer(List.Sort(List.Distinct(Table.Column(Distinct, ColToPivot)), (x as text, y as text)=>
        let
            isCaptain=if x="Captain" then -1 else null,
            other=if x<y then -1 else (if x=y then 0 else 1),
            result= if isCaptain=-1 then isCaptain else other
        in
            result

)),

    Pivot = Table.Pivot(Distinct, PivotColNames, ColToPivot, ColForValues, each List.Sort(_, Order.Ascending)),


    Function = (rec as record, fieldnames as list) =>
        let
            PartialRecord = Record.SelectFields(rec,fieldnames),
            RecordToList = Record.ToList(PartialRecord),
            Table = Table.FromColumns(RecordToList,fieldnames)
        in
            Table,

    TFR = Table.AddColumn(Pivot, "Values", each Function(_,PivotColNames)),
    RC = Table.RemoveColumns(TFR,PivotColNames),
    Expand = Table.ExpandTableColumn(RC, "Values", PivotColNames)
in
    Expand
 
Upvote 0

Excel Facts

Do you hate GETPIVOTDATA?
Prevent GETPIVOTDATA. Select inside a PivotTable. In the Analyze tab of the ribbon, open the dropown next to Options and turn it off
I can say it works :cool: (y)
and no, this is not the same as my M ;)
I didn't use any additional function
Lines: 16 vs 22 :biggrin:

Challenge goes on ? (4 days left)
 
Upvote 0
update:
all lines: 20 vs 32 (no blanks)
no cheating, previous step in next step
 
Upvote 0
Ok, I've removed a number of superfluous lines, but still no where near your 16. That said, minimum lines wasn't part of the challenge and I prefer to ensure that code is readable rather than short (it helps debug it later!). Additionally, I've changed the functionality slightly. Now, the 'Captain' position is whoever is first listed in the Source table as a 'Budget Holding Position' this means that the yacht can use names rather than positions and still identify who is the captain. There's probably a more elegant way to do this, but it suits the evolution of the app. I shall continue to work at reducing the number of lines (now down to 25!), but while I do so, this is the source data followed by the output I want.

Source:

Accounts - Aberlour 21yr Release -Development.xlsm
IJ
6Budget Holding PositionsCategory
7XavierCapital Expense
8XavierAdministration
9XavierCharter & Sale Related
10HaleyComms & Subscription
11EricCrew
12HaleyEngineering Maintenance
13HaleyFuel/Oil
14BosunHull & Deck Maintenance
15EricInterior Maintenance
16XavierManagement
17BosunNavigation
18XavierPayroll
19XavierPort Fees
20BosunSafety & Security
21BosunTenders/Toys
22XavierYacht Insurance
23EricOwner/Guest
24HaleyRefit
25EricVIP
26BosunAshley2
Defaults


Output:

Accounts - Aberlour 21yr Release -Development.xlsm
BCDE
1XavierBosunEricHaley
2AdministrationAshley2CrewComms & Subscription
3Ashley2Hull & Deck MaintenanceInterior MaintenanceEngineering Maintenance
4Capital ExpenseNavigationOwner/GuestFuel/Oil
5Charter & Sale RelatedSafety & SecurityVIPRefit
6Comms & SubscriptionTenders/Toys
7Crew
8Engineering Maintenance
9Fuel/Oil
10Hull & Deck Maintenance
11Interior Maintenance
12Management
13Navigation
14Owner/Guest
15Payroll
16Port Fees
17Refit
18Safety & Security
19Tenders/Toys
20VIP
21Yacht Insurance
Delegations
 
Upvote 0
minimum lines wasn't part of the challenge
of course not :giggle: but would be nice if there is less lines than more
proper M doesn't need debugging
changing Captain to any name wasn't part of challenge ?
hard to say something only from the two tables without M
 
Upvote 0
proper M doesn't need debugging

Well M doesn't have any debugging tools - you have to break the code down into small segments to see what is happening. And I doubt anyone ever, always, wrote bug free code.

Well the code that delivers the output from the source is only marginally different from the code above - actually, all I've done is replace the 'Captain' with (inline) a short piece of M. Thats your challenge :)

I possibly won't be online much in the next couple of days (certainly not for deep thinking!) as I have to paint the kitchen!!
 
Upvote 0
done, unfortunately 18 lines (I'd like less but I think 18 is a good number, isn't it?)
and working with different names
 
Upvote 0

Forum statistics

Threads
1,214,958
Messages
6,122,475
Members
449,087
Latest member
RExcelSearch

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