Concepts

Getting Started with M Code

What M code is, where to find it, and how to start reading and writing it — for Power BI users who have only ever used the UI.

Every time you click a button in the Power Query Editor — filter rows, add a column, change a type — Power Query generates M code behind the scenes. You may not have noticed, but that code is saved with your query and runs every time you refresh. M is the language underneath the UI.

This guide explains how to find that code, read it, and start modifying it directly.

Opening the Advanced Editor

In Power BI Desktop:

  • Open the Power Query Editor (Home → Transform Data)
  • Select any query in the Queries pane on the left
  • Click Home → Advanced Editor

You'll see the full M code for that query — every Applied Step listed as a named variable in a let block.

The Applied Steps pane on the right is just a visual representation of this same code. Each step in the pane corresponds to one line in the let block. Clicking a step in the pane highlights it in the code, and vice versa.

Reading a Generated Query

When you load a CSV and apply a few transformations, the Advanced Editor shows something like this:

let
    Source = Csv.Document(File.Contents("C:\data\sales.csv"), [Delimiter=","]),
    #"Promoted Headers" = Table.PromoteHeaders(Source),
    #"Filtered Rows" = Table.SelectRows(#"Promoted Headers", each [Region] = "East"),
    #"Removed Columns" = Table.RemoveColumns(#"Filtered Rows", {"Discount"})
in
    #"Removed Columns"

Reading top to bottom:

  • Source — load the CSV file from disk
  • #"Promoted Headers" — use the first row as column headers. The #"..." quoting syntax lets step names contain spaces — that's a Power Query convention, not required in hand-written code
  • #"Filtered Rows" — keep only rows where the Region column equals "East"
  • #"Removed Columns" — drop the Discount column
  • in #"Removed Columns" — return the last step as the query's output

Each step takes the output of the previous one as its input. The let...in structure is how every M query is organized: a set of named steps, followed by a declaration of which step to return.

Your First Edit

The most common first edit: change a hardcoded value. Instead of going back to the UI and regenerating a filter step, edit the M directly:

// Before — generated by the UI
#"Filtered Rows" = Table.SelectRows(#"Promoted Headers", each [Region] = "East")

// After — changed by hand
#"Filtered Rows" = Table.SelectRows(#"Promoted Headers", each [Region] = "West")

Click Done and the query refreshes with the new filter. That's your first M code change.

Debugging with Intermediate Steps

You can temporarily change the in clause to return any step — not just the last one:

let
    Source = Csv.Document(File.Contents("C:\data\sales.csv"), [Delimiter=","]),
    #"Promoted Headers" = Table.PromoteHeaders(Source),
    #"Filtered Rows" = Table.SelectRows(#"Promoted Headers", each [Region] = "East"),
    #"Removed Columns" = Table.RemoveColumns(#"Filtered Rows", {"Discount"})
in
    #"Promoted Headers"   // ← return this step to inspect it

The preview pane shows the table at that stage. This is the fastest way to isolate where a transformation goes wrong.

When the UI Isn't Enough

You'll reach the limits of the UI eventually. Common scenarios where writing M directly is the better path:

  • Dynamic filter values — filtering based on a value pulled from another table, rather than a hardcoded string
  • Complex conditional columns — the UI's Conditional Column dialog handles simple if/else cases; M handles nested logic, multiple conditions, and computed values
  • Iterating over a list — running the same transformation for each item in a list, then combining the results
  • Tweaking generated code — adjusting arguments that the UI doesn't expose, like changing a merge from a Left Outer join to an Inner join
  • Reusable logic — writing a custom function once and calling it across multiple queries

The next step is From the UI to M Code — a side-by-side translation guide for the ten most common UI operations.