Forum Discussion

Licantrop0's avatar
Licantrop0
Microsoft Employee
6 years ago
Solved

Split table in multiple tables by blank rows

I have a single CSV file that is actually separate tables.

The tables are separate by a blank row, after which there is a new header:

 

The number of rows in each sub-table may change, so I cannot use "keep first N rows".

 

I need a function to split this table into multiple tables whenever there is a blank row.

Or at least an M function to tell me what is the first blank row number so I can use it as parameter of the Table.Skip function.

 

Thanks for any help!

  • ImkeF's avatar
    ImkeF
    6 years ago

    Hi Licantrop0 ,

     

    you can create a staging table that holds the partitions to be referenced by further queries.

    Please paste the following code into the advanced editor and follow the steps:

     

    let
        Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45W8khNTEktMlTSgbKMgCylWJ1oJZCQMYwDEjWBcUA0lIlNN4RljGKIKYopZhA5AyDTCEQYG6Cb65iXX5KRWqSQATYLScIQiW0EY8cCAA==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Column1 = _t, Column2 = _t, Column3 = _t]),
        #"Changed Type" = Table.TransformColumnTypes(Source,{{"Column1", type text}, {"Column2", type text}, {"Column3", type text}}),
        #"Added Index" = Table.AddIndexColumn(#"Changed Type", "Index", 0, 1, Int64.Type),
        #"Added Custom" = Table.AddColumn(#"Added Index", "Custom", each if [Column1] = "" then [Index] else null),
        #"Filled Down" = Table.FillDown(#"Added Custom",{"Custom"}),
        #"Removed Columns" = Table.RemoveColumns(#"Filled Down",{"Index"}),
        #"Filtered Rows" = Table.SelectRows(#"Removed Columns", each ([Column1] <> "")),
        #"Grouped Rows" = Table.Group(#"Filtered Rows", {"Custom"}, {{"All", each _, type table [Column1=nullable text, Column2=nullable text, Column3=nullable text, Custom=nullable number]}})
    in
        #"Grouped Rows"

     

5 Replies

    • ImkeF's avatar
      ImkeF
      Community Champion

      Hi Licantrop0 ,

       

      you can create a staging table that holds the partitions to be referenced by further queries.

      Please paste the following code into the advanced editor and follow the steps:

       

      let
          Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45W8khNTEktMlTSgbKMgCylWJ1oJZCQMYwDEjWBcUA0lIlNN4RljGKIKYopZhA5AyDTCEQYG6Cb65iXX5KRWqSQATYLScIQiW0EY8cCAA==", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Column1 = _t, Column2 = _t, Column3 = _t]),
          #"Changed Type" = Table.TransformColumnTypes(Source,{{"Column1", type text}, {"Column2", type text}, {"Column3", type text}}),
          #"Added Index" = Table.AddIndexColumn(#"Changed Type", "Index", 0, 1, Int64.Type),
          #"Added Custom" = Table.AddColumn(#"Added Index", "Custom", each if [Column1] = "" then [Index] else null),
          #"Filled Down" = Table.FillDown(#"Added Custom",{"Custom"}),
          #"Removed Columns" = Table.RemoveColumns(#"Filled Down",{"Index"}),
          #"Filtered Rows" = Table.SelectRows(#"Removed Columns", each ([Column1] <> "")),
          #"Grouped Rows" = Table.Group(#"Filtered Rows", {"Custom"}, {{"All", each _, type table [Column1=nullable text, Column2=nullable text, Column3=nullable text, Custom=nullable number]}})
      in
          #"Grouped Rows"

       

      • Licantrop0's avatar
        Licantrop0
        Microsoft Employee

        Thanks so much ImkeF !

        That's a very good workaround.

        I hoped there was a more streamlined solution like:

        Table.Split([TableName], <condition>)

        but I guess I'll have to open a new uservoice item for it... 

  • TheBoojum's avatar
    TheBoojum
    Frequent Visitor

    I know this is a slightly old post, but I had a similar problem and found this article which gives a very good way of flagging empty rows:

    https://www.thebiccountant.com/2016/03/08/select-rows-that-have-no-empty-fields-using-expression-evaluate-in-power-bi-and-power-query/ 

     

    There is a really neat approach documented in the comments:

     

    = Table.SelectRows(Source, each List.AllTrue(List.Transform(Record.FieldValues(_), (fieldVal) => fieldVal <> null)))

    - just add a new column with the code after 'each' and change the '<> null' to '= null'.

     

    Having identified the null rows, you can play around with indices to split the data as required.