6.9 Introduction to the M Language
Every query is an M expression. Open Home › Advanced Editor to see the full code. M queries are built with a let … in block: each line defines a named step that usually refers to the previous one.
let
Source = Csv.Document(
File.Contents("C:\QuickCommerce\Blinkit_Orders_2025.csv"),
[Delimiter = ",", Encoding = 65001, QuoteStyle = QuoteStyle.Csv]
),
#"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars = true]),
#"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers", {
{"OrderID", type text},
{"OrderDateTime", type datetime},
{"Quantity", Int64.Type},
{"Amount", Currency.Type},
{"DeliveryTimeMins", Int64.Type}
}),
#"Renamed Columns" = Table.RenameColumns(#"Changed Type", {
{"OrderID", "Order ID"}, {"OrderDateTime", "Order DateTime"},
{"DeliveryTimeMins", "Delivery Time Mins"}
}),
#"Filtered Rows" = Table.SelectRows(#"Renamed Columns", each [Quantity] > 0),
#"Added Order Date" = Table.AddColumn(#"Filtered Rows", "Order Date",
each DateTime.Date([Order DateTime]), type date),
#"Added Order Hour" = Table.AddColumn(#"Added Order Date", "Order Hour",
each Time.Hour([Order DateTime]), Int64.Type)
in
#"Added Order Hour"
Key points about M:
- M is case-sensitive:
Table.SelectRowsworks,table.selectrowsdoes not. - Step names with spaces are written as
#"Step Name". eachis a shortcut for a function applied to every row;[Column]refers to a column in the current row.- The value after
inis what the query returns (normally the last step). - Comments:
// single lineand/* multi-line */.
Converting UTC timestamps to IST
Some systems store timestamps in UTC. To convert a UTC column to Indian Standard Time (UTC+5:30), add a custom column like the one below. DateTime.AddZone(…, 0) marks the value as UTC, DateTimeZone.SwitchZone(…, 5, 30) converts it to IST, and DateTimeZone.RemoveZone returns a normal Date/Time. Our sample files are already in IST, so they do not need this step.
= Table.AddColumn(Source, "Order DateTime", each
DateTimeZone.RemoveZone(
DateTimeZone.SwitchZone(DateTime.AddZone([OrderDateTimeUTC], 0), 5, 30)
), type datetime)
A small custom function
// Query named fnDeliveryBand
(mins as nullable number) as text =>
if mins = null then "Not delivered"
else if mins <= 10 then "Within 10 min"
else if mins <= 20 then "11-20 min"
else "Over 20 min"
Use it in Add Column › Invoke Custom Function, or in a custom column: fnDeliveryBand([Delivery Time Mins]).
M code path karaycha nahi, fakt vachta aala pahije. UI vaprun step banva, aani formula bar madhe bagha.
Ravindra Bagale's Tip
Look, friends: M is case-sensitive, and that trips up almost every beginner: text.upper or [amount] fails, while Text.Upper and [Amount] work. Let the UI write the first version of a step, then edit the M code in the formula bar instead of typing everything from memory. Remember this rule.
Ravindra Bagale's Tip – मराठी
हे बघा मित्रांनो: M case-sensitive आहे, आणि त्यात जवळजवळ प्रत्येक beginner अडखळतो: text.upper किंवा [amount] fail होतं, तर Text.Upper आणि [Amount] चालतं. Step चं पहिलं version UI ला लिहू द्या, मग सगळं आठवणीतून type करण्याऐवजी formula bar मध्ये M code edit करा. हा नियम लक्षात ठेवा.
Ravindra Bagale's Tip – हिंदी
देखो दोस्तों: M case-sensitive है, और इसमें लगभग हर beginner फँसता है: text.upper या [amount] fail होता है, जबकि Text.Upper और [Amount] चलते हैं. Step का पहला version UI को लिखने दो, फिर सब कुछ याद से type करने की बजाय formula bar में M code edit करो. यह नियम याद रखो.