
Some time again, I used to be engaged on a mission involving getting knowledge from Excel recordsdata. The Excel recordsdata include the info in sheets and tables. Getting the info from the tables is straightforward. Nevertheless, the info within the sheets have some commentaries on high of the sheet, then the column names after which the info itself. One thing like under:
This method is fairly constant throughout many Excel recordsdata. The shopper needs to have the commentary within the column names when the info is imported into Energy BI. So the ultimate outcome should appear to be this:
The enterprise requirement although is to mix the primary 3 rows of knowledge and advertise because the column title.
The Problem
Let’s join the Excel file and have a look at the info in Energy BI Desktop.
As you may see within the previous picture, Energy BI, or extra exactly, Energy Question, sees the info in Desk format. After we click on the Rework Information button, that is what we get in Energy Question Editor:
Everyone knows that tables include Columns and Rows. The conjunction of a column and a row is a Cell. What we require to do is to concatenate the values of cells from the primary three rows. We even have to make use of a Area character to separate the values of every cell from the others.
In Energy Question, we will get every row of knowledge in as a Report with the next syntax:
Desk{RecordIndex}
Within the above syntax, the Desk
may be the outcomes of the earlier transformation step, and the RecordIndex
begins from 0
. So to get the primary row of the desk within the previous picture, we use the next syntax:
#"Modified Sort"{0}
The place the #"Modified Sort"
is the earlier step. Listed below are the outcomes of operating the previous expression:
So we will get the second and third rows with comparable expressions. The next picture exhibits the complete codes within the Superior Editor:

However how can we concatenate the values of the rows?
My method is:
- Making a desk from the primary three rows
- Transposing the resutls to get the rows as columns
- Merging the columns right into a single column
- Transposing the brand new column
- Appending the transposed values to the unique desk
- Selling the primary row as column names
Right here is how we achieve this:
- We create a Desk from Data utilizing the Desk.FromRecords() operate:
- Transposing the resutls to get the rows as columns
- Merging all columns and eradicating the columns. To take action we choose all columns, right-click a particular column and click on Merge Columns. We use Area because the separator
- Transposing the brand new merged column
- Appending the transposed outcomes to the unique desk. The resutls of the third transformation step provides us the orignial desk. We use the
Desk.Mix()
operate
Desk.Mix({#"Transposed Table1", #"Modified Sort"})
As you may within the previous picture, the outcomes will not be what we wish as we nonetheless have the primary 3 rows showing within the values. So earlier than we append the transposed outcomes to the unique desk, we’ve to take away the primary 3 rows from the unique desk, after which append the outcomes. To take away the primary N rows we use Desk.Skip()
operate. So we’ve to vary the earlier step as follows:
Desk.Mix({#"Transposed Table1", Desk.Skip(#"Modified Sort", 3)})

- Selling the primary row as column names
Straightforward!
Hmm… Not likely. Particularly when we’ve a number of different Excel recordsdata; some have two, some have three rows of feedback, and a few have much more. So not solely is the duty time-consuming, but it surely is also fairly boring and vulnerable to human errors. What if there’s a customized operate that I can invoke to get the job achieved?
The Answer
To beat the problem, I wrote a fairly dynamic customized operate. It accepts a desk and an iterator. The iterator is the variety of rows we wish to concatenate and use because the column names. After invoking the operate, it iterated by the primary X variety of rows following the situation I defined within the earlier part. It then appends the transposed outcomes to the unique desk whereas eradicating the primary X variety of rows.
Right here you go…
After I examined my unique operate with completely different knowledge varieties, I famous that I needed to convert the remark values to textual content knowledge sort; in any other case, dynamically, the merging columns step breaks because it can not concatenate textual content and quantity values.
A giant shout-out to Imke Feldman for writing such useful blogposts. I used her method in a single block of the next code to dynamically convert the columns to textual content.
// fn_CombineTopXRows
(InputTable as desk, Iterator as quantity) as desk =>
let
TopXRows = Checklist.Generate(
() => 0
, every _ < Iterator
, every _ + 1
, every InputTable{_}
),
TableFromRecords = Desk.FromRecords(
Checklist.Generate(
() => 0
, every _ < Iterator
, every _ + 1
, every InputTable{_}
)
),
TransposeTable = Desk.Transpose(
TableFromRecords
, Checklist.Generate(
() => 0
, every _ < Iterator
, every _ + 1
, every "Col" & Textual content.From(_)
)
),
// Particular because of Imke Feldman for this line of code?
// https://www.thebiccountant.com/2017/01/09/dynamic-bulk-type-transformation-in-power-query-power-bi-and-m/
DataTypeToText = Desk.TransformColumnTypes(
TransposeTable
, Checklist.Rework(
Desk.ColumnNames(TransposeTable)
, every {_, sort textual content}
)
),
CombineColumns = Desk.CombineColumns(
DataTypeToText
, Checklist.Generate(
() => 0
, every _ < Iterator
, every _ + 1
, every "Col" & Textual content.From(_)
)
, Combiner.CombineTextByDelimiter(
" "
, QuoteStyle.None
)
,"Merged"
),
TransposeCombined = Desk.Transpose(CombineColumns),
AppendToOriginalTable = Desk.Mix({TransposeCombined, Desk.Skip(InputTable, Iterator)}),
PromotedHeaders = Desk.PromoteHeaders(AppendToOriginalTable, [PromoteAllScalars=true])
in
PromotedHeaders
You may obtain the code from right here.
Let’s see the fn_CombineTopXRows
customized operate in motion. Listed below are the outcomes after invoking the operate with our earlier pattern knowledge:
Here’s a extra excessive pattern knowledge containing particular characters, nulls and Unicode characters:
And listed here are the outcomes of invoking the fn_CombineTopXRows
customized operate:

As all the time, when you have any feedback or you realize a greater manner than I defined right here, please let me know through the feedback part under.
Replace
After sharing this submit on LinkedIn, Muneer Marzouq, commented that he would write the customized operate in another way. I favored his method, so I share his code right here.
// fn_CombineTopNRows
// Supply: https://www.linkedin.com/feed/replace/urn:li:exercise:6866137870068002816?commentUrn=urnpercent3Alipercent3Acommentpercent3Apercent28activitypercent3A6866137870068002816percent2C6866640507234254848percent29&replyUrn=urnpercent3Alipercent3Acommentpercent3Apercent28activitypercent3A6866137870068002816percent2C6867174468557529088percent29
(InputTable as desk, TopNRows as quantity, elective Delimiter as nullable textual content) as desk =>
let
Delimiter = if Delimiter <> null then Delimiter else "#(lf)",
ToTables = Desk.Cut up(InputTable, TopNRows),
ColsNames = Desk.ColumnNames(ToTables{0}),
ToText =
Desk.TransformColumnTypes(
ToTables{0}
, Checklist.Rework(
ColsNames
, every {_, sort textual content}
)
),
ToColumns = Desk.ToColumns(ToText),
CombineText =
Checklist.Rework(
ToColumns
, every Textual content.Mix(_
, Delimiter
)
),
ToTable = Desk.FromRows({CombineText}, ColsNames),
Mix = Desk.Mix({ToTable, ToTables{1}})
in
Mix
Replace 2022 Jan
Right here is one other resolution that Mahmoud Baniasadi put within the feedback part. What I like about Mahmoud’s code are:
- Utilizing the
Desk.SplitAt()
operate which returns a listing of two tables as a substitute ofDesk.Cut up()
operate which returns a listing of tables - Implementing the operate documentation
let func=
(InputTable as desk, TopNRows as quantity, elective Delimiter as nullable textual content) as desk =>
let
Delimiter = if Delimiter <> null then Delimiter else "#(lf)",
// Correction: Change Desk.Cut up to Desk.SplitAt
ToTables = Desk.SplitAt(InputTable, TopNRows),
ColsNames=Desk.ColumnNames(ToTables{0}),
ToText= Desk.TransformColumnTypes(
ToTables{0}
, Checklist.Rework(
ColsNames
, every {_, sort textual content}
)
),
/* My various technique for this half
CombineText=
Checklist.Rework(
Desk.ToList(
Desk.Transpose(ToText),
Combiner.CombineTextByDelimiter(Delimiter,0)),
every Textual content.Trim(_)),
*/
// Muneer Marzouq Answer
ToColumns=Desk.ToColumns(ToText),
CombineText =
Checklist.Rework(
ToColumns
, every Textual content.Mix(_
, Delimiter
)
),
//Finish of Muneer code which is completely different from mine
ToTable = Desk.FromRows({CombineText}, ColsNames),
Mix = Desk.Mix({ToTable, ToTables{1}}),
// Correction: add one step to advertise mixed rows as header
PromotedHeaders = Desk.PromoteHeaders(Mix, [PromoteAllScalars=true])
in
PromotedHeaders,
// Add documentation
documentation = [
Documentation.Name = " fn_CombineTopNRows ",
Documentation.Description = " Returns a Table with Combining X Number of Rows. ",
Documentation.LongDescription = " Returns a Table with Combining X Number of Rows and Promote them as header. ",
Documentation.Category = " Table ",
Documentation.Source = " https://www.biinsight.com/combining-x-number-of-rows-in-power-query-for-power-bi-excel-and-power-query-online/ ",
Documentation.Version = " 1.0 ",
Documentation.Author = " Muneer Marzouq, Mahmoud Bani Asadi, Soheil Bakhshi ",
Documentation.Examples = {[Description = " see this blogpost: https://www.biinsight.com/combining-x-number-of-rows-in-power-query-for-power-bi-excel-and-power-query-online/ ",
Code = " fn_CombineTopNRows(#table({""Column1"", ""Column2"", ""Column3""}, {{""TitleA"", ""TitleC"", ""Title1""}, {""TitleB"", ""TitleD"", ""Title2""}, {7, 8, 9}}), 2, "" "")",
Result = " #table({""TitleA TitleB"", ""TitleC TitleD"", ""Title1 Title2""}, {{7, 8, 9}}) "]}]
in
Worth.ReplaceType(func, Worth.ReplaceMetadata(Worth.Sort(func), documentation))
For this reason I like information sharing. You be taught one thing new from others day-after-day.
Associated
Uncover extra from BI Perception
Subscribe to get the newest posts despatched to your e mail.