top of page

Unlocking Next-Level Productivity with Power BI's TMDL View and AI

  • Jihwan Kim
  • 2 days ago
  • 8 min read

Introduction: A New Chapter in My Power BI Development Journey

In this writing, I'd like to share my journey with a feature that has fundamentally changed my approach to Power BI development: the TMDL View. I initially saw it as just another tab in Power BI Desktop, but my most recent learning point is that it's not a feature—it's a gateway to an entire professional development ecosystem.

For those new to the term, Tabular Model Definition Language (TMDL) is a human-readable scripting language that acts as the blueprint for a Power BI semantic model. Every table, relationship, and measure is represented in a clean, text-based format. The TMDL View, available as a preview feature in Power BI Desktop, is the built-in code editor that lets you see and interact with this blueprint directly. 


My central discovery, and the focus of this post, is that the true power of TMDL View is realized not in isolation, but when combined with Power BI Projects (.pbip), external editors like Visual Studio (VS) Code, version control with Git, and the assistive power of Generative AI like GitHub Copilot. This synergy transforms Power BI development from a series of UI clicks into a structured, efficient, and collaborative process akin to modern software engineering. This evolution represents a strategic pivot by Microsoft, elevating the native development experience by incorporating capabilities that previously required a heavy reliance on third-party tools. This post will walk you through my learning curve, from initial efficiency gains to embracing a full-fledged development lifecycle that has unlocked a new level of productivity.   


Beyond the UI: My First Steps and Foundational Learnings with TMDL View

Getting started is straightforward. You first need to enable the feature by navigating to File > Options and settings > Options > Preview features and checking the box next to "TMDL View". After a quick restart of Power BI Desktop, a new icon for the TMDL View appears on the left-hand pane.   


My First Script

My first interaction was simple: I dragged a table from the Data pane onto the empty TMDL View canvas. Instantly, Power BI Desktop generated a createOrReplace script for that table, laying out its entire definition in clean text. The experience felt immediately familiar, much like scripting a database object in SQL Server Management Studio. This was the first "wow" moment—the sheer transparency of it. Instead of hunting through scattered properties panes and dialogs in the UI, the complete definition of the object was right there in one place.   


createOrReplace

	table fact_sales
		lineageTag: 356586d9-fd5d-4218-b3c8-125b424fb56c

		column date
			dataType: dateTime
			formatString: Long Date
			lineageTag: 4180d495-9366-46f9-a0fe-7e7f7eae5ff8
			summarizeBy: none
			sourceColumn: date

			annotation SummarizationSetBy = Automatic

			annotation UnderlyingDateTimeDataType = Date

		column product
			dataType: string
			lineageTag: 68f8713f-e4bd-4f7a-b6ef-06b710d470c2
			summarizeBy: none
			sourceColumn: product

			annotation SummarizationSetBy = Automatic

		column sales
			dataType: int64
			formatString: 0
			lineageTag: 74624111-fb40-4669-81bc-53e7a39086a2
			summarizeBy: sum
			sourceColumn: sales

			annotation SummarizationSetBy = Automatic

		partition fact_sales = m
			mode: import
			source =
					let
					    Source = Csv.Document(File.Contents("C:\Users\JI\Downloads\sales_product.csv"),[Delimiter=",", Columns=3, Encoding=65001, QuoteStyle=QuoteStyle.None]),
					    #"Promoted Headers" = Table.PromoteHeaders(Source, [PromoteAllScalars=true]),
					    #"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"date", type date}, {"product", type text}, {"sales", Int64.Type}})
					in
					    #"Changed Type"

		annotation PBI_NavigationStepName = Navigation

		annotation PBI_ResultType = Table

Viewing M Code Without the Editor

An unexpected productivity boost came from being able to view a table's Power Query transformations directly within the TMDL script. The M code resides within the table's partition definition, as seen above or below. This allows for a quick check of the logic without launching the resource-intensive Power Query Editor, which can be a time-saver during development. It is important to note, however, that the TMDL View currently lacks syntax highlighting or validation specifically for the embedded M code.


createOrReplace

	createOrReplace

	table dim_calendar
		lineageTag: 287cecaa-890f-4d55-bc5c-fe8168a36f3c
		dataCategory: Time

		column date
			dataType: dateTime
			isKey
			formatString: Short Date
			lineageTag: 8e35a2e7-e13d-4f94-a198-f979063cdb0f
			summarizeBy: none
			sourceColumn: date

			annotation SummarizationSetBy = Automatic

			annotation UnderlyingDateTimeDataType = Date

		column Year
			dataType: int64
			formatString: 0
			lineageTag: 8883a462-b09c-41c9-8d6c-15a23b7f8da4
			summarizeBy: none
			sourceColumn: Year

			annotation SummarizationSetBy = Automatic

		column Month
			dataType: int64
			formatString: 0
			lineageTag: b62e5d1e-b03b-4cf3-a797-8e999f249edf
			summarizeBy: none
			sourceColumn: Month

			annotation SummarizationSetBy = Automatic

		column 'Month Name'
			dataType: string
			lineageTag: f9eb476b-2980-4022-812e-9b25ee86aebd
			summarizeBy: none
			sourceColumn: Month Name
			sortByColumn: Month

			changedProperty = SortByColumn

			annotation SummarizationSetBy = Automatic

		column 'Start of Month'
			dataType: dateTime
			formatString: Short Date
			lineageTag: f4446e5e-c3c9-4a75-afa8-a7339de8844c
			summarizeBy: none
			sourceColumn: Start of Month

			annotation SummarizationSetBy = Automatic

			annotation UnderlyingDateTimeDataType = Date

		column 'End of Month'
			dataType: dateTime
			formatString: Short Date
			lineageTag: 02b7585a-4df5-4c3c-ac58-b23e13209943
			summarizeBy: none
			sourceColumn: End of Month

			annotation SummarizationSetBy = Automatic

			annotation UnderlyingDateTimeDataType = Date

		column Year-Month
			dataType: string
			lineageTag: 793670ce-a42c-46a8-bb73-48c0ae4660c2
			summarizeBy: none
			sourceColumn: Year-Month
			sortByColumn: 'End of Month'

			changedProperty = SortByColumn

			annotation SummarizationSetBy = Automatic

		partition dim_calendar = m
			mode: import
			source =
					let
					    Source = Excel.Workbook(File.Contents("C:\Users\JI\Downloads\calendar.xlsx"), null, true),
					    Sheet1_Sheet = Source{[Item="Sheet1",Kind="Sheet"]}[Data],
					    #"Promoted Headers" = Table.PromoteHeaders(Sheet1_Sheet, [PromoteAllScalars=true]),
					    #"Changed Type" = Table.TransformColumnTypes(#"Promoted Headers",{{"date", type date}}),
					    #"Inserted Year" = Table.AddColumn(#"Changed Type", "Year", each Date.Year([date]), Int64.Type),
					    #"Inserted Month" = Table.AddColumn(#"Inserted Year", "Month", each Date.Month([date]), Int64.Type),
					    #"Inserted Month Name" = Table.AddColumn(#"Inserted Month", "Month Name", each Date.MonthName([date]), type text),
					    #"Inserted Start of Month" = Table.AddColumn(#"Inserted Month Name", "Start of Month", each Date.StartOfMonth([date]), type date),
					    #"Inserted End of Month" = Table.AddColumn(#"Inserted Start of Month", "End of Month", each Date.EndOfMonth([date]), type date),
					    #"Added Custom Column" = Table.AddColumn(#"Inserted End of Month", "Year-Month", each Text.Combine({Text.From([Year], "en-US"), "-", Text.Start([Month Name], 3)}), type text)
					in
					    #"Added Custom Column"

		annotation PBI_NavigationStepName = Navigation

		annotation PBI_ResultType = Table





The Productivity Breakthrough: Mastering Bulk Operations and Hidden Properties


After getting comfortable with viewing scripts, the next step was to leverage the editor for modifications. This is where the productivity gains become truly tangible, especially for repetitive tasks.


Conquering Repetitive Tasks

The built-in code editor facilitates bulk changes with an efficiency that the graphical UI cannot match. For instance, if you need to remove a standard prefix like "dim_" or "fact_" from all your table names, you can script the entire Semantic model, use the find-and-replace feature (Ctrl+F) with a regular expression like dim_, and replace all occurrences with an empty string in a single action.


Another real-world example is updating a property across dozens of measures. In one project, I needed to update the formatStringDefinition for approximately 40 different measures. Doing this through the UI would have involved clicking on each measure individually, navigating to the properties, making the change, and waiting for it to apply—a tedious and error-prone process. With TMDL View, I scripted the table containing the measures, used find-and-replace to update all instances at once, and applied the changes in seconds. This saved a significant amount of time and eliminated the risk of manual errors. For more complex, non-uniform edits, advanced features like multi-cursor editing (Ctrl+Shift+L or Crtl+D) allow for making simultaneous changes in multiple places without repeated find-and-replace operations.   


Unlocking the Model's Secrets


Perhaps one of the most powerful aspects of TMDL View is that it exposes object properties that are not available in the Power BI Desktop user interface. Previously, accessing these required third-party tools like Tabular Editor. Now, they can be managed natively.   


  • DetailRowsDefinition: This property allows you to customize the drill-through behavior for users who "Show Details" on a pivot table in Excel. By setting this in TMDL, you can control exactly which columns are returned, providing a curated and performant experience that was previously only possible with external tools.   


  • IsPrivate and IsAvailableInMDX: You can set the IsPrivate property on a table to true to hide it from client tools, which is useful for intermediate tables that shouldn't be exposed to end-users. Similarly, setting IsAvailableInMDX to false on a column can reduce memory usage, though it makes the column inaccessible to MDX-based queries like Analyze in Excel.   


  • Perspectives and Cultures: Features like perspectives, which are essential for the "Personalize Visuals" feature, and cultures (translations) for creating multilingual reports, lack a graphical interface in Power BI Desktop. TMDL View provides a direct, code-based way to create and manage them. 1    




Connecting Power BI to Developer Tools

The real breakthrough for me was connecting the TMDL view to the broader world of developer tools like VS Code and GitHub Copilot. The key is to save my work as a Power BI Project file (.pbip).

Doing this changes how your data model is saved. Instead of being a single, complex file, it becomes a folder containing simple, text-based .tmdl files. This file structure is the secret to using professional developer workflows.

While my first attempt to use AI to write TMDL code didn't work out, the process itself was a huge learning experience. (Separately, I had great success using AI with M-code, but that’s a story for another day!)


My AI Experiment: A Learning Experience

I was excited to see if AI could revolutionize my workflow. My first try wasn't a success, but there's a lot to learn from the attempt. Here’s a walkthrough of what happened.


Save as PBIP: I saved my Power BI report as a .pbip file.


Open in VS Code: I opened the entire project folder in VS Code, where I had already installed the TMDL Language extension from Microsoft for syntax highlighting.   


Locate the Script: Inside the \TMDLScripts or \definition folder, I found the calendar_dimension.tmdl file.


Prompt Copilot: After installing the extension in VS Code,


I right-clicked in the editor, started an inline chat with GitHub Copilot, and gave it a precise prompt: "Add calculated column "Quarter Number", and use QUARTER() DAX function.".   




Review and Accept: Copilot immediately suggested the exact lines of code to add to the TMDL script. I reviewed its suggestion, saw it was NOT correct, but clicked "Accept", and saved it to see what would happen.



Apply in Power BI: I saved the file in VS Code, then reopened the .pbip file in Power BI Desktop. The TMDL View showed the modified script. I clicked the "Apply" button.


An error was displayed.

In my previous blog post, https://jihwankimcscp.wixsite.com/supplychainflow/post/leveraging-the-tmdl-view-feature-in-vscode-with-github-copilot-my-experience , the calendar table is created by writing DAX (calculated table), and I think this made easy for AI modifying or adding new columns.


The correct version is shown below; hopefully, AI will soon be able to provide accurate assistance.



Making Power BI Fun with AI

While my attempt in here was a learning curve, it opened my eyes to what's coming next, and it is incredibly exciting. Forget the sci-fi stuff; let's talk about having an AI coding partner right inside my Power BI workflow. This isn't about replacing developers; it's about giving me superpowers to ditch the boring tasks and focus on being creative architects.


Imagine having a tool like GitHub Copilot as my new junior dev—one that never gets tired and loves doing the tedious jobs. Here’s what that actually looks like:

  • My Personal Performance Coach: Instead of hunting for bottlenecks, I could just ask my AI partner to scan my model. It might come back with friendly tips like, "Hey, I noticed this DAX is working way too hard. Here’s a slicker version that will run much faster," or "You could shrink your model size by 15% just by changing this one data type!"

  • A Super-Smart Spellchecker for Your Model: Perhaps, I am the only one on my team who remembers the proper naming conventions? Let the AI be the friendly nudge. It can automatically flag things like, "It looks like this table isn't connected to my main date calendar," or "This is a great measure, but how about we add a quick comment so everyone knows how it works?"

  • The Ultimate Shortcut: The Model-Building Genie: This is where it feels like real magic. I could simply write a prompt like, "Create a basic sales model with tables for products, stores, and daily sales, and add standard MTD/QTD/YTD measures." Copilot could then generate the entire TMDL folder structure, building the foundation for me. I just get to handle the fun, creative parts.


This kind of AI assistance frees us up from the copy-paste grind and endless troubleshooting. It lets me jump straight to what really matters: designing and building robust, scalable, and genuinely impactful data solutions.


Now, you might be wondering what makes this AI-powered future possible. The secret ingredient is TMDL. It’s the key that unlocks the Power BI "black box." By saving my work as a Power BI Project (.pbip), I transform that one giant, mysterious .pbix file into a clean folder of human-readable text files. It's like finally being able to pop the hood of my car to see how everything works.

This is what allows me (and my AI partner) to get in there and work magic. It opens the door to using professional tools like Git, which means my whole team can collaborate on a single model without the classic "who has the latest version?!" panic. It paves the way for automating tests and deployments. In short, it helps Power BI development grow up. The journey is just beginning, and this transformation makes building things with data more creative and efficient than ever before.


I hope this helps having more fun in your journey with modern Power BI development.

1 Comment


Api Connects
Api Connects
18 hours ago

API Connects is a leading IT firm in New Zealand, specializing in IoT development, IoT solutions, and data engineering services. We provide cutting-edge IoT solutions to enhance business operations and data engineering services for seamless data migration and optimization. Our expert DevOps team ensures secure core banking data migration for financial institutions. Visit- https://apiconnects.co.nz/iot-development-testing-consulting/ , https://apiconnects.co.nz/data-engineering-services/ 

Like
bottom of page