Wicked Smart Data
LearnInsightsAboutContact
Sign InLet's Build
LearnInsightsAboutContact
Sign InLet's Build
Wicked Smart Data

Intelligence, automation, and expert execution — plus an elite library of free knowledge. We turn complexity into competitive advantage.

Start a conversation

Platform

  • Learning Paths
  • Insights
  • RSS Feed

Company

  • About
  • Contact
  • Work With Us

Legal

  • Privacy Policy
  • Terms of Service

© 2026 Wicked Smart Data. All rights reserved.

Intelligence · Automation · Advantage

All Insights
Power Query

Unpivoting Cross-Tab and Matrix-Formatted Excel Reports in Power Query: Reshaping Wide Data into Analysis-Ready Tables

Cross-tab reports look great in Excel but break every analysis tool that touches them. Learn how to use Power Query's unpivot operations to reshape wide, matrix-formatted data into tidy, analysis-ready tables — including how to handle multi-row headers, merged cell hierarchies, and dynamic column counts.

⚡ Practitioner23 min readNov 9, 2026Updated Nov 9, 2026
Unpivoting Cross-Tab and Matrix-Formatted Excel Reports in Power Query: Reshaping Wide Data into Analysis-Ready Tables
On this page
  • Prerequisites
  • Why Cross-Tab Formats Exist (and Why They Break Analysis)
  • Understanding Your Source Data Before You Start
  • Scenario 1: The Simple Single-Header Cross-Tab
  • Loading and Inspecting
  • Applying Unpivot
  • Scenario 2: Multiple Identifier Columns with a Row Hierarchy
  • The Merged-Cell Hierarchy Problem
  • Scenario 3: Multi-Row Column Headers
  • Step-by-Step Multi-Row Header Resolution
  • Scenario 4: Mixed Cross-Tab with Embedded Totals
  • Scenario 5: Unpivoting Only Specific Columns
  • Building a Robust, Refresh-Ready Unpivot Pipeline
  • Parameterize the File Path
  • Stage Your Transformations
  • Handle Null Values After Unpivoting
  • Hands-On Exercise
  • Common Mistakes & Troubleshooting
  • "My column count changed on refresh and now the query errors"
  • "After unpivoting, my Attribute column has weird values like 'Column3', 'Column4'"
  • "Unpivoting creates way more rows than expected"
  • "My value column contains text like '12,400' instead of numbers"
  • "Fill Down is propagating values too far — it's filling past where the group ends"
  • Performance Considerations
  • The Inverse Problem: When You Need to Re-Pivot
  • Summary & Next Steps
  • Unpivoting Cross-Tab and Matrix-Formatted Excel Reports in Power Query: Reshaping Wide Data into Analysis-Ready Tables

    If you've spent any time working with real-world Excel files, you've met the enemy: a beautifully formatted cross-tab report where months run across the top, product categories cascade down the left, and the actual data lives in a grid of cells that no pivot table, DAX measure, or SQL join can touch without surgery. These reports look great in a printed board pack. They're analysis poison.

    The good news is that Power Query was practically built to solve this problem. Unpivoting — the process of collapsing wide column-based data into tall row-based data — is one of the most transformative operations you'll perform as a data practitioner. Master it, and you unlock an enormous class of Excel reports that were previously unusable. By the end of this lesson, you'll be able to handle simple single-header cross-tabs, multi-row header matrices, and partially structured reports where row labels are themselves nested — all without breaking a sweat when next month's file arrives.

    What you'll learn:

    • Why cross-tab structure breaks analysis and what "tidy" data looks like
    • How to use Unpivot Columns, Unpivot Other Columns, and Unpivot Only Selected Columns — and when to choose each
    • How to handle multi-row column headers by promoting, combining, and then unpivoting
    • How to deal with row hierarchies that require Fill Down before unpivoting
    • How to build a robust, parameterized unpivot pipeline that survives monthly file refreshes
    • Common failure modes and how to diagnose them

    Prerequisites

    This lesson assumes you're comfortable with the Power Query Editor interface, know how to connect to an Excel workbook, and understand the basic connect-transform-load workflow. You should know what promoting headers means and have a working grasp of how steps chain together in the Applied Steps pane. If you're newer to M or the query editor, Getting Started with Power Query will bring you up to speed.


    Why Cross-Tab Formats Exist (and Why They Break Analysis)

    Cross-tabulations are a natural way for humans to read summarized data. When a finance analyst sends you a spreadsheet with regions as row headers and months as column headers and revenue figures in every cell, they've made something easy to scan visually. Each cell sits at the intersection of two dimensions, and the eye moves across the grid intuitively.

    The problem is that this structure encodes two dimensions of information in the layout of the table rather than in the data itself. The month "January" isn't stored as a value in a column — it's implied by which column a number lives in. This breaks every standard data operation:

    • You can't filter to "just Q1" without selecting three columns manually
    • You can't sum revenue across all months by writing a simple aggregation
    • You can't join the table to a date dimension because there's no date column
    • Adding a new month means adding a new column, which silently breaks any downstream formula

    The solution is to reshape the data into what statisticians call tidy format: every variable in its own column, every observation in its own row. For a cross-tab report, that means turning the column headers (the months) into values in a "Month" column, and stacking all the revenue figures into a single "Revenue" column. This is exactly what unpivoting does.

    Key insight

    The fundamental rule of tidy data is that each column represents one variable and each row represents one observation. A cross-tab violates this by using column position to encode a variable's value. Unpivoting restores the rule.


    Understanding Your Source Data Before You Start

    Before you open Power Query, spend two minutes studying your source file. The answers to four questions determine which unpivot strategy you'll use:

    1. How many header rows are there? A single header row is the simplest case. Two or more header rows — where, say, the top row shows the quarter and the row below shows the month — require extra work before you can unpivot.

    2. Are the row labels in a single column or hierarchical across multiple columns? If product category, subcategory, and product name each live in their own column, you're in the simple case. If the category appears in one column and subcategory in a merged cell below it (a common Excel aesthetic choice), you'll need Fill Down first.

    3. Are there summary/total rows? Subtotals and grand totals embedded in the data look like regular rows to Power Query. You need to remove them before unpivoting or they'll corrupt your fact data.

    4. Does the number of columns change between refreshes? If new months are added to the right each period, hardcoding which columns to unpivot will break your pipeline. You'll need a dynamic approach using Unpivot Other Columns.

    Take a mental snapshot of these four characteristics before proceeding. The rest of this lesson walks through each scenario in increasing complexity.


    Scenario 1: The Simple Single-Header Cross-Tab

    Let's start with the most common case. You receive a monthly sales report from a regional sales manager. It looks like this in Excel:

    Product          | Jan-24  | Feb-24  | Mar-24  | Apr-24
    -----------------+---------+---------+---------+--------
    Widget A         | 12,400  | 11,900  | 14,200  | 13,800
    Widget B         |  8,750  |  9,100  |  8,400  |  9,650
    Gadget Pro       | 22,100  | 21,500  | 23,800  | 24,200
    Gadget Lite      | 15,300  | 14,900  | 16,100  | 15,700
    

    One header row, one identifier column, four value columns. This is as clean as cross-tabs get.

    Loading and Inspecting

    Connect to the workbook via Data > Get Data > From File > From Excel Workbook. Navigate to the correct sheet and click Transform Data to open the Power Query Editor. If you need a refresher on connecting to Excel files, the lesson on connecting to Excel workbooks and named ranges covers this thoroughly.

    After promoting headers (if Power Query hasn't already done so), your query table will show Product as a text column and Jan-24 through Apr-24 as separate columns.

    Applying Unpivot

    Select the Product column by clicking its header. Then in the Transform ribbon, click the dropdown arrow next to Unpivot Columns and choose Unpivot Other Columns.

    This is the critical choice. "Unpivot Other Columns" tells Power Query: "Whatever columns I've selected are identifier columns — keep them as they are. Take everything else and unpivot it." This is almost always the right choice for cross-tabs, because it means that when new month columns appear in next month's file, they'll automatically get unpivoted without any change to your query.

    After the step executes, your table transforms from 4 rows × 5 columns to 16 rows × 3 columns:

    Product     | Attribute | Value
    ------------+-----------+-------
    Widget A    | Jan-24    | 12400
    Widget A    | Feb-24    | 11900
    Widget A    | Mar-24    | 14200
    Widget A    | Apr-24    | 13800
    Widget B    | Jan-24    | 8750
    ...
    

    Power Query names the new columns "Attribute" and "Value" by default. Rename them to something meaningful — "Month" and "Revenue" — by double-clicking each header.

    Tip

    Always rename "Attribute" and "Value" immediately after unpivoting. These generic names have a way of surviving into your data model and confusing every person who opens the file six months later. Rename them in the same session while the context is fresh.

    Finally, change the data type of the Revenue column to Decimal Number or Whole Number (not Text), and if your month values are in a format Power Query can parse, consider converting them to proper dates using the date transformation techniques covered elsewhere in this learning path.

    The M code behind this entire operation is straightforward:

    let
        Source = Excel.Workbook(File.Contents("C:\Reports\Sales_Apr2024.xlsx"), null, true),
        Sheet1 = Source{[Item="SalesData",Kind="Sheet"]}[Data],
        PromotedHeaders = Table.PromoteHeaders(Sheet1, [PromoteAllScalars=true]),
        UnpivotedColumns = Table.UnpivotOtherColumns(
            PromotedHeaders, 
            {"Product"}, 
            "Month", 
            "Revenue"
        ),
        ChangedType = Table.TransformColumnTypes(
            UnpivotedColumns,
            {{"Revenue", type number}}
        )
    in
        ChangedType
    

    Notice how Table.UnpivotOtherColumns takes the table, a list of columns to keep as identifiers, and the names for the new Attribute and Value columns. This is the M function you'll use most often in unpivot scenarios.


    Scenario 2: Multiple Identifier Columns with a Row Hierarchy

    Real reports are rarely as clean as Scenario 1. More often, the row structure carries multiple dimensions. Consider this sales report with both Region and Product as row identifiers:

    Region    | Product     | Jan-24  | Feb-24  | Mar-24
    ----------+-------------+---------+---------+--------
    North     | Widget A    | 4,200   | 3,900   | 4,800
    North     | Widget B    | 2,100   | 2,400   | 2,200
    South     | Widget A    | 3,800   | 3,600   | 4,100
    South     | Widget B    | 2,900   | 3,100   | 2,800
    

    The fix here is identical to Scenario 1, except you select both Region and Product before clicking Unpivot Other Columns:

    UnpivotedColumns = Table.UnpivotOtherColumns(
        PromotedHeaders, 
        {"Region", "Product"}, 
        "Month", 
        "Revenue"
    )
    

    Both identifier columns are preserved in every row of the output. The result is 12 rows, each with Region, Product, Month, and Revenue.

    The Merged-Cell Hierarchy Problem

    Now for the common complication: the Excel file uses merged cells to show the hierarchy visually:

    Region    | Product     | Jan-24  | Feb-24  | Mar-24
    ----------+-------------+---------+---------+--------
    North     | Widget A    | 4,200   | 3,900   | 4,800
              | Widget B    | 2,100   | 2,400   | 2,200
    South     | Widget A    | 3,800   | 3,600   | 4,100
              | Widget B    | 2,900   | 3,100   | 2,800
    

    When Power Query reads this, the merged cells become nulls. The Region column will contain "North", null, "South", null instead of repeating the value. If you unpivot now, your output rows for Widget B will have null in the Region column, which breaks every join and filter downstream.

    The fix is Fill Down, applied before unpivoting. Select the Region column, then go to Transform > Fill > Down. Power Query propagates each non-null value downward until it hits the next non-null value. After Fill Down, the Region column correctly reads North, North, South, South.

    Warning

    Always apply Fill Down before removing rows or unpivoting. If you remove blank rows or filter the data first, you may lose the anchor values that Fill Down needs to propagate. Get the structure right before you start slicing.

    The lesson on reshaping data with transpose, fill down, and fill up covers Fill Down in detail if you need a deeper treatment.


    Scenario 3: Multi-Row Column Headers

    This is where unpivoting gets genuinely tricky. Many management reports use two or more header rows to organize the column dimension. A quarterly-then-monthly layout looks like this:

    Row 1:            |         Q1 2024         |         Q2 2024
    Row 2:  Product   | Jan-24 | Feb-24 | Mar-24 | Apr-24 | May-24 | Jun-24
    --------+----------+--------+--------+--------+--------+--------+--------
            Widget A  | 12,400 | 11,900 | 14,200 | 13,800 | 15,100 | 14,700
    

    Power Query sees this as a table where the first two rows are data rows (not headers), and the first column has no header. You need to merge these two header rows into a single meaningful column header before you can unpivot.

    Step-by-Step Multi-Row Header Resolution

    Step 1: Don't promote headers yet. When you load the data, let Power Query treat everything as data rows. The default Column1, Column2, Column3 names are fine for now.

    Step 2: Extract the first two rows. Use Table.ToRows to capture those header rows, or more practically, use the approach of converting them to lists and then combining them:

    let
        Source = Excel.Workbook(File.Contents("C:\Reports\Quarterly_Sales.xlsx"), null, true),
        Sheet1 = Source{[Item="QuarterlySales",Kind="Sheet"]}[Data],
        
        // Extract the two header rows as lists
        Row1 = Table.ToRows(Table.FirstN(Sheet1, 1)){0},
        Row2 = Table.ToRows(Table.FirstN(Sheet1, 2)){1},
        
        // Combine them: "Q1 2024 | Jan-24", "Q1 2024 | Feb-24", etc.
        // The first column is an identifier, leave it as-is
        CombinedHeaders = List.Transform(
            List.Positions(Row1),
            each if _ = 0 
                 then "Product"
                 else (if Row1{_} = null then "" else Text.From(Row1{_})) 
                      & " | " 
                      & Text.From(Row2{_})
        ),
        
        // Remove the two header rows from the data
        DataOnly = Table.Skip(Sheet1, 2),
        
        // Apply the combined headers
        RenamedTable = Table.RenameColumns(
            DataOnly, 
            List.Zip({Table.ColumnNames(DataOnly), CombinedHeaders})
        ),
        
        // Now unpivot
        Unpivoted = Table.UnpivotOtherColumns(
            RenamedTable, 
            {"Product"}, 
            "Quarter_Month", 
            "Revenue"
        )
    in
        Unpivoted
    

    After unpivoting, your "Quarter_Month" column contains values like "Q1 2024 | Jan-24". You can then split this column on the delimiter to create separate Quarter and Month columns, or just parse out the month if the quarter is redundant.

    Key insight

    The pattern for multi-row headers is always: (1) capture the header rows as lists before they're treated as data, (2) combine them into single meaningful strings, (3) remove the header rows from the data body, (4) rename the columns with your combined strings, (5) then unpivot. Trying to skip any of these steps creates hard-to-debug column name collisions.

    Step 3: Fill gaps in the top header row. Often the top header row uses merged cells, so "Q1 2024" appears once and then the next two cells are null. You need to fill those nulls before combining the headers. Convert Row1 to a table, Fill Down, then convert back to a list:

    // Fill the merged-cell gaps in Row1
    Row1Filled = List.RemoveNulls(
        Table.Column(
            Table.FillDown(
                Table.FromList(Row1, Splitter.SplitByNothing(), {"Val"}), 
                {"Val"}
            ), 
            "Val"
        )
    ),
    

    Actually, the cleaner approach here is to handle the top header row as a mini table and apply Table.FillDown to it before combining with Row2.


    Scenario 4: Mixed Cross-Tab with Embedded Totals

    Production reports almost always contain total rows — subtotals by region, grand totals at the bottom, running totals mid-table. These don't just add noise; they actively corrupt your analysis by double-counting values when you aggregate.

    Consider a report where every region block ends with a "Region Total" row:

    Region    | Product      | Jan-24 | Feb-24 | Mar-24
    ----------+--------------+--------+--------+--------
    North     | Widget A     | 4,200  | 3,900  | 4,800
    North     | Widget B     | 2,100  | 2,400  | 2,200
    North     | Region Total | 6,300  | 6,300  | 7,000
    South     | Widget A     | 3,800  | 3,600  | 4,100
    South     | Widget B     | 2,900  | 3,100  | 2,800
    South     | Region Total | 6,700  | 6,700  | 6,900
              | Grand Total  | 13,000 | 13,000 | 13,900
    

    Filter these out before applying Fill Down or Unpivot. In Power Query, filter the Product column to exclude values containing "Total":

    FilteredRows = Table.SelectRows(
        FilledDown,
        each not Text.Contains(Text.From([Product]), "Total")
    )
    

    Warning

    Be careful with filter logic like not Text.Contains([Product], "Total") — it will also remove any legitimate product that happens to have "Total" in its name (imagine a product called "Total Control Valve"). Build your filter to be as precise as possible, using exact matches where you can, or confirm with the data owner that no product names overlap with the summary row labels.

    You can also filter on null values in the data columns if the grand total row is identifiable that way, or add a step that removes the last N rows if the total is always at the bottom.


    Scenario 5: Unpivoting Only Specific Columns

    Sometimes you have a wide table where some columns should stay as columns (they're genuine variables) and only a subset should be unpivoted. Consider a customer analytics report:

    Customer_ID | Region | Segment | Jan_Spend | Feb_Spend | Mar_Spend | Lifetime_Value | Credit_Score
    

    Here, Lifetime_Value and Credit_Score are customer attributes — they shouldn't become rows. Only the monthly spend columns should be unpivoted. If you use "Unpivot Other Columns" with just Customer_ID, Region, and Segment as identifiers, you'd inadvertently unpivot Lifetime_Value and Credit_Score too.

    The right approach is to either:

    1. Select only the spend columns and choose Unpivot Columns (not "Other Columns"), or
    2. Select all identifier columns plus the non-time-series attribute columns and use "Unpivot Other Columns"

    Option 2 is more robust because it's driven by what you want to keep, not what you want to unpivot. If a new month column appears next refresh, it'll automatically get unpivoted. But if someone adds a new attribute column like "Churn_Risk_Score," it'll also automatically get unpivoted — which is wrong. In this case, you'll need a naming convention strategy: prefix all time-series columns with a consistent pattern and use a custom M step to identify columns dynamically.

    Here's how to unpivot all columns matching a pattern:

    let
        // Identify columns that are monthly spend (match pattern Mon_Spend)
        SpendColumns = List.Select(
            Table.ColumnNames(Source),
            each Text.EndsWith(_, "_Spend")
        ),
        
        // Everything else is an identifier
        IdentifierColumns = List.Difference(
            Table.ColumnNames(Source),
            SpendColumns
        ),
        
        Unpivoted = Table.UnpivotOtherColumns(
            Source,
            IdentifierColumns,
            "Month",
            "Spend"
        )
    in
        Unpivoted
    

    This pattern — dynamically computing identifier columns as the complement of your target columns — is production-grade. It handles both new month columns and new attribute columns correctly, as long as your naming convention holds.

    Tip

    Establish a column naming convention with whoever produces the source report. If all time-series columns end with _Spend, _Units, or _Budget, your unpivot logic can key off that pattern and become genuinely self-maintaining. This conversation is worth having before you build the pipeline.


    Building a Robust, Refresh-Ready Unpivot Pipeline

    A one-time unpivot is a party trick. A pipeline that handles monthly refreshes without breaking is a professional tool. Here's what that looks like in practice.

    Parameterize the File Path

    If the source file path changes (new folder, new server, new SharePoint location), hardcoding the path in your query is a maintenance burden. Use a parameter or a named range to store the path. The lesson on parameterized queries and dynamic data sources covers this in depth.

    Stage Your Transformations

    Don't put everything in one query. Break your pipeline into stages:

    1. Raw query: Loads the file with no transformations. This is your diagnostic checkpoint.
    2. Shaped query: Applies header promotion, Fill Down, total removal, and unpivoting.
    3. Typed query: Applies data types, renames columns to business-friendly names.

    This separation means that when something breaks, you can open the Raw query and see exactly what arrived from the source — without wading through twelve transformation steps. The lesson on multi-stage staging architectures describes this pattern in detail.

    Handle Null Values After Unpivoting

    After unpivoting, some rows may have null in the value column. This happens when a cell was blank in the original cross-tab. By default, Table.UnpivotOtherColumns drops null-value rows entirely. This is usually the right behavior — you don't want rows that say "Widget A, March, null revenue." But confirm this is your intent. If you need to preserve null rows (to track missing data explicitly), use Table.Unpivot with the MissingField.UseNull option or add the nulls back with a custom step.

    If you're combining multiple reports from a folder (a very common pattern), null handling becomes especially important. The lesson on combining files from a folder discusses how to apply transformation templates consistently across multiple files.


    Hands-On Exercise

    The scenario: You receive a quarterly budget vs. actual report from your finance team as an Excel file. The file has two header rows (the first row shows "Budget" or "Actual," the second shows the month), a "Department" column using merged cells for the department hierarchy, and a "Total" row at the bottom of each department block.

    Your task: Build a Power Query pipeline that produces a tidy output table with columns: Department, Cost_Center, Metric_Type (Budget or Actual), Month, Amount.

    Step 1: Load the file and examine the raw data in Power Query. Count the header rows and identify the merged cell pattern in the Department column.

    Step 2: Without promoting headers, extract the first two rows to build your combined column headers. For the "Department" and "Cost_Center" columns, use their actual names. For every value column, combine the metric type (Row 1) and month (Row 2) with a " | " separator.

    Step 3: Remove the two header rows from the data body and rename columns with your combined headers.

    Step 4: Fill Down the Department column to resolve the merged cell nulls.

    Step 5: Filter out rows where Cost_Center contains "Total" or is null.

    Step 6: Use Table.UnpivotOtherColumns with {"Department", "Cost_Center"} as identifiers, naming the output columns "Metric_Month" and "Amount."

    Step 7: Split the "Metric_Month" column on " | " to create separate "Metric_Type" and "Month" columns.

    Step 8: Set data types — Department and Cost_Center as Text, Metric_Type as Text, Month as Text (you'll convert to Date separately), Amount as Decimal Number.

    Verification: Your final table should have exactly (number of cost centers × number of months × 2 metrics) rows. If you have 8 cost centers, 6 months, and 2 metrics (Budget/Actual), you should have 96 rows. Count them. If you have more, you have total rows leaking through. If you have fewer, null values are being dropped that you expected to keep.


    Common Mistakes & Troubleshooting

    "My column count changed on refresh and now the query errors"

    This is the classic sign that you used Unpivot Columns (the hardcoded variant) instead of Unpivot Other Columns. When you use Unpivot Columns, Power Query records the specific column names to unpivot. When new columns appear, they aren't in the list and stay as columns — or worse, the step errors because expected columns are missing.

    Fix: Switch to Table.UnpivotOtherColumns and specify only your identifier columns. The function will capture whatever value columns exist at refresh time.

    "After unpivoting, my Attribute column has weird values like 'Column3', 'Column4'"

    You promoted headers when you shouldn't have, or the source data's first row isn't actually a header. Power Query assigned default column names (Column1, Column2, etc.) because the header row had nulls or the promotion step ran on data that wasn't ready.

    Fix: Don't promote headers until you've verified what the first row actually contains. Check the Raw query step first. If your source has multiple header rows, don't promote — handle the headers manually as described in Scenario 3.

    "Unpivoting creates way more rows than expected"

    Likely cause: total rows, blank rows, or repeated header rows embedded in the data. Cross-tab reports frequently re-print column headers partway through the data for printing purposes. These rows unpivot into garbage data like ("Total", "Jan-24", "Grand Total").

    Fix: Before unpivoting, filter out rows where the identifier column contains header-like values. A filter of Table.SelectRows(t, each [Department] <> "Department" and [Department] <> null) removes re-printed headers and blank rows in one step.

    Note

    When something unexpected happens after unpivoting, the best diagnostic strategy is to remove the Unpivot step temporarily and examine what the table looks like immediately before the step. Add a filter step to look at just the rows that are causing problems. Nine times out of ten, you'll spot a total row or repeated header row immediately.

    "My value column contains text like '12,400' instead of numbers"

    The source Excel file likely stored numbers as text (a formatting issue common in exported reports), or Power Query read the column as text before it understood the values were numeric.

    Fix: After unpivoting, use Transform > Data Type > Decimal Number to change the type. If that produces errors because of commas or currency symbols, clean the value column first: Text.Remove([Revenue], {",","$","£","€"}) before converting. The lesson on cleaning messy data with nulls, errors, and type conversions covers this pattern thoroughly.

    "Fill Down is propagating values too far — it's filling past where the group ends"

    This happens when you apply Fill Down to a column that has actual legitimate nulls mixed in with the merged-cell nulls. The function can't distinguish between "this null is a merged cell" and "this null is a genuinely missing value."

    Fix: If you have a reliable way to identify group boundaries (a subtotal row, a blank row, a row number pattern), filter or mark those boundaries before applying Fill Down. Alternatively, fill down and then verify that the results are correct by counting the rows per group and comparing to expectations.


    Performance Considerations

    Unpivoting is a relatively lightweight operation within Power Query — it's essentially a table restructuring that doesn't require sorting, grouping, or external data lookups. However, some surrounding operations deserve attention.

    If you're applying unpivot as part of a folder combine pattern where you're stacking together 24 monthly files, each with its own unpivot transformation, the total operation scales linearly with file count. This is usually fine for monthly batch reports, but if you're dealing with hundreds of files, check whether query folding is possible at the source or whether buffering intermediate results makes sense. The lesson on Power Query performance and folding has detailed guidance.

    The dynamic column detection pattern (using List.Select to find columns by name pattern) adds a small overhead because Power Query must retrieve the column names before it can execute the unpivot. In most real-world scenarios this is negligible, but be aware of it if you're chaining many such dynamic steps in a complex pipeline.


    The Inverse Problem: When You Need to Re-Pivot

    It's worth noting that unpivoting is reversible. After you've reshaped the data into tidy format for analysis, you may need to re-create a cross-tab layout for a presentation report. Power Query's Pivot Column operation (Transform > Pivot Column) does exactly this — it takes a column of values and spreads them into new columns. The lesson on generating cross-tabulated reports in Power Query covers that direction in detail.

    The professional pattern is: unpivot at the ingestion layer, pivot only at the presentation layer. Keep your analytical tables in tidy format throughout your data pipeline. Reshape for display only at the last step, and preferably in a separate query that references the tidy source rather than transforming the analytical table in place.


    Summary & Next Steps

    You've now covered the full spectrum of unpivot scenarios that appear in real Excel-based data pipelines:

    • Simple single-header cross-tabs using Table.UnpivotOtherColumns with explicit identifier columns
    • Row hierarchies with merged cells that need Fill Down before unpivoting
    • Multi-row column headers that require capturing, combining, and re-applying headers before the unpivot step can run
    • Embedded total rows that must be filtered before they corrupt your output
    • Dynamic column detection using naming conventions and List.Select to build refresh-safe pipelines

    The underlying mental model is consistent across all of them: identify what stays (your identifier columns), identify what transforms into rows (your value columns), clean everything that could interfere (totals, nulls, merged headers), and then execute the unpivot. Everything else is application of that model to whatever messy reality the source file presents.

    Where to go next:

    • Deepen your M language skills with Understanding the M Formula Language — the dynamic unpivot patterns in this lesson only scratch the surface of what's possible once you're comfortable writing M directly.
    • If your unpivoted data feeds into a data model with other tables, Combining Data from Multiple Sources with Append and Merge Queries shows how to join your newly tidy table to dimension tables for enrichment.
    • For advanced transformation techniques that complement unpivoting — including pivot, split, and merge — see Power Query Transformations: Split, Merge, Pivot, and Unpivot.
    • Once you've got the pipeline working, invest in Power Query Best Practices for Maintainable ETL to make sure the next person who touches your query (including future you) can understand and extend it without breaking things.

    Unpivoting is one of those skills that pays for itself immediately. The day you can open a cross-tab report from finance, reshape it in four steps, and have it feeding a live dashboard — while your colleagues are still copying and pasting — is a good day.

    Work With Us

    From insight to implementation

    Reading is the start. When you're ready to build the data, automation, or AI systems behind it, our team turns strategy into shipped results.

    Let's Build

    Power Query Essentials

    Previous

    Loading Data from CSV and Text Files in Power Query: Options, Delimiters, and Encoding Settings

    Related Insights

    Power QueryFoundation

    Closures and Higher-Order Functions in M: Passing, Returning, and Composing Functions as First-Class Values

    15 min
    Power QueryFoundation

    Loading Data from CSV and Text Files in Power Query: Options, Delimiters, and Encoding Settings

    19 min
    Power QueryExpert

    Implementing Custom Expression.Evaluate Pipelines in Power Query M: Dynamic Code Generation, Runtime Formula Injection, and Safe Sandboxed Execution Patterns

    28 min

    On this page

    • Prerequisites
    • Why Cross-Tab Formats Exist (and Why They Break Analysis)
    • Understanding Your Source Data Before You Start
    • Scenario 1: The Simple Single-Header Cross-Tab
    • Loading and Inspecting
    • Applying Unpivot
    • Scenario 2: Multiple Identifier Columns with a Row Hierarchy
    • The Merged-Cell Hierarchy Problem
    • Scenario 3: Multi-Row Column Headers
    • Step-by-Step Multi-Row Header Resolution
    • Scenario 4: Mixed Cross-Tab with Embedded Totals
    • Scenario 5: Unpivoting Only Specific Columns
    • Building a Robust, Refresh-Ready Unpivot Pipeline
    • Parameterize the File Path
    • Stage Your Transformations
    • Handle Null Values After Unpivoting
    • Hands-On Exercise
    • Common Mistakes & Troubleshooting
    • "My column count changed on refresh and now the query errors"
    • "After unpivoting, my Attribute column has weird values like 'Column3', 'Column4'"
    • "Unpivoting creates way more rows than expected"
    • "My value column contains text like '12,400' instead of numbers"
    • "Fill Down is propagating values too far — it's filling past where the group ends"
    • Performance Considerations
    • The Inverse Problem: When You Need to Re-Pivot
    • Summary & Next Steps