Power Query M Cheat Sheet Guide
Quick reference for Power Query M — the functional language behind Power BI and Excel data transformations. Covers values, operators, text, numbers, dates, lists, records, and tables.
📋 Quick reference: Power Query M Cheat Sheet — use this alongside the guide for fast syntax lookup while you read.
Core Concepts
Power Query
Power Query is the data transformation engine built into Power BI, Excel, and Microsoft Fabric. It lets you connect to data sources, clean and reshape data, and load it into a model — without writing SQL or Python. Every transformation you apply in the Power Query Editor generates M code behind the scenes.
Power Query M
M (officially "Power Query Formula Language") is the functional language that powers every transformation in Power Query. It is case-sensitive, expression-based, and lazy — steps are only evaluated when needed. You write M directly in the Advanced Editor or it is generated automatically by the UI.
Expression
Everything in M is an expression that evaluates to a value. A value can be a number, text, a list, a record, or a table. There are no statements or loops in the traditional sense — just expressions that produce values.
// A simple expression
1 + 1 // evaluates to 2
// A text expression
"Hello" & " " & "World" // evaluates to "Hello World"Query (let...in)
A query is a let...in expression. let defines named steps. in specifies which step is the final output.
let
Source = Csv.Document(File.Contents("C:\data\sales.csv")),
Promoted = Table.PromoteHeaders(Source),
TypedCols = Table.TransformColumnTypes(Promoted, {
{"Date", type date},
{"Amount", type number}
}),
Filtered = Table.SelectRows(TypedCols, each [Amount] > 0)
in
FilteredComments
M supports single-line and multi-line comments.
// This is a single-line comment
/* This is a
multi-line comment */Creating Values
Number
Integer and decimal number literals.
42 // integer
3.14 // decimal
-100 // negative
1.5e3 // scientific notation = 1500Text
Text values are enclosed in double quotes. Use #(lf) for a line feed, #(tab) for a tab.
"Hello World"
"Line 1#(lf)Line 2" // newline inside text
"Tab#(tab)separated"Logical
Boolean values — always lowercase in M.
true
falseNull
Represents the absence of a value.
nullDate
Date literals use the #date constructor.
#date(2024, 6, 15) // June 15, 2024Datetime
Datetime literals use the #datetime constructor.
#datetime(2024, 6, 15, 9, 30, 0) // June 15 2024 09:30:00Duration
Duration literals use the #duration constructor — days, hours, minutes, seconds.
#duration(1, 2, 30, 0) // 1 day, 2 hours, 30 minutes
#duration(0, 0, 0, 45) // 45 secondsList
An ordered collection of values, enclosed in curly braces.
{1, 2, 3, 4, 5}
{"apple", "banana", "cherry"}
{1, "mixed", true, null} // lists can hold mixed types
{1..10} // range shorthand: 1 to 10Record
A set of named fields enclosed in square brackets. Like a row or a JSON object.
[Name = "Alex", Age = 30, Active = true]Table
A structured collection of rows and columns. Usually produced by a data source function or a Table.From* function.
#table(
{"Name", "Sales"},
{
{"North", 42000},
{"South", 38000},
{"East", 51000}
}
)Variables & Queries
let...in
The foundation of every M query. Each step in let is a named variable referencing the previous step.
let
RawData = Excel.Workbook(File.Contents("C:\sales.xlsx"), true),
SalesSheet = RawData{[Item="Sales", Kind="Sheet"]}[Data],
Promoted = Table.PromoteHeaders(SalesSheet),
Cleaned = Table.SelectRows(Promoted, each [Region] <> null)
in
CleanedNaming conventions
Step names can contain spaces if wrapped in #"...". Descriptive names make queries readable.
let
#"Raw Source" = Csv.Document(...),
#"Promoted Headers" = Table.PromoteHeaders(#"Raw Source"),
#"Removed Nulls" = Table.SelectRows(#"Promoted Headers", each [ID] <> null)
in
#"Removed Nulls"Step reference
Each step is just a variable. You reference a previous step by name to build on it.
let
Source = ...,
Step2 = Table.PromoteHeaders(Source), // references Source
Step3 = Table.SelectRows(Step2, ...) // references Step2
in
Step3Operators
Arithmetic
Standard math operators.
5 + 3 // 8
10 - 4 // 6
6 * 7 // 42
15 / 4 // 3.75Comparison
Return true or false. M comparisons are type-sensitive.
5 > 3 // true
5 < 3 // false
5 = 5 // true (single = for equality)
5 <> 3 // true (not equal)
5 >= 5 // true
5 <= 4 // falseLogical
Combine boolean expressions.
true and false // false
true or false // true
not true // falseText concatenation &
Join two text values with &.
"Hello" & " " & "World" // "Hello World"
"FY" & Text.From(2024) // "FY2024"List concatenation &
Combine two lists with &.
{1, 2, 3} & {4, 5, 6} // {1, 2, 3, 4, 5, 6}
{"a", "b"} & {"c"} // {"a", "b", "c"}is / as (type)
is tests whether a value is of a type. as asserts a type (errors if wrong).
42 is number // true
"hello" is text // true
42 is text // false
42 as number // 42
"hello" as number // error? (optional)
Append ? to a type to allow null values without error.
42 as number? // 42
null as number? // null (no error)Text Functions
Text.Length
Return the number of characters in a text value.
Text.Length("Hello") // 5
Text.Length([ProductCode]) // length of each codeText.Upper / Lower / Proper
Convert text to uppercase, lowercase, or title case.
Text.Upper("hello world") // "HELLO WORLD"
Text.Lower("HELLO WORLD") // "hello world"
Text.Proper("hello world") // "Hello World"Text.Start / End
Extract N characters from the start or end of a string.
Text.Start("SKU-001-A", 3) // "SKU"
Text.End("SKU-001-A", 1) // "A"Text.Middle
Extract a substring by start position and length (zero-indexed).
// Text.Middle(text, start, count)
Text.Middle("SKU-001-A", 4, 3) // "001"Text.Range
Extract a substring by start position and optional length (zero-indexed).
Text.Range("Hello World", 6) // "World"
Text.Range("Hello World", 0, 5) // "Hello"Text.Split
Split a text string into a list using a delimiter.
Text.Split("North,South,East", ",") // {"North", "South", "East"}
Text.Split("2024-06-15", "-") // {"2024", "06", "15"}Text.Combine
Join a list of text values into a single string with an optional separator.
Text.Combine({"North", "South", "East"}, ", ") // "North, South, East"
Text.Combine({"2024", "06", "15"}, "-") // "2024-06-15"Text.Replace
Replace all occurrences of a substring with another.
Text.Replace("Hello World", "World", "M Code") // "Hello M Code"
Text.Replace([Phone], "-", "") // remove dashesText.Contains
Return true if a text value contains a substring.
Text.Contains("Power BI Desktop", "BI") // true
Text.Contains("Power BI Desktop", "DAX") // falseText.StartsWith / EndsWith
Return true if text starts or ends with a given value.
Text.StartsWith("SKU-001", "SKU") // true
Text.EndsWith("report.csv", ".csv") // trueText.Trim / TrimStart / TrimEnd
Remove whitespace. Trim removes both sides; TrimStart removes leading; TrimEnd removes trailing.
Text.Trim(" Hello World ") // "Hello World"
Text.TrimStart(" Hello World ") // "Hello World "
Text.TrimEnd(" Hello World ") // " Hello World"Text.PadStart / PadEnd
Pad a string to a minimum length with a specified character.
Text.PadStart("42", 5, "0") // "00042"
Text.PadEnd("North", 10, " ") // "North "Text.From
Convert any value to its text representation.
Text.From(42) // "42"
Text.From(3.14) // "3.14"
Text.From(true) // "true"
Text.From(#date(2024,6,15)) // "2024-06-15"Text.ToList
Convert a text string into a list of individual characters.
Text.ToList("ABC") // {"A", "B", "C"}Number Functions
Number.Abs
Return the absolute value.
Number.Abs(-42) // 42
Number.Abs(42) // 42Number.Round
Round to a specified number of decimal places.
Number.Round(3.14159, 2) // 3.14
Number.Round(2.5, 0) // 3Number.RoundUp / RoundDown
Always round up or always round down.
Number.RoundUp(3.1, 0) // 4
Number.RoundDown(3.9, 0) // 3Number.IntegerDivide
Return the integer quotient of a division (no remainder).
Number.IntegerDivide(17, 5) // 3Number.Mod
Return the remainder of a division.
Number.Mod(17, 5) // 2
Number.Mod(10, 2) // 0Number.Power
Raise a number to a power.
Number.Power(2, 10) // 1024
Number.Power(9, 0.5) // 3 (square root)Number.Sqrt
Return the square root.
Number.Sqrt(144) // 12
Number.Sqrt(2) // 1.4142...Number.Ln / Exp
Natural logarithm and its inverse (e to the power of x).
Number.Ln(1) // 0
Number.Exp(1) // 2.71828... (e)Number.Log
Logarithm with a specified base.
Number.Log(100, 10) // 2
Number.Log(8, 2) // 3Number.IsNaN
Return true if a value is Not a Number (NaN).
Number.IsNaN(0/0) // true
Number.IsNaN(42) // falseNumber.From
Convert a value to a number.
Number.From("42") // 42
Number.From(true) // 1
Number.From(false) // 0Number.ToText
Convert a number to text with optional format and culture.
Number.ToText(1234567.89, "N2") // "1,234,567.89"
Number.ToText(0.852, "P1") // "85.2%"Value.Equals
Test deep equality between two values of any type.
Value.Equals({1,2,3}, {1,2,3}) // true
Value.Equals([A=1], [A=1]) // trueDate & Time Functions
Date.From
Convert a value to a date.
Date.From("2024-06-15") // #date(2024, 6, 15)
Date.From(#datetime(2024,6,15,9,0,0)) // #date(2024, 6, 15)DateTime.LocalNow
Return the current local date and time.
DateTime.LocalNow() // current datetime on the machineDate.Year / Month / Day
Extract the year, month, or day from a date.
Date.Year(#date(2024, 6, 15)) // 2024
Date.Month(#date(2024, 6, 15)) // 6
Date.Day(#date(2024, 6, 15)) // 15Date.DayOfWeek
Return the day of week as a number. Optional second argument sets the first day of the week.
// Day.Monday makes Monday = 0
Date.DayOfWeek(#date(2024, 6, 15), Day.Monday) // returns 5 (Saturday)Date.WeekOfYear
Return the week number of the year.
Date.WeekOfYear(#date(2024, 6, 15)) // 24Date.QuarterOfYear
Return the quarter number (1–4).
Date.QuarterOfYear(#date(2024, 6, 15)) // 2Date.AddDays / Months / Years
Add a specified number of days, months, or years to a date.
Date.AddDays(#date(2024, 6, 15), 30) // #date(2024, 7, 15)
Date.AddMonths(#date(2024, 6, 15), 3) // #date(2024, 9, 15)
Date.AddYears(#date(2024, 6, 15), 1) // #date(2025, 6, 15)Date.StartOfMonth / EndOfMonth
Return the first or last day of the month.
Date.StartOfMonth(#date(2024, 6, 15)) // #date(2024, 6, 1)
Date.EndOfMonth(#date(2024, 6, 15)) // #date(2024, 6, 30)Date.StartOfYear / EndOfYear
Return the first or last day of the year.
Date.StartOfYear(#date(2024, 6, 15)) // #date(2024, 1, 1)
Date.EndOfYear(#date(2024, 6, 15)) // #date(2024, 12, 31)Duration.Days / TotalHours
Extract components from a duration value.
Duration.Days(#duration(3, 4, 30, 0)) // 3
Duration.TotalHours(#duration(1, 6, 0, 0)) // 30Date difference
Subtract two dates to get a duration, then extract the component you need.
let
Start = #date(2024, 1, 1),
End = #date(2024, 6, 15),
Diff = End - Start,
DaysApart = Duration.Days(Diff) // 166
in
DaysApartList Functions
List creation
Create lists with literal syntax or range shorthand.
{1, 2, 3} // explicit list
{1..10} // range: 1 to 10
{"a".."e"} // character range: {"a","b","c","d","e"}
{} // empty listList.Count
Return the number of items in a list.
List.Count({10, 20, 30, 40}) // 4List.First / Last
Return the first or last item.
List.First({10, 20, 30}) // 10
List.Last({10, 20, 30}) // 30List.FirstN / LastN
Return the first or last N items as a list.
List.FirstN({10, 20, 30, 40, 50}, 3) // {10, 20, 30}
List.LastN({10, 20, 30, 40, 50}, 2) // {40, 50}List.Distinct
Remove duplicate values.
List.Distinct({"a", "b", "a", "c", "b"}) // {"a", "b", "c"}List.Select
Filter a list to items that satisfy a condition.
List.Select({1, 2, 3, 4, 5, 6}, each _ > 3) // {4, 5, 6}
List.Select({"apple","ant","banana"}, each Text.StartsWith(_, "a"))
// {"apple", "ant"}List.Transform
Apply a function to every item in a list and return the results.
List.Transform({1, 2, 3, 4}, each _ * 2) // {2, 4, 6, 8}
List.Transform({"hello", "world"}, Text.Upper) // {"HELLO", "WORLD"}List.Sort
Sort a list. Default is ascending; pass Order.Descending for descending.
List.Sort({3, 1, 4, 1, 5, 9}) // {1, 1, 3, 4, 5, 9}
List.Sort({3, 1, 4, 1, 5, 9}, Order.Descending) // {9, 5, 4, 3, 1, 1}List.Reverse
Reverse the order of a list.
List.Reverse({1, 2, 3, 4, 5}) // {5, 4, 3, 2, 1}List.Contains / ContainsAny / All
Test whether a list contains a value, any value from another list, or all values.
List.Contains({"a","b","c"}, "b") // true
List.ContainsAny({"a","b","c"}, {"b","x"}) // true (b matches)
List.ContainsAll({"a","b","c"}, {"a","b"}) // trueList.MatchesAny / All
Test whether any or all items in a list satisfy a condition.
List.MatchesAny({1, 2, 3, 4}, each _ > 3) // true (4 > 3)
List.MatchesAll({1, 2, 3, 4}, each _ > 0) // true (all positive)List.RemoveNulls
Remove all null values from a list.
List.RemoveNulls({1, null, 2, null, 3}) // {1, 2, 3}List.RemoveRange
Remove a range of items by start index and count.
// List.RemoveRange(list, index, count)
List.RemoveRange({1, 2, 3, 4, 5}, 1, 2) // {1, 4, 5}List.Repeat
Repeat a list N times.
List.Repeat({1, 2}, 3) // {1, 2, 1, 2, 1, 2}List.Combine
Concatenate multiple lists into one.
List.Combine({{1, 2}, {3, 4}, {5, 6}}) // {1, 2, 3, 4, 5, 6}List.Split
Split a list into sublists of a specified size.
List.Split({1, 2, 3, 4, 5, 6}, 2)
// {{1, 2}, {3, 4}, {5, 6}}List.Min / Max / Sum / Average
Aggregate functions over a list.
List.Min({3, 1, 4, 1, 5}) // 1
List.Max({3, 1, 4, 1, 5}) // 5
List.Sum({10, 20, 30}) // 60
List.Average({10, 20, 30}) // 20List.Product / StandardDeviation
Multiply all values or calculate standard deviation.
List.Product({2, 3, 4}) // 24
List.StandardDeviation({2,4,4,4,5,5,7,9}) // 2List.Union / Intersect / Difference
Set operations on lists.
List.Union({{1,2,3},{2,3,4}}) // {1, 2, 3, 4}
List.Intersect({{1,2,3},{2,3,4}}) // {2, 3}
List.Difference({1,2,3,4},{2,4}) // {1, 3}List.Numbers
Generate a list of numbers from a start, with a count and optional step.
List.Numbers(1, 5) // {1, 2, 3, 4, 5}
List.Numbers(0, 5, 2) // {0, 2, 4, 6, 8}List.Dates
Generate a list of dates from a start, with a count and duration step.
List.Dates(
#date(2024, 1, 1),
12,
#duration(31, 0, 0, 0)
)
// Approximately one date per month for 12 monthsList.Generate
Generate a list by iterating with an initial state, condition, and next-state function.
// Generate powers of 2 up to 512
List.Generate(
() => 1,
each _ <= 512,
each _ * 2
)
// {1, 2, 4, 8, 16, 32, 64, 128, 256, 512}List.SingleOrDefault
Return the single item in a list, or a default value if the list is empty or has multiple items.
List.SingleOrDefault({42}) // 42
List.SingleOrDefault({}, 0) // 0
List.SingleOrDefault({1,2}, -1) // -1 (multiple items)Record Functions
Record creation
Create a record with named fields using square bracket syntax.
[Name = "Alex", Role = "Engineer", Active = true]Record.Field
Access a field value by name as a function call.
Record.Field([Name = "Alex", Age = 30], "Name") // "Alex"record[FieldName]
Access a field value using dot-style lookup — more common in practice.
let r = [Name = "Alex", Age = 30]
in r[Name] // "Alex"Record.FieldNames / Values
Return a list of all field names or all field values.
Record.FieldNames([A = 1, B = 2, C = 3]) // {"A", "B", "C"}
Record.FieldValues([A = 1, B = 2, C = 3]) // {1, 2, 3}Record.HasFields
Return true if a record contains the specified field(s).
Record.HasFields([A = 1, B = 2], "A") // true
Record.HasFields([A = 1, B = 2], {"A", "C"}) // false (C missing)Record.AddField
Add a new field to a record.
Record.AddField([Name = "Alex"], "Role", "Engineer")
// [Name = "Alex", Role = "Engineer"]Record.RemoveFields
Remove one or more fields from a record.
Record.RemoveFields([A = 1, B = 2, C = 3], {"B", "C"})
// [A = 1]Record.RenameFields
Rename fields by providing a list of old/new name pairs.
Record.RenameFields(
[first_name = "Alex", last_name = "Mensah"],
{{"first_name", "FirstName"}, {"last_name", "LastName"}}
)
// [FirstName = "Alex", LastName = "Mensah"]Record.ToTable
Convert a record to a two-column table with Name and Value columns.
Record.ToTable([Region = "North", Sales = 42000])
// Table: Name | Value
// Region | North
// Sales | 42000Record.FromList
Create a record from a list of values and a list of field names.
Record.FromList({"Alex", 30, true}, {"Name", "Age", "Active"})
// [Name = "Alex", Age = 30, Active = true]Table Functions
Table.FromRecords
Create a table from a list of records. Each record becomes a row.
Table.FromRecords({
[Name = "Alex", Sales = 42000],
[Name = "Sarah", Sales = 51000],
[Name = "James", Sales = 38000]
})Table.RowCount / ColumnCount
Return the number of rows or columns.
Table.RowCount(Source) // e.g. 1500
Table.ColumnCount(Source) // e.g. 12Table.ColumnNames
Return a list of column names.
Table.ColumnNames(Source) // {"ID", "Name", "Date", "Amount"}Table.SelectRows
Filter rows using a condition. each is shorthand for a row function.
Table.SelectRows(Source, each [Region] = "North")
Table.SelectRows(Source, each [Amount] > 1000 and [Status] = "Active")Table.AddColumn
Add a new calculated column.
Table.AddColumn(Source, "FullName", each [FirstName] & " " & [LastName])
Table.AddColumn(Source, "Margin",
each [Revenue] - [Cost],
type number
)Table.TransformColumns
Apply a transformation function to one or more existing columns.
Table.TransformColumns(Source, {
{"Name", Text.Proper},
{"Email", Text.Lower},
{"Amount", each _ * 1.1, type number}
})Table.TransformColumnTypes
Set the data type of one or more columns.
Table.TransformColumnTypes(Source, {
{"OrderDate", type date},
{"Amount", type number},
{"CustomerID", type text}
})Table.RemoveColumns
Remove one or more columns by name.
Table.RemoveColumns(Source, {"TempCol", "InternalID"})Table.SelectColumns
Keep only the specified columns — drops everything else.
Table.SelectColumns(Source, {"CustomerID", "Name", "OrderDate", "Amount"})Table.RenameColumns
Rename columns by providing old/new name pairs.
Table.RenameColumns(Source, {
{"customer_id", "CustomerID"},
{"order_date", "OrderDate"},
{"total_amount", "TotalAmount"}
})Table.ReorderColumns
Reorder columns to a specified sequence.
Table.ReorderColumns(Source, {"ID", "Date", "Name", "Amount"})Table.Sort
Sort a table by one or more columns.
Table.Sort(Source, {{"OrderDate", Order.Descending}})
// Multiple sort columns
Table.Sort(Source, {
{"Region", Order.Ascending},
{"Amount", Order.Descending}
})Table.Group
Group rows and apply aggregations — equivalent to GROUP BY in SQL.
Table.Group(Source, {"Region"}, {
{"TotalSales", each List.Sum([Amount]), type number},
{"OrderCount", each Table.RowCount(_), type number},
{"AvgSale", each List.Average([Amount]), type number}
})Table.PromoteHeaders
Use the first row of a table as column headers.
Table.PromoteHeaders(Source, [PromoteAllScalars = true])Table.DemoteHeaders
Move column headers back to the first row as data.
Table.DemoteHeaders(Source)Table.FillDown / FillUp
Fill null values in a column by propagating the nearest non-null value downward or upward.
Table.FillDown(Source, {"Region", "Category"})
Table.FillUp(Source, {"Region"})Table.Pivot
Pivot a column — turn unique row values into column headers.
// Turn Region values (North, South, East) into columns
Table.Pivot(
Source,
List.Distinct(Source[Region]), // distinct values become column names
"Region", // column to pivot
"Amount", // values to aggregate
List.Sum // aggregation function
)Table.Unpivot
Unpivot specified columns — turn column headers into row values. Reverse of pivot.
Table.Unpivot(Source, {"Jan","Feb","Mar","Apr"}, "Month", "Amount")
// Columns Jan, Feb, Mar, Apr become rows in Month columnTable.UnpivotOtherColumns
Unpivot all columns except the ones specified as identity columns.
Table.UnpivotOtherColumns(Source, {"ProductID", "ProductName"}, "Month", "Amount")Table.ExpandListColumn
Expand a column containing lists — each list item becomes its own row.
Table.ExpandListColumn(Source, "Tags")Table.ExpandRecordColumn
Expand a column containing records — each record field becomes its own column.
Table.ExpandRecordColumn(
Source,
"Address",
{"Street", "City", "PostalCode"},
{"Address.Street", "Address.City", "Address.PostalCode"}
)Table.NestedJoin
Join two tables on a key column and store the result as a new nested table column.
Table.NestedJoin(
Orders, {"CustomerID"},
Customers, {"CustomerID"},
"CustomerData",
JoinKind.LeftOuter
)Table.Join
Join two tables directly — returns a flat combined table.
Table.Join(
Orders, {"CustomerID"},
Customers, {"CustomerID"},
JoinKind.Inner
)Table.Distinct
Remove duplicate rows. Optionally specify columns to compare.
Table.Distinct(Source)
Table.Distinct(Source, {"CustomerID", "OrderDate"})Table.Buffer
Load the entire table into memory — prevents repeated re-evaluation of upstream steps. Use before operations that iterate over the table multiple times.
Buffered = Table.Buffer(Source)Functions & Each
Function definition
Define a reusable function using the (parameters) => expression syntax.
// Named function in a let block
AddTax = (price as number, rate as number) as number =>
price * (1 + rate),
// Call it
TotalWithTax = AddTax(100, 0.2) // 120each shorthand
each is shorthand for (_) => — a function that takes a single argument called _. Used heavily with table and list functions.
// These are equivalent
Table.SelectRows(Source, each [Amount] > 100)
Table.SelectRows(Source, (_) => _[Amount] > 100)
// each in List.Transform
List.Transform({1, 2, 3, 4}, each _ * 2)each with record fields
Inside each, use [FieldName] to access a field of the current row record.
// Access multiple fields per row
Table.AddColumn(Source, "Label",
each [Region] & " - " & Text.From([Year])
)
// Conditional per row
Table.AddColumn(Source, "Tier",
each if [Amount] >= 10000 then "High"
else if [Amount] >= 5000 then "Mid"
else "Low"
)Type annotation
Specify input and output types on a function for validation and documentation.
CleanName = (raw as text) as text =>
Text.Trim(Text.Proper(raw))Optional parameters
Mark a parameter optional with optional. It receives null if not provided.
Greet = (name as text, optional greeting as text) as text =>
let
g = if greeting = null then "Hello" else greeting
in
g & ", " & name & "!"
Greet("Alex") // "Hello, Alex!"
Greet("Alex", "Welcome") // "Welcome, Alex!"?? (null coalescing)
Return the left value if it is not null, otherwise return the right value.
"value" ?? "default" // "value"
null ?? "default" // "default"
// Practical use — fallback when a field might be null
[PreferredName] ?? [FirstName] ?? "Unknown"Part of the FTTG Learn Cheat Sheet series — fttgsolutions.com