{"id":1537,"date":"2025-11-29T14:36:18","date_gmt":"2025-11-29T12:36:18","guid":{"rendered":"https:\/\/www.flip-design.de\/?p=1537"},"modified":"2025-11-29T14:36:18","modified_gmt":"2025-11-29T12:36:18","slug":"accelerating-power-bi-development-with-tmdl-faster-consistent-and-scalable-reporting","status":"publish","type":"post","link":"https:\/\/www.flip-design.de\/?p=1537","title":{"rendered":"Accelerating Power BI Development with TMDL: Faster, Consistent, and Scalable Reporting"},"content":{"rendered":"\n<p>With TMDL (Tabular Model Definition Language), model creation can be carried out faster and in a more standardized way by storing code definitions as scripts. For example, a frequently required date dimension can be stored as a script with all fields and attributes needed for implementation. This allows the table to be created simply by executing the script.<\/p>\n\n\n\n<p>In this entry, I demonstrate how quickly and easily you can use TMDL to create a date table and a calculation group around a fact table, based on a simple measure. This enables you to save time by generating the relevant measures with just a few clicks.<\/p>\n\n\n\n<p>Okay, let&#8217;s take a look at the &#8222;data model&#8220;:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image.png\"><img decoding=\"async\" loading=\"lazy\" width=\"940\" height=\"505\" src=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image.png\" alt=\"\" class=\"wp-image-1538\" srcset=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image.png 940w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-300x161.png 300w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-768x413.png 768w\" sizes=\"(max-width: 940px) 100vw, 940px\" \/><\/a><\/figure>\n\n\n\n<p>Currently, there is only a sales table, and a corresponding dimension references this facts table. Additionally, there is a spreadsheet containing relevant key figures. This spreadsheet contains only one simple key figure with the following code:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Sum Rev = SUM(sales&#91;Revenue])<\/code><\/pre>\n\n\n\n<p>This key figure adds a column to display the revenue.<\/p>\n\n\n\n<p>Now we need a date dimension. This dimension should contain the columns required by the organization. Creating this manually would be quite time-consuming and error-prone. Therefore, we can reference a date dimension in TMDL format. You can find a description of how to create such a table with TMDL code at the following link: <a href=\"https:\/\/www.flip-design.de\/?p=1533\">https:\/\/www.flip-design.de\/?p=1533<\/a><\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-1.png\"><img decoding=\"async\" loading=\"lazy\" width=\"940\" height=\"505\" src=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-1.png\" alt=\"\" class=\"wp-image-1539\" srcset=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-1.png 940w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-1-300x161.png 300w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-1-768x413.png 768w\" sizes=\"(max-width: 940px) 100vw, 940px\" \/><\/a><\/figure>\n\n\n\n<p>Since the table is currently empty, the data basis needs to be updated here:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-2.png\"><img decoding=\"async\" loading=\"lazy\" width=\"875\" height=\"836\" src=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-2.png\" alt=\"\" class=\"wp-image-1540\" srcset=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-2.png 875w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-2-300x287.png 300w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-2-768x734.png 768w\" sizes=\"(max-width: 875px) 100vw, 875px\" \/><\/a><\/figure>\n\n\n\n<p>The table containing the facts can then be generated based on this field:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><a href=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-3.png\"><img decoding=\"async\" loading=\"lazy\" width=\"910\" height=\"1024\" src=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-3-910x1024.png\" alt=\"\" class=\"wp-image-1541\" srcset=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-3-910x1024.png 910w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-3-267x300.png 267w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-3-768x864.png 768w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-3.png 940w\" sizes=\"(max-width: 910px) 100vw, 910px\" \/><\/a><\/figure>\n\n\n\n<p>This allows for the creation of simple time visualizations.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-4.png\"><img decoding=\"async\" loading=\"lazy\" width=\"575\" height=\"434\" src=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-4.png\" alt=\"\" class=\"wp-image-1542\" srcset=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-4.png 575w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-4-300x226.png 300w\" sizes=\"(max-width: 575px) 100vw, 575px\" \/><\/a><\/figure>\n\n\n\n<p>To implement the key performance indicators (KPIs) that are frequently needed, a calculation group is a good option. You&#8217;ll find a corresponding TMDL code script below. This script would create a calculation group called Time Intelligence.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>createOrReplace\r\n\r\n    table 'Time Intelligence'\r\n        lineageTag: 00991730-2d3c-46d8-a8c6-2427a67e6684\r\n\r\n        calculationGroup\r\n\r\n            calculationItem Raw = SELECTEDMEASURE()\r\n\r\n            calculationItem MTD = ```\r\n                    CALCULATE( SELECTEDMEASURE(), DATESMTD( 'Dim Date'&#91;Date] ) )\r\n                    \r\n                    ```\r\n\r\n            calculationItem QTD = ```\r\n                    CALCULATE( SELECTEDMEASURE(), DATESQTD( 'Dim Date'&#91;Date] ) )\r\n                    \r\n                    ```\r\n\r\n            calculationItem YTD = ```\r\n                    CALCULATE( SELECTEDMEASURE(), DATESYTD( 'Dim Date'&#91;Date] ) )\r\n                    \r\n                    ```\r\n\r\n            calculationItem PM = ```\r\n                    CALCULATE( SELECTEDMEASURE(), DATEADD( 'Dim Date'&#91;Date], -1, MONTH ) )\r\n                    \r\n                    ```\r\n\r\n            calculationItem PQ = ```\r\n                    CALCULATE( SELECTEDMEASURE(), DATEADD( 'Dim Date'&#91;Date], -1, QUARTER ) )\r\n                    \r\n                    ```\r\n\r\n            calculationItem PY = CALCULATE( SELECTEDMEASURE(), DATEADD( 'Dim Date'&#91;Date], -1, YEAR ) )\r\n\r\n            calculationItem PYTD = ```\r\n                    CALCULATE(\r\n                        SELECTEDMEASURE(),\r\n                        DATESYTD( DATEADD( 'Dim Date'&#91;Date], -1, YEAR ) )\r\n                    )\r\n                    \r\n                    ```\r\n\r\n        column 'Time Intelligence'\r\n            dataType: string\r\n            lineageTag: 791f8c80-4d7b-4dbb-af95-7377fdc5bed4\r\n            summarizeBy: none\r\n            sourceColumn: Name\r\n            sortByColumn: Ordinal\r\n\r\n            annotation SummarizationSetBy = Automatic\r\n\r\n        column Ordinal\r\n            dataType: int64\r\n            formatString: 0\r\n            lineageTag: 583594ac-4aa0-45d4-a8e4-ed7fd29e82e3\r\n            summarizeBy: sum\r\n            sourceColumn: Ordinal\r\n\r\n            annotation SummarizationSetBy = Automatic\r\n<\/code><\/pre>\n\n\n\n<p>If you run this script, you will usually get an error message:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-6.png\"><img decoding=\"async\" loading=\"lazy\" width=\"940\" height=\"505\" src=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-6.png\" alt=\"\" class=\"wp-image-1544\" srcset=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-6.png 940w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-6-300x161.png 300w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-6-768x413.png 768w\" sizes=\"(max-width: 940px) 100vw, 940px\" \/><\/a><\/figure>\n\n\n\n<p>This message simply indicates that the property preventing the creation of implicit measures has not yet been deactivated in the model. This property is typically deactivated when creating calculation groups, but the TMDL Editor cannot yet do this, and the property cannot be configured in the desktop version either. To avoid relying on external programs like the Tabular Editor, it&#8217;s helpful to create a calculation group once and then delete it. This deactivates the property, which applies to the entire model.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-7.png\"><img decoding=\"async\" loading=\"lazy\" width=\"781\" height=\"339\" src=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-7.png\" alt=\"\" class=\"wp-image-1545\" srcset=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-7.png 781w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-7-300x130.png 300w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-7-768x333.png 768w\" sizes=\"(max-width: 781px) 100vw, 781px\" \/><\/a><\/figure>\n\n\n\n<p>Now that this has been confirmed and the new calculation group has been removed, the TMDL script can be run without any problems.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-8.png\"><img decoding=\"async\" loading=\"lazy\" width=\"940\" height=\"505\" src=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-8.png\" alt=\"\" class=\"wp-image-1546\" srcset=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-8.png 940w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-8-300x161.png 300w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-8-768x413.png 768w\" sizes=\"(max-width: 940px) 100vw, 940px\" \/><\/a><\/figure>\n\n\n\n<p>The new calculation group is now available in the model, and corresponding visualizations can be created with it.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-9.png\"><img decoding=\"async\" loading=\"lazy\" width=\"940\" height=\"311\" src=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-9.png\" alt=\"\" class=\"wp-image-1547\" srcset=\"https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-9.png 940w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-9-300x99.png 300w, https:\/\/www.flip-design.de\/wp-content\/uploads\/2025\/11\/image-9-768x254.png 768w\" sizes=\"(max-width: 940px) 100vw, 940px\" \/><\/a><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>With TMDL (Tabular Model Definition Language), model creation can be carried out faster and in a more standardized way by storing code definitions as scripts. For example, a frequently required date dimension can be stored as a script with all &hellip; <a href=\"https:\/\/www.flip-design.de\/?p=1537\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0},"categories":[1],"tags":[],"_links":{"self":[{"href":"https:\/\/www.flip-design.de\/index.php?rest_route=\/wp\/v2\/posts\/1537"}],"collection":[{"href":"https:\/\/www.flip-design.de\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.flip-design.de\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.flip-design.de\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.flip-design.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=1537"}],"version-history":[{"count":1,"href":"https:\/\/www.flip-design.de\/index.php?rest_route=\/wp\/v2\/posts\/1537\/revisions"}],"predecessor-version":[{"id":1548,"href":"https:\/\/www.flip-design.de\/index.php?rest_route=\/wp\/v2\/posts\/1537\/revisions\/1548"}],"wp:attachment":[{"href":"https:\/\/www.flip-design.de\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=1537"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.flip-design.de\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=1537"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.flip-design.de\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=1537"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}