3

I am trying to dynamically rename a set of columns in Power Query, List1 being the original column names and List2 the new column names. I think I need to merge List1 and List2 into a single list of pairs, but can't figure out the correct syntax.

Many thanks!

    let

    //list of original column names 
    List1= {"Name1","Name2","Name3","Name4"},

    //Create test table
    Source = Table.FromRows({{1231,1233,4121,5232},{3546,3426,1246,3464}} , List1),

    //list of new column names
    List2 = {"NewName 1","NewName 2","NewName 3","NewName 4"},

    //Rename columns (in practice, the two lists of names will be dynamic, not hard coded as below)
    Result = Table.RenameColumns(Source, {
        {"Name1","NewName 1"},
        {"Name2","NewName 2"},
        {"Name3","NewName 3"},
        {"Name4", "NewName 4"}})

    in
        Result

4 Answers 4

4

If you have a table with old and new names then you can use following pattern

let
    rename_list = Table.ToColumns(Table.Transpose(Table2)),
    result = Table.RenameColumns(Table1, rename_list, MissingField.Ignore)
in result

where Table2 is "Rename Table" and Table1 is initial table with data.

This idea is described in details here https://bondarenkoivan.wordpress.com/2015/04/17/dynamic-table-headers-in-power-query-sap-bydesign-odata/

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks Ivan, I'll take a look at this.
I like it - it will always pair up the correct oldname/newname pairs. The Table.ToColumns(Table.Transpose...) solves the "I need to merge List1 and List2 into a single list of pairs" nicely as the second argument for Table.RenameColumns. I can skip the Table.Transpose by using Table2 = Table.FromRows({List1,List2}). I'll step it out in my original problem for completeness.
Thanks Ivan, I've restated the original example using your solution. Many thanks for your help
1

If you have the resulting column names you want, it seems like you could convert Source back to rows, then call Table.FromRows on List2

let

    //list of original column names 
    List1= {"Name1","Name2","Name3","Name4"},

    //Create test table
    Source = Table.FromRows({{1231,1233,4121,5232},{3546,3426,1246,3464}} , List1),

    //list of new column names
    List2 = {"NewName 1","NewName 2","NewName 3","NewName 4"},

    Result = Table.FromRows(Table.ToRows(Source), List2)

in
    Result

(Unless it is wrong to assume that e.g. Name 2 will always be the second column.)

3 Comments

Thanks Carl, I'll take a look at this. It certainly looks a lot simpler than my solution!
I like how Table.ToRows strips out the column names and Table.FromRows rebuilds the table again with List2 as the column new names. As you say, the replacement column names would need to be listed in the correct order within List2.
I've gone with Ivan's answer because in production, I have some columns that I don't want to rename plus I was trying to figure out how to use the Table.RenameColumns function properly. I'll learnt a lot from stepping through your solution, thank you!
1

Stating the original problem according to Ivan's solution, here goes. Carl's has the same result and is a little simpler for the example I gave, however, my situation will benefit from having the rename pairs set out explicitly in a table (ie. Table2). Plus using the MissingField.Ignore parameter with Table.RenameColumns means that it will only change the selection of columns I want to rename in my production query, the rest will remain unchanged.

let

    //list of original column names 
    List1= {"Name1","Name2","Name3","Name4"},

    //Create test table
    Source = Table.FromRows({{1231,1233,4121,5232},{3546,3426,1246,3464}} , List1),

    //list of new column names
    List2 = {"NewName 1","NewName 2","NewName 3","NewName 4"},

    //Rename columns (in practice, the two lists of names will be dynamic, not hard coded as below)

    //Bring List1 and List2 together as rows in a table
    Table2 = Table.FromRows({List1,List2}),

    //Create a list of rename pairs 
    RenameList = Table.ToColumns(Table2),

    //Call to Table.RenameColumns 
    Result = Table.RenameColumns(Source, RenameList, MissingField.Ignore)

in
    Result

Comments

0

Finally... figured it out using the following function

Table.TransformColumnNames(table as table, nameGenerator as function, optional options as nullable record) as table

First create a nameGenerator function (e.g. MyFuncRenameColumns) to provide a new column name given any original column name as an input.

In my example, here's my code for MyFuncRenameColumns:

    let
        MyFunctionSwitchColumnName = (originalColumnName) as text =>
        let
            //list of original column names 
            List1= {"Name1","Name2","Name3","Name4"},

            //Create table
            Source = Table.FromRows({{1231,1233,4121,5232},{3546,3426,1246,3464}} , List1),

            //list of new column names
            List2 = {"NewName 1","NewName 2","NewName 3","NewName 4"},

            //Create table matching List1 to corresponding new value in List2
            CreateRecord = Record.FromList(List2,List1),
            ConvertedtoTable = Record.ToTable(CreateRecord),

            //Filter table to just the row where the input originalColumnName matches 
            ReduceExcess = Table.SelectRows(ConvertedtoTable, each [Name] = originalColumnName),

            //Return the matching result in the [Value] column (or give the original column name if there was no valid match)
            NewColumnName = try ReduceExcess{0}[Value] otherwise originalColumnName

        in 
            NewColumnName
    in
        MyFunctionSwitchColumnName

Here's where you use it as one of the parameters for Table.TransformColumnNames:

    let
        //list of original column names 
        List1= {"Name1","Name2","Name3","Name4"},

        //Create table
        Source = Table.FromRows({{1231,1233,4121,5232},{3546,3426,1246,3464}} , List1),

        RenameColumns = Table.TransformColumnNames(Source, MyFuncRenameColumns)
    in
        RenameColumns

Hope that helps someone!

2 Comments

you said "TransformColumnTypes", did you mean TransformColumnNames?
Unless you have some complex requirements for the function to rename the columns, my solution here is overkill and too complex. It is nice to know the Table.TransformColumnNames function exists, but if you just have a straight column name switch then both Ivan and Carl's answers are much simpler.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.