Sections & the Shared Environment
The hidden organizational structure of M programs — sections, section members, and the #shared global environment.
Behind every Power Query project is a structure most users never see: sections. Understanding sections explains how queries reference each other, how the standard library is organized, and how #shared works.
What Is a Section?
A section is a named container for a group of variable definitions (called section members). Each "query" you see in the Power Query Editor is actually a section member:
section MySection;
shared Sales = Csv.Document(File.Contents("sales.csv"));
shared CleanedSales = Table.SelectRows(Sales, each [Region] <> null);The Power Query UI hides this syntax — when you edit a query in the Advanced Editor, you only see the expression (the right-hand side of the assignment). But behind the scenes, each query is a member of a section.
shared vs. Private Members
Section members marked with shared are visible to other queries. Members without shared are private to their section:
section MySection;
// Visible to other queries
shared Customers = ...;
// Only accessible within this section
HelperFunction = (x) => x * 2;In practice, the Power Query UI always creates shared members, so every query can reference every other query. But when writing M code directly or building custom connectors, the distinction matters.
The #shared Environment
#shared is a special record that contains all shared section members plus the entire standard library. You can inspect it to discover every available function and query:
#sharedThis returns a record with thousands of fields — every built-in function (Table.AddColumn, Text.Upper, etc.) and every query in your project.
To check if a specific function exists:
Record.HasFields(#shared, "Table.AddColumn") // trueTo list all available function names:
Record.FieldNames(#shared)How Queries Reference Each Other
When Query B references Query A by name, M resolves that name through the shared environment. This is why you can write:
// In Query B
let
Source = Sales, // References the "Sales" query by name
Filtered = Table.SelectRows(Source, each [Region] = "East")
in
FilteredSales is resolved because it is a shared section member visible in the global environment.
Expression.Evaluate and #shared
Expression.Evaluate compiles and runs an M expression from text. It takes an optional environment parameter — typically #shared — so the expression can access standard library functions:
Expression.Evaluate("1 + 2") // 3
Expression.Evaluate("Text.Upper(""hello"")", #shared) // "HELLO"Without passing #shared, the evaluated expression cannot reference any built-in functions — it only has access to basic operators.
The Standard Library
The M standard library (all the Table.*, Text.*, List.* functions, etc.) is loaded into the global environment before your queries run. This is why you can call Table.AddColumn without importing anything — it is already in #shared.
Custom data connectors can extend the global environment by adding their own functions (e.g., Salesforce.Accounts, GoogleAnalytics.Data). These appear in #shared alongside the standard library.
Best Practices
- Use
#sharedfor exploration, not production code. It is a powerful debugging tool but referencing it directly makes queries less portable. - Keep helper queries private when building in environments that support it (custom connectors, TMDL). Not every query needs to be shared.
- Pass
#sharedtoExpression.Evaluatewhen you need the evaluated expression to access standard library functions. - Understand that query names are identifiers in the shared environment. Renaming a query changes its identifier, which can break references from other queries.