Forum Discussion

piorsenpai's avatar
piorsenpai
Frequent Visitor
5 years ago
Solved

Split multiple row to multiple row by line break based on character conditions

Hello everyone,

 

I have a dataframe that looks as follows:

 
 

I want to split multiple row to multiple row by line break and first character each line.

 

Here is the result I want:

I have listed all the case that appear on table above.

 

Here is excel file for more convenient:

https://1drv.ms/x/s!AgaDgBBM4rAGli_UZM0WlmdiT7wj?e=L8WpTG

 

Thank you!

 

  • edhans's avatar
    edhans
    5 years ago

    Here you go. 

     

    let
        Source = Excel.Workbook(File.Contents("C:\Users\Ed Hansberry\OneDrive\Downloads\split_test.xlsx"), null, true),
        test_Sheet = Source{[Item="test",Kind="Sheet"]}[Data],
        #"Promoted Headers" = Table.PromoteHeaders(test_Sheet, [PromoteAllScalars=true]),
        #"Filtered Rows" = Table.SelectRows(#"Promoted Headers", each ([checklist] <> null)),
        #"Grouped Rows" = Table.Group(#"Filtered Rows", {"num", "checklist"}, {{"All Rows", each _, type table [num=number, checklist=text, sop=text, expected=text]}}),
        #"Split Column by Delimiter" = Table.ExpandListColumn(Table.TransformColumns(#"Grouped Rows", {{"checklist", Splitter.SplitTextByDelimiter("#(lf)", QuoteStyle.Csv), let itemType = (type nullable text) meta [Serialized.Text = true] in type {itemType}}}), "checklist"),
        #"Filtered Rows1" = Table.SelectRows(#"Split Column by Delimiter", each ([checklist] <> "")),
        #"Added First Column" = 
            Table.AddColumn(
                #"Filtered Rows1", 
                "First Column",
                each 
                    let
                        varGroupText = Text.Start([checklist], 1)
                    in
                    Text.Combine(
                        Table.SelectRows(
                            Table.FromList(
                                Text.Split([All Rows][sop]{0}, "#(lf)"),
                                Splitter.SplitByNothing()
                            ),
                            each Text.Start([Column1],1) = varGroupText
                        )[Column1],
                    "#(lf)"
                    )
                ),
        #"Added Second Column" = 
            Table.AddColumn(
                #"Added First Column", 
                "Second Column",
                each 
                    let
                        varGroupText = Text.Start([checklist], 1)
                    in
                    Text.Combine(
                        Table.SelectRows(
                            Table.FromList(
                                Text.Split([All Rows][expected]{0}, "#(lf)"),
                                Splitter.SplitByNothing()
                            ),
                            each Text.Start([Column1],1) = varGroupText
                        )[Column1],
                    "#(lf)"
                    )
                ),
        #"Removed Other Columns" = Table.SelectColumns(#"Added Second Column",{"num", "checklist", "First Column", "Second Column"})
    in
        #"Removed Other Columns"

     

    Again, change the source to your file. THe key was adding 

    Splitter.SplitByNothing()

    to the Table.FromList functions in each column. 

     

    Apparently the unusual ASCII characters was causing Power Query to split more than you wanted, so this forces no splitting within a Table.FromList. If ImkeF knows more I'd love her wisdom on this usage.

    You need to be 100% sure nothing is being dropped. I cannot read that language so it isn't efficient for me to do character comparisons.

     

13 Replies

  • ImkeF's avatar
    ImkeF
    Community Champion

    Hey edhans ,

    ha, ha, that's pretty mean.
    Unfortunately I also don't have any idea what the undocumented default-splitter function is. 
    Also have no idea why someone considered it not to be Splitter.SplitByNothing 😉

  • piorsenpai's avatar
    piorsenpai
    Frequent Visitor

    Hello everyone,

     

    I have a dataframe that looks as follows:

     

    numchecklistsopexpected
    1

    A. (text)

    B. (text)

    C. (text)

    D. (text)

    A. (text)

    B. (text)

    C. (text)

    D. (text)

    A. (text)

    B. (text)

    C. (text)

    D. (text)

    2

    A. (text)

    B. (text)

    C. (text)

    A 1. (text)

    A 2. (text)

    B 1. (text)

    B 2. (text)

    C. (text)

    A 1. (text)

    A 2. (text)

    B 1-1. (text)

    B 1-2. (text)

    B 2. (test)

    C 1. (text)

    C 2. (text)

    3

    A. (text)

    B. (text)

    C. (text)

    A. (text)

    B 1. (text)

    B 2. (text)

    C. (text)

    A. (text)

    C. (text)

     

     

    I want to split multiple row to multiple row by line break and first character each line.

    Here is the result I want:

    numchecklistsopexpected
    1A. (text)A. (text)A. (text)
    1B. (text)B. (text)B. (text)
    1C. (text)C. (text)C. (text)
    1D. (text)D. (text)D. (text)
    2A. (text)

    A 1. (text)

    A 2. (text)

    A 1. (text)

    A 2. (text)

    2B. (text)

    B 1. (text)

    B 2. (text)

    B 1-1. (text)

    B 1-2. (text)

    B 2. (test)

    2C. (text)C. (text)

    C 1. (text)

    C 2. (text)

    3A. (text)A. (text)A. (text)
    3B. (text)

    B 1. (text)

    B 2. (text)

     

    3C. (text)C. (text)C. (text)

     

    Here is excel file for more convenient:

    https://1drv.ms/x/s!AgaDgBBM4rAGli_UZM0WlmdiT7wj?e=L8WpTG

     

    I have listed all the case that appear on table above.

     

    Thank you!

    • edhans's avatar
      edhans
      Community Champion

      I cannot tell what you are wanting based on what you have posted piorsenpai - that is just a lot of text that when I paste it into Excel or a text editor, it is one long string. 

       

      But if you want to break based on line feeds, you can use the Split Column feature and use special characters.

      It turns this:

      into this:

      If you need more help, I think you are going to have to share an Excel file via OneDrive or Dropbox with real sample data. Pasting text into the forum will destroy any of the special characters you are trying to parse. That includes your expected results. It looks a bit jumbled to me based on what the forum did with it.

       

       

       

      • piorsenpai's avatar
        piorsenpai
        Frequent Visitor

        Sorry for that inconvenient,

         

        Here is excel file which I added Data sample and Result that I want in 2 sheets:

        https://1drv.ms/x/s!AgaDgBBM4rAGli_UZM0WlmdiT7wj?e=rG2tqQ

         

        If possible, I hope I can have a method for multiple row like that not just 3 rows in file excel sample because the file which I am working on have thousands of row like that.

  • edhans's avatar
    edhans
    Community Champion

    See this code piorsenpai 

     

    let
        Source = Excel.Workbook(File.Contents("C:\Users\Ed Hansberry\OneDrive\Downloads\test.xlsx"), null, true),
        Data_Sheet = Source{[Item="Data",Kind="Sheet"]}[Data],
        #"Promoted Headers" = Table.PromoteHeaders(Data_Sheet, [PromoteAllScalars=true]),
        #"Filtered Rows" = Table.SelectRows(#"Promoted Headers", each ([checklist] <> null)),
        #"Grouped Rows" = Table.Group(#"Filtered Rows", {"num", "checklist"}, {{"All Rows", each _, type table [num=number, checklist=text, sop=text, expected=text]}}),
        #"Split Column by Delimiter" = Table.ExpandListColumn(Table.TransformColumns(#"Grouped Rows", {{"checklist", Splitter.SplitTextByDelimiter("#(lf)", QuoteStyle.Csv), let itemType = (type nullable text) meta [Serialized.Text = true] in type {itemType}}}), "checklist"),
        #"Filtered Rows1" = Table.SelectRows(#"Split Column by Delimiter", each ([checklist] <> "")),
        #"Added First Column" = 
            Table.AddColumn(
                #"Filtered Rows1", 
                "First Column",
                each 
                    let
                        varGroupText = Text.Start([checklist], 1)
                    in
                    Text.Combine(
                        Table.SelectRows(
                            Table.FromList(
                                Text.Split([All Rows][sop]{0}, "#(lf)")
                            ),
                            each Text.Start([Column1],1) = varGroupText
                        )[Column1],
                    "#(lf)"
                    )
                ),
        #"Added Second Column" = 
            Table.AddColumn(
                #"Added First Column", 
                "Second Column",
                each 
                    let
                        varGroupText = Text.Start([checklist], 1)
                    in
                    Text.Combine(
                        Table.SelectRows(
                            Table.FromList(
                                Text.Split([All Rows][expected]{0}, "#(lf)")
                            ),
                            each Text.Start([Column1],1) = varGroupText
                        )[Column1],
                    "#(lf)"
                    )
                ),
        #"Removed Other Columns" = Table.SelectColumns(#"Added Second Column",{"num", "checklist", "First Column", "Second Column"})
    in
        #"Removed Other Columns"

     

    It turns this after I filtered out some blank/empty rows in the Excel file:

    into this:

     

    You will need to change the "Source" line to be your folder path to the test.xlsx file.

     

    • piorsenpai's avatar
      piorsenpai
      Frequent Visitor

      It worked on the test.xlsx file. However, when I start working on real data some rows still can work but some is not and occur an error

      DataFormat.Error: There were more columns in the result than expected.
      Details:
      Count=1

      • edhans's avatar
        edhans
        Community Champion

        I would have to see the data. There is nothing in my code that is expecting a specific number of columns. Change the "Second Column" code in the advanced editor this and show me what is in one of the lists that is currently returning an error. Row 10 for example, and we can work from there.

            #"Added Second Column" = 
                Table.AddColumn(
                    #"Added First Column", 
                    "Second Column",
                    each 
                        let
                            varGroupText = Text.Start([checklist], 1)
                        in
                        Table.SelectRows(
                            Table.FromList(
                                Text.Split([All Rows][expected]{0}, "#(lf)")
                            ),
                            each Text.Start([Column1],1) = varGroupText
                        )[Column1]
                ),