This article describes basic rules for working with M, which is a language for queries in Power Query (Get and Transform) as well as in Power BI.

Honestly, it is not necessary to know this language – because most of workflow steps can be done in standard GUI and M is used in background only. So, this article is mostly for advanced users – that need to write less common thing. 

Before I start with specific rules, I´d like to emphasize that M is case sensitive in both variables and function names. So, for example when writing “If” function, you cannot write “IF”. This is little bit tricky, since other languages we are discussing on this webpage are not so sensitive in this delicate in this…

  • Common formulas in Excel can be written in capitals or small letters, anyway Excel changes everything to capitals. For example “if” is changed to “IF”.
  • In DAX you can use small or capitals and it is OK
  • VBA changes the syntax automatically – in functions mostly to first capital

So we have to care about case sensitivity in M. And what else?

Basic logic

The basic logic is quite simple. There are always two blocks – “let” and “in”. “Let” contains multiple rows defining variables, “in” is an output. Yes, “in” is really the output – I don´t say this syntax makes sense…

It looks like this:

let
   my_variable = “hello world”
in
   my_variable

In this example, the output is “hello world”, the value of “my_variable” variable, which is in output. If you write this in the advanced editor in Power Query or in Power BI, you will really see the text string “hello world”.

Yes, but don´t need the “hello wordl” usually. So this is a query, taking the “Revenue” column in “Source” source and divides it by 1000.

let
   Source = my_source,
   #”Divided Column” = Table.TransformColumns(Source, {{“Revenue”, each _ / 1000, type number}})
in
   #”Divided Column”

Variables

To say it simply, every row is derived from the previous one. So the last row´s name is “Divided Column” and is calculated from “Source” using the Table.TransformColumns function. Source comes from “my_source” etc, no matter how many rows do we have.

You can give any name to the steps (names of variables). So if you switched “Source” to “xy”, it is still working – you just have to change twice – in two following rows.

If the name of variable contains multiple words separated by space, you need to start with # and use quotation marks. For example:

  • xy

but:

  • #”x y”

Functions

Functions are called simply by writing of their name and its arguments, like this:

  • Text.Start(“abcd”, 2)

resulting in “ab”

Comments

Comments, the part of code, that has no impact on query, can be written like thiswith two slashes (if it is only one row):

  • // this is my comment

or like this (if it is for multiple rows)

  • */ this is my
    comment */

So… that´s all…