Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

The Power BI Data Visualization World Championships is back! Get ahead of the game and start preparing now! Learn more

Reply
QZ
Helper I
Helper I

(M code)How to unpivot sepcial columns from independent Excel file which in a folder then summary it

There have many many Excel files(same structure) in a folder, I would like extract special columns(not fixed) in ervery Excel file, then unpivot the data base on the specail columns, and finally summarize the unpivot data to a summary file.
If user input the value(refer blue circle) in the "stage" column, it also must input "Category" and "Pattern"(refer red circle):

QZ_0-1757920404431.png

If user input none in the "stage" column(refer blue circle), the "Category" and "Pattern" also is none(refer red circle):

QZ_1-1757920553011.png

The source file:  INPUT
Finally I want to get summary file:  OUTPUT
How can I get the final Output file by M code? Much appreciated if you have any idea about the case!

2 ACCEPTED SOLUTIONS
DataNinja777
Super User
Super User

Hi @QZ ,

 

You can accomplish this by creating a Power Query function to process each Excel file and then applying that function across all files located in a specific folder. The process involves handling the unique two-row header structure and extracting the "Category" and "Pattern" metadata from each file before unpivoting the data into a summarized format.

 

Here is the complete M code to achieve this. You can paste this solution directly into the Advanced Editor of a blank query in either Excel or Power BI.

let
    // 1. Point to the folder containing your Excel files
    Source = Folder.Files("C:\YOUR\FOLDER\PATH"),

    // 2. Filter for Excel files only (optional but recommended)
    FilterExcelFiles = Table.SelectRows(Source, each Text.EndsWith([Name], ".xlsx") or Text.EndsWith([Name], ".xls")),

    // 3. Define the function to transform each file
    TransformFile = (binaryContent as binary) =>
    let
        // Load the workbook and navigate to the first sheet
        Source = Excel.Workbook(binaryContent, null, true),
        Sheet1 = Source{[Item="Sheet1",Kind="Sheet"]}[Data],

        // Extract Category and Pattern from their specific cells
        // Note: {4} is row 5, {Column9} is column I; {Column15} is column O. Adjust if your layout is different.
        CategoryValue = try Sheet1{4}[Column9] otherwise null,
        PatternValue = try Sheet1{4}[Column15] otherwise null,

        // Prepare the main data table (skip top rows to get to the headers)
        DataTable = Table.Skip(Sheet1, 6),

        // Handle the two-level headers by transposing, filling, merging, and transposing back
        Transposed = Table.Transpose(DataTable),
        FilledDown = Table.FillDown(Transposed, {"Column1"}),
        MergedHeaders = Table.CombineColumns(Table.TransformColumnTypes(FilledDown, {{"Column2", type text}}, "en-US"),{"Column1", "Column2"},Combiner.CombineTextByDelimiter(" ", QuoteStyle.None),"MergedHeaders"),
        TransposedBack = Table.Transpose(MergedHeaders),
        
        // Promote the newly created first row to be the headers
        PromotedHeaders = Table.PromoteHeaders(TransposedBack, [PromoteAllScalars=true]),

        // Unpivot the stage columns, keeping the identifier columns
        UnpivotedData = Table.UnpivotOtherColumns(PromotedHeaders, {"Checker", "Machine no.", "S/C", "FB"}, "Stage", "Value"),
        
        // Filter out any rows where the value is null (i.e., no data was entered)
        FilteredRows = Table.SelectRows(UnpivotedData, each [Value] <> null),

        // Add the extracted Category and Pattern as new columns
        AddCategory = Table.AddColumn(FilteredRows, "Category", each CategoryValue),
        AddPattern = Table.AddColumn(AddCategory, "Pattern", each PatternValue)

    in
        AddPattern,

    // 4. Invoke the custom function on each file's content
    InvokeCustomFunction = Table.AddColumn(FilterExcelFiles, "Transform File", each TransformFile([Content])),

    // 5. Remove other columns, keeping only the transformed data
    RemoveOtherColumns = Table.SelectColumns(InvokeCustomFunction, {"Transform File"}),

    // 6. Expand the table column to get the final result
    ExpandedData = Table.ExpandTableColumn(RemoveOtherColumns, "Transform File", {"Checker", "Machine no.", "S/C", "FB", "Stage", "Value", "Category", "Pattern"}),

    // 7. Reorder columns to match the desired output
    ReorderedColumns = Table.ReorderColumns(ExpandedData,{"Checker", "Machine no.", "S/C", "FB", "Category", "Pattern", "Stage", "Value"}),

    // 8. Set the correct data types for the final columns
    ChangedType = Table.TransformColumnTypes(ReorderedColumns,{{"Checker", type text}, {"Machine no.", type text}, {"S/C", type text}, {"FB", Int64.type}, {"Category", type text}, {"Pattern", type text}, {"Stage", type text}, {"Value", Int64.type}})

in
    ChangedType

To use this code, first open Power Query by getting data from a folder (Data > Get Data > From File > From Folder in Excel). Point it to the folder containing your source files and click Transform Data. In the Power Query Editor, open the Advanced Editor from the Home tab. Delete any existing text and paste in the M code provided. The most important step is to update the folder path on the third line of the code to match your folder's location. After pasting and updating the path, click Done, and Power Query will process all the files and display the final summary table.

 

The code works by first using the Folder.Files function to get a list of all files. The core logic is contained within a custom function named TransformFile, which is designed to process one file at a time. Inside this function, it extracts the Category and Pattern values from their specific cell locations. It then cleverly handles the two-level column headers by transposing the table, filling down the stage names, merging the header rows into one, and transposing back. Following this, the Table.UnpivotOtherColumns function converts the wide stage columns into a long format. Finally, the extracted Category and Pattern are added as new columns to the resulting data. The main query then applies this function to every file, combines the results into a single table, and performs final cleanup like reordering columns and setting data types.

 

Best regards,

View solution in original post

Great, your reply is very helpful for me, I'm researching the code, I'll paste the code once accomplish it.

View solution in original post

7 REPLIES 7
QZ
Helper I
Helper I

@DataNinja777 thank u very much! 🤝 Your answer is great, after made a small change to the code, it run smoothly.

let
    Source = Folder.Files("C:\Users\your name\Desktop\Input"),
    FilterExcelFiles = Table.SelectRows(Source, each Text.EndsWith([Name], ".xlsx") or Text.EndsWith([Name], ".xls")),
    
    // 3. Define the function to transform each file
    TransformFile = (binaryContent as binary) =>
    let
        // Load the workbook and navigate to the first sheet
        Source = Excel.Workbook(binaryContent, null, true),
        Sheet1 = Source{[Item="Sheet1",Kind="Sheet"]}[Data],

        Removed Top Rows = Table.Skip(Sheet1,1),
        Removed Speical Rows = Table.RemoveRows(Removed Top Rows,1,1),
        Removed Columns1 = Table.RemoveColumns(Removed Speical Rows,{"Column3", "Column50", "Column51", "Column52"}),
        Custom define5 = Record.FieldValues(Removed Columns1{0}),
        Custom define6 = List.Transform(Custom define5, each if _ = null then "" else _),
        Custom define7 = List.Transform(Custom define6, each Text.Combine(List.FirstN(List.Alternate(Text.SplitAny(_ ,"()"), 1, 1),2))),
        Custom define12 = List.Transform(Custom define7, each if _ <> "" then _ else null),
        Custom define8 = Table.ColumnNames(Removed Columns1),
        Custom define9 = List.Transform(Custom define8, each _ & " ="),
        Custom define10 = List.Zip({Custom define9,Custom define12}),
        Custom define11 = List.Transform(Custom define10, each Text.Combine(_," ")),
        Custom define13 = List.Transform(Custom define11, each _ & ","),
        Custom define14 = Record.FromList(Custom define12,Custom define8),
        Custom define16 = Table.InsertRows(Removed Columns1,1,{Custom define14}),
        DataTable = Table.Skip(Custom define16, 1),
        Transposed = Table.Transpose(DataTable),
        FilledDown = Table.FillDown(Transposed, {"Column1"}),
        MergedHeaders = Table.CombineColumns(Table.TransformColumnTypes(FilledDown, {{"Column2", type text}}, "en-US"),{"Column1", "Column2"},Combiner.CombineTextByDelimiter("", QuoteStyle.None),"MergedHeaders"),
        TransposedBack = Table.Transpose(MergedHeaders),
        PromotedHeaders = Table.PromoteHeaders(TransposedBack, [PromoteAllScalars=true]),
        UnpivotedData = Table.UnpivotOtherColumns(PromotedHeaders, {"Checker", "Machine no.", "FB"}, "Stage", "Value"),
        Split Column by Delimiter = Table.SplitColumn(UnpivotedData, "Stage", Splitter.SplitTextByDelimiter("=", QuoteStyle.Csv), {"Stage.1", "Stage.2"}),
        Removed Columns = Table.RemoveColumns(Split Column by Delimiter,{"Stage.2"}),
        Custom define1 = Table.TransformColumns(Removed Columns, {{"Stage.1", each Text.RemoveRange(_, Text.Length(_) - 1, 1)}}),
        Renamed Columns = Table.RenameColumns(Custom define1,{{"Stage.1", "Stage"}})
    in
        Renamed Columns,

    // 4. Invoke the custom function on each file's content
    InvokeCustomFunction = Table.AddColumn(FilterExcelFiles, "Transform File", each TransformFile([Content])),

    // 5. Remove other columns, keeping only the transformed data
    RemoveOtherColumns = Table.SelectColumns(InvokeCustomFunction, {"Transform File"}),

    // 6. Expand the table column to get the final result
    ExpandedData = Table.ExpandTableColumn(RemoveOtherColumns, "Transform File", {"Checker", "Machine no.", "FB", "Stage", "Value"}),

    // 7. Reorder columns to match the desired output
    ReorderedColumns = Table.ReorderColumns(ExpandedData,{"Checker", "Machine no.", "FB", "Stage", "Value"}),
    ChangedType = Table.TransformColumnTypes(ReorderedColumns,{{"Checker", type text}, {"Machine no.", type text}, {"FB", type text}, {"Stage", type text}, {"Value", Int64.Type}})
in
    ChangedType
v-saisrao-msft
Community Support
Community Support

Hi @QZ,

We haven’t heard back from you in a while regarding your issue. let us know if your issue has been resolved or if you still require support.

 

Thank you.

v-saisrao-msft
Community Support
Community Support

Hi @QZ,

Checking in to see if your issue has been resolved. let us know if you still need any assistance.

 

Thank you.

Omid_Motamedise
Super User
Super User

Hi

See the following video of mine

It will help you

 

 

https://www.bing.com/ck/a?!&&p=e6690fab622609437b4ad6aa69bae3514209a5eaae94d9bcb2889e078c73a533Jmltd...

 

 


If my answer helped solve your issue, please consider marking it as the accepted solution.
v-saisrao-msft
Community Support
Community Support

Hi @QZ,

Have you had a chance to review the solution we shared by @DataNinja777 ? If the issue persists, feel free to reply so we can help further.

 

Thank you.

DataNinja777
Super User
Super User

Hi @QZ ,

 

You can accomplish this by creating a Power Query function to process each Excel file and then applying that function across all files located in a specific folder. The process involves handling the unique two-row header structure and extracting the "Category" and "Pattern" metadata from each file before unpivoting the data into a summarized format.

 

Here is the complete M code to achieve this. You can paste this solution directly into the Advanced Editor of a blank query in either Excel or Power BI.

let
    // 1. Point to the folder containing your Excel files
    Source = Folder.Files("C:\YOUR\FOLDER\PATH"),

    // 2. Filter for Excel files only (optional but recommended)
    FilterExcelFiles = Table.SelectRows(Source, each Text.EndsWith([Name], ".xlsx") or Text.EndsWith([Name], ".xls")),

    // 3. Define the function to transform each file
    TransformFile = (binaryContent as binary) =>
    let
        // Load the workbook and navigate to the first sheet
        Source = Excel.Workbook(binaryContent, null, true),
        Sheet1 = Source{[Item="Sheet1",Kind="Sheet"]}[Data],

        // Extract Category and Pattern from their specific cells
        // Note: {4} is row 5, {Column9} is column I; {Column15} is column O. Adjust if your layout is different.
        CategoryValue = try Sheet1{4}[Column9] otherwise null,
        PatternValue = try Sheet1{4}[Column15] otherwise null,

        // Prepare the main data table (skip top rows to get to the headers)
        DataTable = Table.Skip(Sheet1, 6),

        // Handle the two-level headers by transposing, filling, merging, and transposing back
        Transposed = Table.Transpose(DataTable),
        FilledDown = Table.FillDown(Transposed, {"Column1"}),
        MergedHeaders = Table.CombineColumns(Table.TransformColumnTypes(FilledDown, {{"Column2", type text}}, "en-US"),{"Column1", "Column2"},Combiner.CombineTextByDelimiter(" ", QuoteStyle.None),"MergedHeaders"),
        TransposedBack = Table.Transpose(MergedHeaders),
        
        // Promote the newly created first row to be the headers
        PromotedHeaders = Table.PromoteHeaders(TransposedBack, [PromoteAllScalars=true]),

        // Unpivot the stage columns, keeping the identifier columns
        UnpivotedData = Table.UnpivotOtherColumns(PromotedHeaders, {"Checker", "Machine no.", "S/C", "FB"}, "Stage", "Value"),
        
        // Filter out any rows where the value is null (i.e., no data was entered)
        FilteredRows = Table.SelectRows(UnpivotedData, each [Value] <> null),

        // Add the extracted Category and Pattern as new columns
        AddCategory = Table.AddColumn(FilteredRows, "Category", each CategoryValue),
        AddPattern = Table.AddColumn(AddCategory, "Pattern", each PatternValue)

    in
        AddPattern,

    // 4. Invoke the custom function on each file's content
    InvokeCustomFunction = Table.AddColumn(FilterExcelFiles, "Transform File", each TransformFile([Content])),

    // 5. Remove other columns, keeping only the transformed data
    RemoveOtherColumns = Table.SelectColumns(InvokeCustomFunction, {"Transform File"}),

    // 6. Expand the table column to get the final result
    ExpandedData = Table.ExpandTableColumn(RemoveOtherColumns, "Transform File", {"Checker", "Machine no.", "S/C", "FB", "Stage", "Value", "Category", "Pattern"}),

    // 7. Reorder columns to match the desired output
    ReorderedColumns = Table.ReorderColumns(ExpandedData,{"Checker", "Machine no.", "S/C", "FB", "Category", "Pattern", "Stage", "Value"}),

    // 8. Set the correct data types for the final columns
    ChangedType = Table.TransformColumnTypes(ReorderedColumns,{{"Checker", type text}, {"Machine no.", type text}, {"S/C", type text}, {"FB", Int64.type}, {"Category", type text}, {"Pattern", type text}, {"Stage", type text}, {"Value", Int64.type}})

in
    ChangedType

To use this code, first open Power Query by getting data from a folder (Data > Get Data > From File > From Folder in Excel). Point it to the folder containing your source files and click Transform Data. In the Power Query Editor, open the Advanced Editor from the Home tab. Delete any existing text and paste in the M code provided. The most important step is to update the folder path on the third line of the code to match your folder's location. After pasting and updating the path, click Done, and Power Query will process all the files and display the final summary table.

 

The code works by first using the Folder.Files function to get a list of all files. The core logic is contained within a custom function named TransformFile, which is designed to process one file at a time. Inside this function, it extracts the Category and Pattern values from their specific cell locations. It then cleverly handles the two-level column headers by transposing the table, filling down the stage names, merging the header rows into one, and transposing back. Following this, the Table.UnpivotOtherColumns function converts the wide stage columns into a long format. Finally, the extracted Category and Pattern are added as new columns to the resulting data. The main query then applies this function to every file, combines the results into a single table, and performs final cleanup like reordering columns and setting data types.

 

Best regards,

Great, your reply is very helpful for me, I'm researching the code, I'll paste the code once accomplish it.

Helpful resources

Announcements
Power BI DataViz World Championships

Power BI Dataviz World Championships

The Power BI Data Visualization World Championships is back! Get ahead of the game and start preparing now!

December 2025 Power BI Update Carousel

Power BI Monthly Update - December 2025

Check out the December 2025 Power BI Holiday Recap!

FabCon Atlanta 2026 carousel

FabCon Atlanta 2026

Join us at FabCon Atlanta, March 16-20, for the ultimate Fabric, Power BI, AI and SQL community-led event. Save $200 with code FABCOMM.