{"id":107030,"date":"2025-07-03T02:09:10","date_gmt":"2025-07-03T02:09:10","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=107030"},"modified":"2025-07-14T08:25:12","modified_gmt":"2025-07-14T08:25:12","slug":"13-things-i-wish-i-knew-about-power-query","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/business-intelligence\/13-things-i-wish-i-knew-about-power-query\/","title":{"rendered":"13 Things I wish I knew about Power Query (when I first started)"},"content":{"rendered":"\n<p>When I first started with Power Query, it was in Excel, through the Power Pivot feature. I was amazed at how I could transform data with just a few clicks and quickly create PivotTables. Then, when Power Query appeared in Power BI, I began working with larger data sources and more complex projects.<\/p>\n\n\n\n<p>Through many trials and tribulations, I learned the capabilities of Power Query and the M language (the functional language that actually transforms our data), as well as its idiosyncrasies. Unsurprisingly, with Power BI adoption and rapid growth, many newcomers are learning the same lessons I did.<\/p>\n\n\n\n<p>Some consider this a rite of passage, and I admit I had that view for years. But after managing projects and teams, I realized I was doing a disservice to both my colleagues and our customers by not sharing these learnings earlier. The strength of our society lies in shared learning.<\/p>\n\n\n\n<p>With that in mind, here are the top lessons I give Power Query newcomers to help them avoid the mistakes of my past.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-1-power-query-is-case-sensitive\">1. Power Query is Case Sensitive<\/h2>\n\n\n\n<p>This one will catch you off guard. Whether you\u2019re merging two text columns, using Text.Contains, or performing a Find and Replace, case sensitivity matters. If you don\u2019t account for lowercase versus uppercase, you\u2019ll likely introduce errors into your model.<\/p>\n\n\n\n<p style=\"padding-right:0;padding-left:var(--wp--preset--spacing--md)\">For example, replacing \u201chello\u201d with \u201cGood Morning\u201d in Figure 1 below doesn\u2019t replace the text in the second row as anticipated.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"751\" height=\"121\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-ai-generated-content-m.png\" alt=\"A screenshot of a computer\n\nAI-generated content may be incorrect.\" class=\"wp-image-107031\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-ai-generated-content-m.png 751w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-ai-generated-content-m-300x48.png 300w\" sizes=\"auto, (max-width: 751px) 100vw, 751px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-sm-font-size\">Figure 1 \u2013 Default Find &amp; Replace that doesn\u2019t account for case sensitivity<\/p>\n\n\n\n<p>The low-code UI doesn\u2019t give you the option on case insensitivity, so it creates this M code:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"font-size:14 lang:tsql highlight:0 decode:true block\">Table.ReplaceValue(#\"Added Custom\",\"hello\",\"Good Morning\",Replacer.ReplaceText,{\"Column A\"})<\/pre><\/div>\n\n\n\n<p>So, to make it case insensitive you need to change the M code to this:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">#\"Replaced Value\" = Table.ReplaceValue(\n    #\"Added Custom\",\n    each [Column A],\n    each Text.Combine(\n      List.ReplaceMatchingItems(\n        Text.Split([Column A], \" \"),\n        {{\"hello\", \"Good Morning\"}},\n        Comparer.OrdinalIgnoreCase\n      ),\n      \" \"\n    ),\n    Replacer.ReplaceText,\n    {\"Column A\"}\n)<\/pre><\/div>\n\n\n\n<p>This increases the complexity of the M code, but will properly replace words \u201chello\u201d, \u201cHello\u201d, or \u201cHeLLo\u201d and replace it with the word \u201cGood Morning\u201d.<\/p>\n\n\n\n<p>Keep case sensitivity in mind whenever using text replaces or if you\u2019re using other functions like <code>Text.Contains<\/code> or <code>Text.StartsWith<\/code>.<\/p>\n\n\n\n<p>Credit to <a href=\"https:\/\/gorilla.bi\/power-query\/replace-values\/&quot; \\l &quot;case-insensitive-bulk-replace-sentences\">Rick De Groot<\/a> for teaching me this one.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-2-sort-and-remove-duplicates\">2. Sort and Remove Duplicates<\/h2>\n\n\n\n<p>With timestamped data, I\u2019ve often seen users sort by timestamp and then remove duplicates based on an ID column. However, due to how Power Query streams data during refresh, it won\u2019t retain that sort order unless you explicitly preserve it.<\/p>\n\n\n\n<p>Use <code>Table.Buffer<\/code> to wrap your <code>Table.Sort<\/code> step and ensure the sorted table is held in memory before applying <code>Table.Distinct<\/code>.<\/p>\n\n\n\n<p>Before:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">#\"Sorted Rows\" = Table.Sort(#\"Changed Type\",{{\"Timestamp\", Order.Ascending}}),\n\n#\"Removed Duplicates\" = Table.Distinct(#\"Sorted Rows\", {\"ID\"})<\/pre><\/div>\n\n\n\n<p>After:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">#\"Sorted Rows\" = Table.Sort(#\"Changed Type\",{{\"Timestamp\", Order.Ascending}}),\n    TableBuffer = Table.Buffer(#\"Sorted Rows\",BufferMode.Delayed),\n#\"Removed Duplicates\" = Table.Distinct(#\"Sorted Rows\", {\"ID\"})<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-3-no-regular-expressions-support\">3. No Regular Expressions Support<\/h2>\n\n\n\n<p>Unlike many languages, Power Query (M) doesn&#8217;t support regular expressions. If you&#8217;re used to extracting or cleaning multiline text using regex, you&#8217;ll need to use alternative options (outside of Power Query). Fabric Notebooks have this capability with <code>pyspark.sql.functions.regexp<\/code>, so that is alternative is you have access to Microsoft Fabric.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-4-merges-are-expensive\">4. Merges are Expensive<\/h2>\n\n\n\n<p>Merge steps can significantly slow down development, especially with large datasets, because they require scanning entire tables. Ideally, place merges later in your query. The less processing you do after them, the faster your development will be.<\/p>\n\n\n\n<p>In addition, you can apply these best practices to lower the cost of merge operations:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li> Reduce columns before merging to increase performance. <\/li>\n\n\n\n<li> Use <code>Table.AddKey<\/code> to create an index to improve merge performance. <\/li>\n\n\n\n<li> If needed, use a parameter like <code>Is_Development = true<\/code> to limit rows during development. Set it to false before publishing. <\/li>\n<\/ul>\n<\/div>\n\n\n<p>Credit to <a href=\"https:\/\/blog.crossjoin.co.uk\/2020\/05\/31\/optimising-the-performance-of-power-query-merges-in-power-bi-part-1\/\">Chris Webb<\/a> for his great content on this topic.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-5-rounding-numbers-isn-t-what-you-expect\">5. Rounding Numbers Isn\u2019t What You Expect<\/h2>\n\n\n\n<p><code>Number.Round<\/code> doesn\u2019t follow traditional rounding rules. By default, it uses <a href=\"https:\/\/wiki.c2.com\/?BankersRounding\">Bankers Rounding<\/a>. This means that when two numbers are the same difference from two integers, it will favor the nearest even integer.<\/p>\n\n\n\n<p>So in Figure 2, you\u2019d expect 24.5 to round to 25 if you\u2019re rounding to the nearest whole number by using <code>Number.Round([Value],0)<\/code>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"333\" height=\"102\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-ai-generated-content-m-1.png\" alt=\"A screenshot of a computer\n\nAI-generated content may be incorrect.\" class=\"wp-image-107032\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-ai-generated-content-m-1.png 333w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-ai-generated-content-m-1-300x92.png 300w\" sizes=\"auto, (max-width: 333px) 100vw, 333px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-sm-font-size\">Figure 2 \u2013 Number.Round with Bankers Round<\/p>\n\n\n\n<p>If you wish numbers to round in the \u201cnormal way\u201d, meaning they always round up when they end in .5, you would need to update the <code>Number.Round<\/code> function to be:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">Number.Round([Value], 0, RoundingMode.AwayFromZero)<\/pre><\/div>\n\n\n\n<p>As result, the rounding to the nearest whole number works as expected.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"319\" height=\"93\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-ai-generated-content-m-2.png\" alt=\"A screenshot of a computer\n\nAI-generated content may be incorrect.\" class=\"wp-image-107033\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-ai-generated-content-m-2.png 319w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-ai-generated-content-m-2-300x87.png 300w\" sizes=\"auto, (max-width: 319px) 100vw, 319px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Figure 3 \u2013 Rounding fixed<\/p>\n\n\n\n<p>Credit to <a href=\"https:\/\/solveandexcel.ca\/2021\/03\/09\/rounding-in-power-query-default-rounding-mode-and-the-binary-decimal-conversion-issue-in-excel\/\">Celia Alves<\/a> for teaching me this aspect of Power Query.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-6-parameters-should-not-be-any-type\">6. Parameters Should Not Be &#8216;Any&#8217; Type<\/h2>\n\n\n\n<p>Parameters are a powerful way to make your models more flexible, especially when moving from development to production environments. But here\u2019s the issue: if your parameter is of type <code>Any<\/code>, it cannot be updated in the Power BI Service. There is nothing more frustrating that finishing your work, publishing to the Power BI Service, going to update a parameter and have the parameter disabled. It\u2019s never convenient and you have to update the model and publish the changes again.<\/p>\n\n\n\n<p>Always set parameters like URLs or server names to type Text (see Figure 4) if you plan to change them after publishing.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"330\" height=\"334\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-4.png\" alt=\"\" class=\"wp-image-107034\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-4.png 330w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-4-296x300.png 296w\" sizes=\"auto, (max-width: 330px) 100vw, 330px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-sm-font-size\">Figure 4 \u2013 Example of setting a parameter as Text<\/p>\n\n\n\n<p>As a result, you can set value in the Power BI service versus getting a disabled input field (see Figure 5)<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"433\" height=\"196\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-ai-generated-content-m-3.png\" alt=\"A screenshot of a computer\n\nAI-generated content may be incorrect.\" class=\"wp-image-107035\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-ai-generated-content-m-3.png 433w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-screenshot-of-a-computer-ai-generated-content-m-3-300x136.png 300w\" sizes=\"auto, (max-width: 433px) 100vw, 433px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-sm-font-size\">Figure 5 \u2013 Remember to set your parameters as Text instead of the default value of Any.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-7-enable-load-vs-include-in-refresh\">7. Enable Load vs. Include in Refresh<\/h2>\n\n\n\n<p>Right-click on a table in Power Query and the options shown in Figure 6 can be quite confusing:<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"195\" height=\"42\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-6.png\" alt=\"\" class=\"wp-image-107036\"\/><\/figure>\n\n\n\n<p><br> <br>Figure 6 \u2013 Confusing Options?<\/p>\n\n\n\n<p>Both options can be checked or unchecked independently. Here\u2019s what each one does:<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table class=\"has-fixed-layout\"><thead><tr><th><p><strong>Option<\/strong><\/p><\/th><th><p><strong>Description<\/strong><\/p><\/th><\/tr><\/thead><tbody><tr><td><p><strong>Enable Load (Unchecked)<\/strong><\/p><\/td><td><p>The query runs but does not appear in the model. Useful for intermediate steps.<\/p><\/td><\/tr><tr><td><p><strong>Enable Load (Checked)<\/strong><\/p><\/td><td><p>The query runs and appears in the data model for reporting.<\/p><\/td><\/tr><tr><td><p><strong>Include in Refresh (Unchecked)<\/strong><\/p><\/td><td><p>The query is excluded from refresh operations. Useful for static reference data.<\/p><\/td><\/tr><tr><td><p><strong>Include in Refresh (Checked)<\/strong><\/p><\/td><td><p>The query is included for refresh operations and will pull data from sources when a refresh operation is conducted.<\/p><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-8-web-contents-should-use-relative-paths\">8. Web.Contents Should Use Relative Paths<\/h2>\n\n\n\n<p>If you&#8217;re using <code>Web.Contents<\/code> to access an API, avoid hardcoding the entire URL for every call. Each hardcoded call creates a separate connection, which becomes difficult to manage.<\/p>\n\n\n\n<p>For example, two different tables would each have these functions:<\/p>\n\n\n<div class=\"block-core-list\">\n<ol class=\"wp-block-list\">\n<li><code>Web.Contents(\"https:\/\/x.sharepoint.com\/_api\/web\")<\/code> <\/li>\n\n\n\n<li><code>Web.Contents(\"https:\/\/x.sharepoint.com\/_api\/list\")<\/code> <\/li>\n<\/ol>\n<\/div>\n\n\n<p>This creates multiple data sources to manage as shown in Figure 7.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"511\" height=\"229\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-7.png\" alt=\"\" class=\"wp-image-107037\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-7.png 511w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-7-300x134.png 300w\" sizes=\"auto, (max-width: 511px) 100vw, 511px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-sm-font-size\">Figure 7 \u2013 Duplicate data source connections to the same source<\/p>\n\n\n\n<p>You can access the tables on the same connection using a parameter named <code>Domain<\/code> and the <code>RelativePath<\/code> Parameter.<\/p>\n\n\n<div class=\"block-core-list\">\n<ol class=\"wp-block-list\">\n<li> Web.Contents(Domain,[RelativePath=&#8221;\/_api\/web&#8221;]) <\/li>\n\n\n\n<li> Web.Contents(Domain,[RelativePath=&#8221;\/_api\/list&#8221;]) <\/li>\n<\/ol>\n<\/div>\n\n\n<p>And now you have one connection to manage as shown in Figure 8.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"517\" height=\"190\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-8.png\" alt=\"\" class=\"wp-image-107038\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-8.png 517w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-8-300x110.png 300w\" sizes=\"auto, (max-width: 517px) 100vw, 517px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-sm-font-size\">Figure 8 \u2013 One connection with the help of RelativePath argument in Web.Contents<\/p>\n\n\n\n<p>This will reduce the need for repeated mouse clicks and credential entries in the service, while also improving the model&#8217;s maintainability by minimizing the number of connections to manage.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-9-the-formula-firewall-error\">9. The Formula.Firewall Error<\/h2>\n\n\n\n<p>Joining data from different domains or APIs often triggers privacy level errors during service refreshes with this hated message in Figure 9. It\u2019s agonizing and you usually see this error once you publish to the service and try to refresh the semantic model.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"514\" height=\"79\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-yellow-background-with-black-text-ai-generated.png\" alt=\"A yellow background with black text\n\nAI-generated content may be incorrect.\" class=\"wp-image-107039\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-yellow-background-with-black-text-ai-generated.png 514w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/a-yellow-background-with-black-text-ai-generated-300x46.png 300w\" sizes=\"auto, (max-width: 514px) 100vw, 514px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>You can read more <a href=\"https:\/\/learn.microsoft.com\/en-us\/power-query\/data-privacy-firewall\">about it here<\/a>, but my advice is to use Gen1 or Gen2 Dataflows to bring in data from each source, then join the data in your semantic model. This adds a layer of transformation but prescriptively identifies the sources you wish to join and avoids this error message.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-10-too-many-api-calls-slow-you-down\">10. Too Many API Calls Slow You Down<\/h2>\n\n\n\n<p>When chaining API calls, clicking each step in the interface can trigger a fresh API request, which significantly slows development.<\/p>\n\n\n\n<p>Solutions:<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-use-a-parameter-to-limit-api-responses-while-developing\">Use a parameter to limit API responses while developing. <\/h3>\n\n\n\n<p>Create a parameter that acts as a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Feature_toggle\">feature toggle<\/a> to indicate whether the environment is in development. When enabled, it should limit the number of records ingested to streamline testing and development. For example, create a parameter IsDevelopment (shown in Figure 9)<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"565\" height=\"84\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-10.png\" alt=\"\" class=\"wp-image-107040\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-10.png 565w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-10-300x45.png 300w\" sizes=\"auto, (max-width: 565px) 100vw, 565px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-sm-font-size\">Figure 9 \u2013 IsDevelopment parameter<\/p>\n\n\n\n<p>Then add this step prior to making API calls to limit rows.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">if IsDevelopment then Table.FirstN(#\"Prior Step\",10) else #\"Prior Step\"<\/pre><\/div>\n\n\n\n<p>When <code>IsDevelopment<\/code> is set to <code>TRUE<\/code>, only 10 rows are returned, otherwise all rows are returned.<\/p>\n\n\n\n<p>This will save you hours of waiting for Power Query processing if you reduce the number of rows while developing.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\" id=\"h-storing-raw-api-data-in-power-bi-dataflows\">Storing raw API data in Power BI dataflows<\/h3>\n\n\n\n<p>You could also follow a Medallion architecture by storing raw API data in a Power BI dataflow, then joining and transforming it in your semantic model.<\/p>\n\n\n\n<p>This keeps the semantic model from making the API calls because it\u2019s been handled by the dataflow.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-12-name-and-comment-your-steps-clearly\">12. Name and Comment Your Steps Clearly<\/h2>\n\n\n\n<p>A professor once told me, &#8220;Commenting your code is like cleaning your guest bathroom. It\u2019s a hassle, but others will appreciate it.&#8221;<\/p>\n\n\n\n<p>When creating steps, use clear names like &#8220;Added Fiscal Year Column&#8221; instead of &#8220;Added Custom Column 10.&#8221; Even if you work alone, this makes revisiting your own work weeks later much easier.<\/p>\n\n\n\n<p>For example, would you prefer working with the Applied Steps on the left-side in Figure 10 or the right-side in Figure 10.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"376\" height=\"576\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-11.png\" alt=\"\" class=\"wp-image-107041\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-11.png 376w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-11-196x300.png 196w\" sizes=\"auto, (max-width: 376px) 100vw, 376px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"364\" height=\"568\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-12.png\" alt=\"\" class=\"wp-image-107042\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-12.png 364w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-12-192x300.png 192w\" sizes=\"auto, (max-width: 364px) 100vw, 364px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p class=\"has-sm-font-size\">Figure 10 Example step names<\/p>\n\n\n\n<p>GitHub Copilot can even help generate helpful comments and rename steps automatically. Here is a prompt I use.<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"wrap:true lang:tsql highlight:0 decode:true block\">You are an assistant to help Power Query developers comment their code. Please update each line of code by performing the following:\nInsert a comment above the code explaining what that piece of code is doing.\nDo not start the comment with the word Step or a number\nDo not copy code into the comment.\nKeep the comments to a maximum of 225 characters.\nPlease also update each line of code by performing the following:\n1) Update the variable name explaining what that piece of code is doing.\n2) The variable name should always start with a verb in the past tense.\n3) The variable name should have spaces between words.\n4) Please keep the variable to a maximum of 50 characters.\n5) The variable name should be wrapped in double quotes and preceded by the '#'<\/pre><\/div>\n\n\n\n<p>It is a very long prompt, but it gives Copilot the details it needs to do some renaming for you (especially when you get code that has not been named and commented by the original programmer.. whether that is another programmer\u2026 or you.)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-12-scrolling-to-find-columns-wastes-time\">12. Scrolling to Find Columns Wastes Time<\/h2>\n\n\n\n<p>Sometimes it is the little tips that save you more time than you might expect. When you are searching for a column in a table, you don\u2019t need to scroll and hunt for the name in a list. Power Query includes a &#8220;Go to Column&#8221; feature (see Figure 11).<\/p>\n\n\n\n<p>When I realized this myself, it has saved me a lot more time than I expected. Now, in meetings and screenshares, I can\u2019t tell you how it pains me to see folks struggle to find a column with a 20-column table. Use the \u201cGo to Column\u201d feature instead of scrolling through dozens of columns. It&#8217;s a simple feature that saves a lot of time.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img loading=\"lazy\" decoding=\"async\" width=\"694\" height=\"232\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-13.png\" alt=\"\" class=\"wp-image-107043\" srcset=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-13.png 694w, https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2025\/06\/word-image-107030-13-300x100.png 300w\" sizes=\"auto, (max-width: 694px) 100vw, 694px\" \/><\/figure>\n\n\n\n<p><\/p>\n\n\n\n<p>Figure 11 \u2013 Use the \u201cGo to Column\u201d<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-13-don-t-struggle-alone-learn-from-the-pros\">13. Don\u2019t Struggle Alone\u2026Learn from the Pros<\/h2>\n\n\n\n<p>You don\u2019t need to reinvent the wheel. Many Power Query experts have shared solutions to common problems. The Power BI community is strong, don\u2019t feel like you have to come up with something first. Bookmark and leverage their content:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/bengribaudo.com\/\">Ben Gribaudo<\/a> <\/li>\n\n\n\n<li><a href=\"https:\/\/www.thebiccountant.com\/about\/\">Imke Feldmann<\/a> <\/li>\n\n\n\n<li><a href=\"https:\/\/blog.crossjoin.co.uk\/\">Chris Webb<\/a> <\/li>\n\n\n\n<li><a href=\"https:\/\/gorilla.bi\/about\/\">Rick De Groot<\/a> <\/li>\n\n\n\n<li><a href=\"https:\/\/datawithdom.com\/author\/draimato\/\">Dominick Raimato<\/a> <\/li>\n\n\n\n<li><a href=\"https:\/\/itsnotaboutthecell.com\/\">Alex Powers<\/a> <\/li>\n<\/ul>\n<\/div>\n\n\n<p>(Note: I don\u2019t claim to be an expert-I just have experience knowing who might have the answer.)<\/p>\n\n\n\n<p>And if you can\u2019t find it from them, you can always reach out to the active <a href=\"https:\/\/www.reddit.com\/r\/PowerBI\/\">Reddit group<\/a> for ideas.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-summary\">Summary<\/h2>\n\n\n\n<p>Those are the 13 things I wish I knew about Power Query early in my career with Power Pivot\/Power BI. What things do you wish you knew? Share in the comments, so others can benefit from your knowledge.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When I first started with Power Query, it was in Excel, through the Power Pivot feature. I was amazed at how I could transform data with just a few clicks and quickly create PivotTables. Then, when Power Query appeared in Power BI, I began working with larger data sources and more complex projects. Through many&#8230;&hellip;<\/p>\n","protected":false},"author":344919,"featured_media":107044,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[159160,53],"tags":[],"coauthors":[159224],"class_list":["post-107030","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-business-intelligence","category-featured"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/107030","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/344919"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=107030"}],"version-history":[{"count":4,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/107030\/revisions"}],"predecessor-version":[{"id":107050,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/107030\/revisions\/107050"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/107044"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=107030"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=107030"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=107030"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=107030"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}