Power Query
M language Β· Transform Β· Merge Β· Append Β· Pivot & Unpivot Β· Custom columns Β· Query folding
Sheet 3 of 3
Power BI / Excel
Intermediate
Printable
M Language Structure β letβ¦in
Basic Query Structure
// Every M query follows letβ¦in let // Each step = named transformation Source = Csv.Document( File.Contents("data.csv"), [Delimiter=",", Encoding=1252] ), PromotedHeaders = Table.PromoteHeaders(Source), ChangedTypes = Table.TransformColumnTypes( PromotedHeaders, {{"Date", type date}, {"Sales", type number}}) in ChangedTypes // last step = output
M Language Rules
// Case-sensitive β "text" β "Text" // Each step references the previous // Steps separated by commas // Last step after "in" = query output // Data types type text type number type date type datetime type logical // true/false type duration type any // untyped type null // Comments // single line /* multi line */
Values, Lists & Records
// Primitive values "hello" // text 42 // number 3.14 // decimal true // logical null // null #date(2026,1,15) // date literal // List β curly braces {1, 2, 3} {"a", "b", "c"} // Record β square brackets [Name="Alice", Age=30] // Access record field myRecord[Name]
Power Query UI writes M for you. Every button click in the Query Editor generates a step. View the code anytime via Home β Advanced Editor. Edit M directly for transformations the UI can't do.
Connect & Load Data
Common Data Sources
// Excel / CSV Excel.Workbook(File.Contents("path")) Csv.Document(File.Contents("path")) // SQL Server Sql.Database("server", "database") // SharePoint folder SharePoint.Files("https://...") // Web / API Web.Contents("https://api.example.com") Json.Document(Web.Contents("url")) // Folder β combine multiple files Folder.Files("C:\Data\Reports")
Load Options
| Option | Use when |
|---|---|
| Load to Table | Need data in a worksheet |
| Load to Data Model | Power Pivot / Power BI model |
| Connection Only | Intermediate query (used in merge/append) |
| Close & Apply | Finalise and push to Power BI model |
Common Transforms
Filter, Sort & Column Operations
// Filter rows β keep matching Table.SelectRows(Source, each [Region] = "North") // Filter with AND Table.SelectRows(Source, each [Region] = "North" and [Sales] > 1000) // Remove columns Table.RemoveColumns(Source, {"Col1", "Col2"}) // Keep only these columns Table.SelectColumns(Source, {"Date", "Sales", "Region"}) // Rename a column Table.RenameColumns(Source, {{"OldName", "NewName"}}) // Sort descending Table.Sort(Source, {{"Sales", Order.Descending}})
Column Transformations
Add & Transform Columns
// Add custom column Table.AddColumn(Source, "Profit", each [Revenue] - [Cost]) // Add conditional column Table.AddColumn(Source, "Tier", each if [Sales] > 10000 then "Gold" else if [Sales] > 5000 then "Silver" else "Bronze") // Transform existing column Table.TransformColumns(Source, {{"Name", Text.Upper}, {"Sales", each _ * 1.1}})
Split, Replace & Clean
// Split column by delimiter Table.SplitColumn(Source, "FullName", Splitter.SplitTextByDelimiter( " ", QuoteStyle.Csv), {"First", "Last"}) // Replace value in column Table.ReplaceValue(Source, "N/A", null, Replacer.ReplaceText, {"Region"}) // Fill down (replace nulls) Table.FillDown(Source, {"Category"}) // Remove duplicates Table.Distinct(Source) // Remove blank rows Table.SelectRows(Source, each not List.IsEmpty( List.RemoveMatchingItems( Record.FieldValues(_), {null, ""})))
Change Data Types
Table.TransformColumnTypes( Source, { {"OrderDate", type date}, {"Revenue", type number}, {"CustomerID",type text}, {"IsActive", type logical} } ) // Common type errors to fix // Numbers stored as text β // change to type number // Dates as text β // change to type date // (locale matters!) // Detect types automatically Table.TransformColumnTypes( Source, Table.Schema(Source) [[Name],[TypeName]] )
Always set data types explicitly β don't rely on auto-detect. Incorrect types (numbers as text, wrong date locale) cause silent errors in DAX measures and visuals downstream.
Pivot & Unpivot
Unpivot β wide to tall (most common)
// Before: each month is a column // Region | Jan | Feb | Mar // After: Region | Month | Sales // Unpivot selected columns Table.UnpivotOtherColumns( Source, {"Region"}, // columns to KEEP "Month", // new attribute col "Sales" // new value col ) // Unpivot only selected columns Table.Unpivot(Source, {"Jan", "Feb", "Mar"}, "Month", "Sales")
Pivot β tall to wide
// Before: Region | Month | Sales // After: Region | Jan | Feb | Mar Table.Pivot( Source, List.Distinct(Source[Month]), "Month", // col to pivot from "Sales", // values col List.Sum // aggregation )
Unpivot is your best friend for cleaning cross-tab / matrix data exports β surveys, financial reports, pivot-table exports. Unpivot then model properly in Power BI.
Merge & Append Queries
Merge β join two tables (like SQL JOIN)
// Table.NestedJoin( // table1, key1, table2, key2, // newColName, joinKind) Merged = Table.NestedJoin( Sales, {"ProductID"}, Products, {"ID"}, "ProductsTable", JoinKind.LeftOuter ), // Then expand the nested table Expanded = Table.ExpandTableColumn( Merged, "ProductsTable", {"Name", "Category"} )
Join Kind Reference
| JoinKind | Returns |
|---|---|
| LeftOuter | All left rows + matching right |
| RightOuter | All right rows + matching left |
| FullOuter | All rows from both tables |
| Inner | Only matching rows in both |
| LeftAnti | Left rows with NO match in right |
| RightAnti | Right rows with NO match in left |
Append β stack tables (like UNION)
// Append two tables vertically Table.Combine( {Sales2024, Sales2025} ) // Append multiple tables Table.Combine( {Q1, Q2, Q3, Q4} ) // Append all files in a folder // Home β New Source β Folder // β Combine & Transform // Power Query auto-creates // a Sample File + Transform fn // UI shortcut: Home β // Append Queries (as new)
Use Connection Only for intermediate queries. When you create queries just for merging or appending, set them to "Connection Only" β they won't load to the model, keeping it lean.
Text, Number & Date Functions
Text Functions
Text.Upper([Name]) Text.Lower([Name]) Text.Trim([Name]) Text.Length([Code]) Text.Start([Code], 3) first 3 Text.End([Code], 2) last 2 Text.Middle([Code], 1, 4) 4 from pos 1 Text.Contains([Name], "Ltd") Text.Replace([Col],"old","new") Text.Combine({[F],[L]}, " ")
Number & Date Functions
// Number Number.Round([Price], 2) Number.Abs([Variance]) Number.Mod([Value], 7) Number.IntegerDivide([A],[B]) // Date Date.Year([OrderDate]) Date.Month([OrderDate]) Date.Day([OrderDate]) Date.DayOfWeek([OrderDate]) Date.MonthName([OrderDate]) Date.QuarterOfYear([OrderDate]) Date.From([DateText]) DateTime.LocalNow()
Group By & Aggregation
Table.Group β aggregate rows
// Basic group by Table.Group( Source, {"Region"}, // group keys { {"TotalSales", each List.Sum([Sales]), type number}, {"OrderCount", each Table.RowCount(_), type number} } )
Multi-key group + more aggregations
Table.Group( Source, {"Region", "Year"}, // two keys { {"Total", each List.Sum([Sales])}, {"Avg", each List.Average([Sales])}, {"Max", each List.Max([Sales])}, {"Rows", each Table.RowCount(_)} } )
Parameters, Query Folding & Best Practices
Parameters β dynamic values
// Create via: Home β Manage Parameters // Use in M code as a variable // Example: paramServerName = "PROD" let Source = Sql.Database( paramServerName, paramDatabase ) in Source // Use parameter in filter Table.SelectRows(Source, each [Year] = paramYear) // Dynamic file path File.Contents(paramFolderPath & "data.csv")
Query Folding β push work to source
// Query folding = steps translated // to SQL and run on the server // β much faster for large data β Folds to SQL (fast) Table.SelectRows WHERE Table.SelectColumns SELECT Table.Sort ORDER BY Table.Group GROUP BY Table.NestedJoin JOIN β Breaks folding (run in PQ) Table.AddColumn (custom formula) Table.Buffer (forces in-memory) CSV/Excel source (no server) // Check folding: right-click step // β View Native Query (greyed = no fold)
Best Practices
β Filter & select cols EARLY β reduces data loaded β Set types explicitly β avoids silent errors β Name steps descriptively FilteredToNorth RemovedNullRows β Use Connection Only for intermediate queries β Disable load for staging queries (right-click query β Enable Load = off) β Table.Buffer() when a table is referenced many times β caches in memory
Power Query Quick Reference
| Table Functions | Purpose |
|---|---|
| Table.SelectRows | Filter rows by condition |
| Table.SelectColumns | Keep only specified columns |
| Table.RemoveColumns | Drop specified columns |
| Table.RenameColumns | Rename one or more columns |
| Table.AddColumn | Add custom or conditional column |
| Table.TransformColumns | Transform values in columns |
| Table.TransformColumnTypes | Change data types |
| Table.Group | Group by + aggregate |
| Table.Sort | Sort rows |
| Table.Distinct | Remove duplicate rows |
| Table.RowCount | Count rows |
| Table.Combine | Append (union) tables |
| Reshape Functions | Purpose |
|---|---|
| Table.Pivot | Tall β wide (column per value) |
| Table.Unpivot | Wide β tall (selected cols) |
| Table.UnpivotOtherColumns | Wide β tall (keep specified cols) |
| Table.SplitColumn | Split one column into many |
| Table.NestedJoin | Merge / join two tables |
| Table.ExpandTableColumn | Expand nested table column |
| Table.FillDown | Fill null values downward |
| Table.FillUp | Fill null values upward |
| Table.PromoteHeaders | Use first row as headers |
| Table.Transpose | Flip rows and columns |
| Table.ReplaceValue | Replace values in column(s) |
| Table.Buffer | Cache table in memory |
| List & Text | Purpose |
|---|---|
| List.Sum / Average | Aggregate a list |
| List.Max / Min | Largest / smallest in list |
| List.Distinct | Unique values in a list |
| List.Count | Number of items |
| List.Contains | Check if value exists |
| List.Generate | Generate list dynamically |
| Text.Upper / Lower | Change case |
| Text.Trim | Remove whitespace |
| Text.Contains | Check substring |
| Text.Replace | Replace substring |
| Text.Combine | Join list of text with delimiter |
| Date.Year / Month / Day | Extract date parts |
Power BI series complete! β Β·
You've covered Power BI Basics, DAX Formulas, and Power Query. Explore more on Dataplexa β Tableau, Statistics & Math, and the full Analytics & BI cheat sheet collection.