<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Microsoft Fabric on Hat Full of Data</title><link>https://hatfullofdata.blog/categories/microsoft-fabric/</link><description>Recent content in Microsoft Fabric on Hat Full of Data</description><generator>Hugo -- gohugo.io</generator><language>en-gb</language><lastBuildDate>Wed, 11 Feb 2026 17:21:27 +0000</lastBuildDate><atom:link href="https://hatfullofdata.blog/categories/microsoft-fabric/index.xml" rel="self" type="application/rss+xml"/><item><title>Using Variable Library in a Dataflow</title><link>https://hatfullofdata.blog/using-variable-library-in-a-dataflow/</link><pubDate>Wed, 11 Feb 2026 17:21:24 +0000</pubDate><guid>https://hatfullofdata.blog/using-variable-library-in-a-dataflow/</guid><description>&lt;img src="https://hatfullofdata.blog/using-variable-library-in-a-dataflow/cover.png" alt="Featured image of post Using Variable Library in a Dataflow" /&gt;&lt;p&gt;One of the popular low-code tools within Microsoft Fabric is the Gen2 Dataflow. Power BI report builders already know some Power Query. So armed with this knowledge is a popular starting point to load data into Microsoft Fabric. Adding values from the Variable Library in a Dataflow is an obvious plan to make it more future proof and to work better with Deployment pipelines.&lt;/p&gt;
&lt;p&gt;I will confess the first time I tried these I could not get them to work till I read the instructions correctly. So they do work just understand the limitations!&lt;/p&gt;
&lt;h2&gt;Variable Library Series&lt;/h2&gt;
&lt;p&gt;Variable libraries should be part of every project. This post is part of my series to help get you started creating the library and then using the variables and finally seeing your hard work pay back when it comes to deployment pipelines.&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/variable-library/"&gt;Getting started with variable libraries&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/accessing-a-variable-library-in-a-notebook/"&gt;Variable Values in a Fabric Notebook&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/"&gt;Variable Values in a Data Pipeline&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/"&gt;Variable Values in Lakehouse Shortcuts&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;Variable Values in Dataflows&lt;/strong&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href=""&gt;Variable Libraries in Deployment Pipelines&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="scenario"&gt;Scenario
&lt;/h2&gt;&lt;p&gt;For this post we are going to use the scenario of a dataflow query that lists projects. Whilst we are developing the data handling we want to limit the number of rows loaded and in production we will have no limit.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen grab of the steps described in the next paragraph." class="gallery-image" data-flex-basis="379px" data-flex-grow="158" height="430" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-variable-library-in-a-dataflow/image.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;I create the dataflow and then using Keep Rows, I select Keep top rows. In the next dialog I enter 5 and click OK. This results in a table with only 5 rows of data. The number of rows though needs to come from the variable library.&lt;/p&gt;
&lt;h2 id="getting-the-value"&gt;Getting the Value
&lt;/h2&gt;&lt;p&gt;The next step is to get the value from the variable library into the dataflow. We are going to use a new Power Query function for this called &lt;strong&gt;Variable.ValueOrDefault&lt;/strong&gt;. For the first parameter of this function, you need the Variable Library name and a Variable name. Then you combine together in a string.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;$(/**/&amp;lt;Library Name&amp;gt;/&amp;lt;Variable Name&amp;gt;)&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;So for my example the string will be &lt;strong&gt;“$(/**/Finance Variables/Limit)”&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img alt="snapshots of getting the variable value from variable library in a dataflow" class="gallery-image" data-flex-basis="582px" data-flex-grow="242" height="280" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-variable-library-in-a-dataflow/image-1.png" width="680"&gt;&lt;/p&gt;
&lt;blockquote class="alert alert-note"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;📝&lt;/span&gt;
 &lt;span class="alert-title"&gt;Instructions&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;ol&gt;
&lt;li&gt;On the Home ribbon, expand Get data and select Blank query.&lt;/li&gt;
&lt;li&gt;Rename the query to DataRows.&lt;/li&gt;
&lt;li&gt;Then in the formula bar enter in the code below.&lt;/li&gt;
&lt;li&gt;This will return the current value of the variable in the library.&lt;/li&gt;
&lt;/ol&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Variable.ValueOrDefault(&amp;#34;$(/**/Finance Variables/Limit)&amp;#34;,2)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;blockquote class="alert alert-tip"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;💡&lt;/span&gt;
 &lt;span class="alert-title"&gt;Tip&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;The documentation as of publishing this post states it won’t work hence we use the OrDefault function and in this example the default is 2. It does work though, and we can see the answer 8 comes through.&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;h2 id="using-the-variable-value"&gt;Using the Variable Value
&lt;/h2&gt;&lt;p&gt;We’ve got the variable value from the variable library in a dataflow, now we need to use it. In the last line of my project query that limited the query to 5 rows I can replace the 5 with DataRows. I now get 8 rows of data.&lt;/p&gt;
&lt;p&gt;&lt;img alt="screenshot of the data table showing there are only 8 rows of data" class="gallery-image" data-flex-basis="468px" data-flex-grow="195" height="348" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-variable-library-in-a-dataflow/image-2.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;This works as long as we always want to limit the rows, the chances are in production we don’t want to limit, so I add the extra of only limit if DataRows is greater than 0. Here is my new statement, the previous step is call Sorted Rows hence the #”Sorted rows”&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;if DataRows &amp;gt; 0 then Table.FirstN(#&amp;#34;Sorted rows&amp;#34;, DataRows) else #&amp;#34;Sorted rows&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="references-for-variable-library-in-a-dataflow"&gt;References for Variable Library in a Dataflow
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://learn.microsoft.com/en-us/fabric/data-factory/dataflow-gen2-variable-library-integration?wt.mc_id=DX-MVP-5003563" target="_blank" rel="noopener"
 &gt;Microsoft – Use Fabric variable libraries in Dataflow Gen2&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://learn.microsoft.com/en-us/powerquery-m/variable-valueordefault?wt.mc_id=DX-MVP-5003563" target="_blank" rel="noopener"
 &gt;Power Query Reference for Variable.ValueOrDefault&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="conclusion-on-using-variable-library-in-a-dataflow"&gt;Conclusion on using variable library in a dataflow
&lt;/h2&gt;&lt;p&gt;Its great we can bring in the values easily. Its a shame that we can’t use them to control the destination, but that is on the road map for 2026 Q1. I’ll blog about it as soon as it arrives! I highly recommend using my pattern of fetching the value as a query and then referring to that. It will help in debugging etc.&lt;/p&gt;</description></item><item><title>Using a Variable Library in Lakehouse Shortcuts</title><link>https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/</link><pubDate>Mon, 26 Jan 2026 18:43:51 +0000</pubDate><guid>https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/</guid><description>&lt;img src="https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/cover.png" alt="Featured image of post Using a Variable Library in Lakehouse Shortcuts" /&gt;&lt;p&gt;Lakehouse shortcuts are a popular addition to the Fabric set of tools to access data easily without copying it. Using a variable library in lakehouse shortcuts means its easy to point shortcuts to an alternative location. This great for ALM using development, test and production workspaces.&lt;/p&gt;
&lt;h2&gt;Variable Library Series&lt;/h2&gt;
&lt;p&gt;Variable libraries should be part of every project. This post is part of my series to help get you started creating the library and then using the variables and finally seeing your hard work pay back when it comes to deployment pipelines.&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/variable-library/"&gt;Getting started with variable libraries&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/accessing-a-variable-library-in-a-notebook/"&gt;Variable Values in a Fabric Notebook&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/"&gt;Variable Values in a Data Pipeline&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;Variable Values in Lakehouse Shortcuts&lt;/strong&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/using-variable-library-in-a-dataflow/"&gt;Variable Values in Dataflows&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href=""&gt;Variable Libraries in Deployment Pipelines&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="setting-up-the-shortcuts"&gt;Setting Up the Shortcuts
&lt;/h2&gt;&lt;p&gt;Using the standard GUI you have no option to use a variable library values in the setup of the shortcuts. So set up your shortcuts as you normally and make sure they work. For this post I’m using a shortcut to a table in warehouse. (I had a whole barny with lakehouses and schemas and it not working – another post for another time!)&lt;/p&gt;
&lt;p&gt;&lt;img alt="snapshot of a projects shortcut in the explorer pane." class="gallery-image" data-flex-basis="577px" data-flex-grow="240" height="416" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/image-12.png" srcset="https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/image-12_hu_3c99a595335523c2.png 800w, https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/image-12.png 1001w" width="1001"&gt;&lt;/p&gt;
&lt;p&gt;According to the documentation using the rest API also does not allow for the use of variables in the creation of shortcuts.&lt;/p&gt;
&lt;h2 id="viewing-the-options"&gt;Viewing the Options
&lt;/h2&gt;&lt;p&gt;If we select the short cut and click on the 3 dots to expand the menu we can then click on Manage Shortcut. This opens a pan that shows the values behind the shortcut. The values that be populated from a variable library have a Variable drop down, so we can see Target workspace, Target item and Target path.&lt;/p&gt;
&lt;p&gt;&lt;img alt="screenshot of the exploere and manage shortcut panes" class="gallery-image" data-flex-basis="292px" data-flex-grow="121" height="558" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/image-13.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;I only want to populate the workspace and item guids, so I set up a those variables in my variable library. The variables must be set up as strings, they might look like guids but the shortcut demands they are strings. I set the default values to match the current values. When we apply each variables it will check the current values work so it only works if you use the current values.&lt;/p&gt;
&lt;p&gt;&lt;img alt="screenshot of the variable library" class="gallery-image" data-flex-basis="620px" data-flex-grow="258" height="263" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/image-15.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="applying-the-variables"&gt;Applying the Variables
&lt;/h2&gt;&lt;p&gt;Back in the Manage Shortcut pane click on the Variable below the current value to expand that section. Then click on Select variable to open the Select variable dialog. Click on the correct variable and then click Select Variable. This will update the value to come from the variable.&lt;/p&gt;
&lt;p&gt;&lt;img alt="screenshots of clicking on select variable and selecting the right one" class="gallery-image" data-flex-basis="538px" data-flex-grow="224" height="303" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/image-16.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Once you have pointed it to the variable there does not appear to be a method to change back to a hard coded value.&lt;/p&gt;
&lt;h2 id="updating-variable-values"&gt;Updating Variable Values
&lt;/h2&gt;&lt;p&gt;Variable values will get updated, the most common being a different active set being selected. For other artifacts the change will get picked up when they execute or refresh. For shortcuts this is slightly different. You need to force the updating of variables.&lt;/p&gt;
&lt;p&gt;Open the lakehouse and stay in the lakehouse view. On the ribbon the last button is Update all variables. A message will show the updating is taking and finally there will be a notification to say they have been updated.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Updating variable library in lakehouse shortcuts" class="gallery-image" data-flex-basis="228px" data-flex-grow="95" height="682" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/2026-01-26_16-40-32.png" width="648"&gt;&lt;/p&gt;
&lt;p&gt;If one of the shortcut fails in the update please be aware the successful ones will have updated. You do get a notification and an error message that tries to help.&lt;/p&gt;
&lt;p&gt;&lt;img alt="screenshots of updatings the variables" class="gallery-image" data-flex-basis="361px" data-flex-grow="150" height="451" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/2026-01-26_16-58-29.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="conclusion-on-variable-library-in-lakehouse-shortcuts"&gt;Conclusion on Variable Library in Lakehouse Shortcuts
&lt;/h2&gt;&lt;p&gt;I really like that the variable libraries can be accessed directly in the shortcut details, there is no pre-loading. I would prefer that I could change the values and then press apply so that each value isn’t checked individually. My experience in deployment pipelines means I fell foul of not realising I needed to refresh the variable values.&lt;/p&gt;
&lt;h2 id="resources"&gt;Resources
&lt;/h2&gt;&lt;p&gt;Creating Shortcuts – &lt;a class="link" href="https://learn.microsoft.com/en-us/fabric/data-engineering/lakehouse-shortcuts?wt.mc_id=DX-MVP-5003563" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/en-us/fabric/data-engineering/lakehouse-shortcuts&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Microsoft Learn – &lt;a class="link" href="https://learn.microsoft.com/en-us/fabric/onelake/assign-variables-to-shortcuts?wt.mc_id=DX-MVP-5003563" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/en-us/fabric/onelake/assign-variables-to-shortcuts&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Using a Variable Library in a Data Pipeline</title><link>https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/</link><pubDate>Mon, 19 Jan 2026 10:36:26 +0000</pubDate><guid>https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/</guid><description>&lt;img src="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/cover.png" alt="Featured image of post Using a Variable Library in a Data Pipeline" /&gt;&lt;p&gt;You’ve set up your variable pipeline with WorkspaceIDs and LakehouseIDs etc etc Now you want to use that variable library in a data pipeline so we can use the common values and they will behave in a deployment pipeline.&lt;/p&gt;
&lt;h2&gt;Variable Library Series&lt;/h2&gt;
&lt;p&gt;Variable libraries should be part of every project. This post is part of my series to help get you started creating the library and then using the variables and finally seeing your hard work pay back when it comes to deployment pipelines.&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/variable-library/"&gt;Getting started with variable libraries&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/accessing-a-variable-library-in-a-notebook/"&gt;Variable Values in a Fabric Notebook&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;Variable Values in a Data Pipeline&lt;/strong&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/"&gt;Variable Values in Lakehouse Shortcuts&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/using-variable-library-in-a-dataflow/"&gt;Variable Values in Dataflows&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href=""&gt;Variable Libraries in Deployment Pipelines&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="adding-the-variables-to-the-data-pipeline"&gt;Adding the Variables to the Data Pipeline
&lt;/h2&gt;&lt;p&gt;Before you can use the variable library in a data pipeline you need to add the variables. In your data pipeline you need to click on the grey background to bring up the section on the bottom of the screen with Parameters, Variables etc. If you are in a brand new pipeline you need to click on the settings cog first, then it will appear.&lt;/p&gt;
&lt;p&gt;Select the Library Variables section. Then click on +New and the select variable dialog box appears. If you have multiple variable libraries you can select the right one, you can also search for a variable in the top right. Once you select a variable click on Select Variable button to add that variable to the pipeline.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shot showing the Library values section in the pipeline. The the steps to add a variable from a variable library to a data pipelines" class="gallery-image" data-flex-basis="482px" data-flex-grow="201" height="338" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/Variable-Library-003.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Yes you have to add each variable in turn, no multi-select. You can rename the variables but please don’t, name your variables in your library better.&lt;/p&gt;
&lt;h2 id="using-variable-values"&gt;Using Variable Values
&lt;/h2&gt;&lt;p&gt;You can use the variable values anywhere you can use Dynamic Content. Click on the Add Dynamic content link to open the Pipeline expression builder. Click on the three dots to select Library variables. Click on the variable value you want to use to enter in the formula into the expression. Click OK to put the formula back into the box.&lt;/p&gt;
&lt;p&gt;&lt;img alt="screenshot of adding dynamic content to get Variable Values" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="383" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/Variable-Library-004.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;You can use the variable value inside any functions if required.&lt;/p&gt;
&lt;h2 id="using-variables-for-data-connections"&gt;Using Variables for Data Connections
&lt;/h2&gt;&lt;p&gt;When a data pipeline move from a dev workspace to test workspace and then onto production workspace we need to change the details of the connections to the new values. For this post we will use a connection to a Fabric warehouse in a workspace. I want to pull the values from a table in the warehouse using a lookup action.&lt;/p&gt;
&lt;p&gt;I need to create the following variables in the library:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Project_Warehouse_Connection_ID&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Project_Workspace_ID&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Project_Warehouse_ID&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Project_Warehouse_Connection_String&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="connection-ids"&gt;Connection IDs
&lt;/h3&gt;&lt;p&gt;For the connection guid you need to click on the cog on the top bar and select Manage connections and gateways. From the list of connections, find the one you are using. From the three dots menu select settings. The Connection ID will be listed and can be highlighted and copied.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shots of the steps to get a connection ID" class="gallery-image" data-flex-basis="265px" data-flex-grow="110" height="614" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/image-7.png" width="680"&gt;&lt;/p&gt;
&lt;h3 id="workspace-warehouse-and-lakehouse-ids"&gt;Workspace, Warehouse and Lakehouse IDs
&lt;/h3&gt;&lt;p&gt;IDs for most artifacts can be found when it is opened. Be aware groups=workspaces in the url. Lakehouses have 2 IDs, one for the lakehouse and one for the SQL analytics endpoint or lakewarehouse as the url names it. No comment on names to confuse us!&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of the address bar in a browser highlighting the Workspace ID and Warehouse ID" class="gallery-image" data-flex-basis="1833px" data-flex-grow="764" height="89" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/image-8.png" width="680"&gt;&lt;/p&gt;
&lt;h3 id="connection-string"&gt;Connection String
&lt;/h3&gt;&lt;p&gt;The final part needed is the connection string for the warehouse or lakehouse. The easiest way to copy this is to open the lakehouse SQL endpoint or the warehouse and in the bottom left hand corner is a Copy SQL connection string link.&lt;/p&gt;
&lt;p&gt;&lt;img alt="screen shot of the Copy SQL coonnection string link" class="gallery-image" data-flex-basis="716px" data-flex-grow="298" height="189" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/image-9.png" width="564"&gt;&lt;/p&gt;
&lt;p&gt;It can also be found in the lakehouse or warehouse settings under SQL analytics endpoint.&lt;/p&gt;
&lt;h3 id="variable-library"&gt;Variable Library
&lt;/h3&gt;&lt;p&gt;All these values need saving into the Variable Library. I’ve used Guid for the IDs and String for the connection string.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shot of the Finance_Variables variable library with the 4 variables setup." class="gallery-image" data-flex-basis="473px" data-flex-grow="197" height="344" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/image-10.png" width="679"&gt;&lt;/p&gt;
&lt;h2 id="using-the-variables-in-the-activities"&gt;Using the Variables in the Activities
&lt;/h2&gt;&lt;p&gt;We now need to use the variable values from the variable library in a data pipeline activity connection. We start by adding all 4 variables to the library. Note the guids become strings.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shot of the Library variables from the variable library in a data pipeline settings." class="gallery-image" data-flex-basis="549px" data-flex-grow="228" height="297" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/image-11.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;In this post for simplicity I’m using a Lookup activity to just get all the rows from the projects table. So I add a lookup activity and fill in the general details. On the Settings tab I click the drop down for Connection and select Use dynamic content. In the Add dynamic content pane I find Library Variables under the three dots and select FinanceVariables_Warehouse_Connection_ID so it appears in the expression box. Then I click OK for the Connection to now be an expression.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshots of the steps described in the previous paragraph." class="gallery-image" data-flex-basis="398px" data-flex-grow="165" height="410" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/Variable-Library-006.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Once the connection has been populated you can select the connection type, in my case Warehouse. Then the text boxes appear to take the Workspace ID, Warehouse ID and SQL Connection string. They all have a link to Add dynamic content.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="496px" data-flex-grow="206" height="329" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/Variable-Library-007.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;The table drop down can be populated by entering manually or by clicking Refresh. This will open a pane showing the values that are going to be used in the connection. Click OK to start it fetching the list of tables. Once a table is selected if you click Preview data the same pane appears confirming values. Its a great way to test the connection works.&lt;/p&gt;
&lt;p&gt;You now have a variable values from a variable library in a data pipeline activity. Well done!&lt;/p&gt;
&lt;h2 id="conclusion-on-using-a-variable-library-in-a-data-pipeline"&gt;Conclusion on Using a Variable Library in a Data Pipeline
&lt;/h2&gt;&lt;p&gt;I like how simple it is to use the variables and that you get to select the variables needed in this data pipeline. I’d prefer if you could add multiple variables at a time. I like the consitent use of the expression builder so its something we get familiar with.&lt;/p&gt;
&lt;p&gt;I’d also really like it if in lineage view you could see which artifacts are using of the variable library and the impact was also included. Maybe oneday!&lt;/p&gt;
&lt;h2 id="resources"&gt;Resources
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://learn.microsoft.com/en-us/fabric/data-factory/variable-library-integration-with-data-pipelines?wt.mc_id=DX-MVP-5003563" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/en-us/fabric/data-factory/variable-library-integration-with-data-pipelines&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Accessing a Variable Library in a Notebook</title><link>https://hatfullofdata.blog/accessing-a-variable-library-in-a-notebook/</link><pubDate>Mon, 12 Jan 2026 09:34:51 +0000</pubDate><guid>https://hatfullofdata.blog/accessing-a-variable-library-in-a-notebook/</guid><description>&lt;img src="https://hatfullofdata.blog/accessing-a-variable-library-in-a-notebook/cover.png" alt="Featured image of post Accessing a Variable Library in a Notebook" /&gt;&lt;p&gt;This post walks through how to access a variable library in a notebook in Microsoft Fabric. I recommend a Microsoft Fabric project starts by creating a variable library to store the common values different artifacts need and could be changed if a deployment pipeline gets involved. So when we create a notebook we need to be able to use these variables. This means we need load the variable library in a notebook and then get the variable values.&lt;/p&gt;
&lt;h2&gt;Variable Library Series&lt;/h2&gt;
&lt;p&gt;Variable libraries should be part of every project. This post is part of my series to help get you started creating the library and then using the variables and finally seeing your hard work pay back when it comes to deployment pipelines.&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/variable-library/"&gt;Getting started with variable libraries&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;strong&gt;Variable Values in a Fabric Notebook&lt;/strong&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/"&gt;Variable Values in a Data Pipeline&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/"&gt;Variable Values in Lakehouse Shortcuts&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/using-variable-library-in-a-dataflow/"&gt;Variable Values in Dataflows&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href=""&gt;Variable Libraries in Deployment Pipelines&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="connect-to-library"&gt;Connect to Library
&lt;/h2&gt;&lt;p&gt;The first task is to create a variable for the variable library. The notebookutils package includes the functions we need to do this easily. In the code below the variable vl will refer to the variable library that is called “Finance Variables”. This code assumes the notebook is in the same workspace as the library.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Get the Variable library
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vl = notebookutils.variableLibrary.getLibrary(&amp;#34;Finance Variables&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="get-variable-value"&gt;Get Variable Value
&lt;/h2&gt;&lt;p&gt;Once we have the variable library loaded, we can access the variable values in one of two syntaxes.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 2 syntaxes to get variable value
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SP_URL = vl.getVariable(&amp;#34;SharePoint_URL&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Limit = vl.Limit
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Combining both of the two and adding some print statements we can demo the above using this code.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Get the Variable library
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;vl = notebookutils.variableLibrary.getLibrary(&amp;#34;Finance Variables&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# 2 syntaxes to get variable value
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SP_URL = vl.getVariable(&amp;#34;SharePoint_URL&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Limit = vl.Limit
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Check results
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(f&amp;#34;{SP_URL=}&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(f&amp;#34;{Limit=}&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;And here is the run&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shot of the code loading variable library in a notebook and the results after it ran." class="gallery-image" data-flex-basis="576px" data-flex-grow="240" height="283" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/accessing-a-variable-library-in-a-notebook/image-3.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="get-a-variable-value-by-reference"&gt;Get a variable value by reference
&lt;/h2&gt;&lt;p&gt;There is a third way to get a variable value. The get method from notebookutils variable library uses a reference string that follows the following syntax:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;#34;$(/**/&lt;span class="nt"&gt;&amp;lt;LIBRARY&lt;/span&gt; &lt;span class="err"&gt;NAME&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;/&lt;span class="nt"&gt;&amp;lt;VARIABLE&lt;/span&gt; &lt;span class="err"&gt;NAME&lt;/span&gt;&lt;span class="nt"&gt;&amp;gt;&lt;/span&gt;)&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Before you get excited that the ** implies you could refer to another workspace, sorry that is not supported. This string is used in the variableLibrary.get action in notebookutils. For example to get the two values from before could be done like this&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Get the variable values directly
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;SP_URL = notebookutils.variableLibrary.get(&amp;#34;$(/**/Finance Variables/SharePoint_URL)&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Limit = notebookutils.variableLibrary.get(&amp;#34;$(/**/Finance Variables/Limit)&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;And here is the run&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shot of the code loading variable library in a notebook using references and the results after it ran." class="gallery-image" data-flex-basis="788px" data-flex-grow="328" height="207" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/accessing-a-variable-library-in-a-notebook/image-4.png" width="680"&gt;&lt;/p&gt;
&lt;blockquote class="alert alert-tip"&gt;
 &lt;div class="alert-header"&gt;
 &lt;span class="alert-icon"&gt;💡&lt;/span&gt;
 &lt;span class="alert-title"&gt;Tip&lt;/span&gt;
 &lt;/div&gt;
 &lt;div class="alert-body"&gt;
 &lt;p&gt;The print(f&amp;quot;{Limit=}&amp;quot;) prints Limit=4 for us newbies to Python!&lt;/p&gt;
 &lt;/div&gt;
 &lt;/blockquote&gt;
&lt;h2 id="naming-conventions"&gt;Naming Conventions
&lt;/h2&gt;&lt;p&gt;When you start and there are only 4 variables in the library its easy to remember the names to type in by hand when you are using a variable library in a notebook. When it gets to 20 names, its harder. So create standards, whats the case pattern, you using _ between words or not? Pick a set of rules and stick with it, BronzeWorkspaceID works just as well as Bronze_Workspace_ID, WorkspaceID1 and workspace_id2 are a technical debt you don’t need.&lt;/p&gt;
&lt;h2 id="conclusion-on-using-variable-library-in-a-notebook"&gt;Conclusion on using Variable Library in a Notebook
&lt;/h2&gt;&lt;p&gt;I’m really impressed on how easy it is to use the variable library in a notebook. The pattern is simple and resusable. If I had a magic wand it it would be great is the intellisense knew the variable names from loading the variable library object.&lt;/p&gt;
&lt;p&gt;The method by reference is great if you want to dynamically select which variable to load as the string could be dynamically built.&lt;/p&gt;
&lt;p&gt;Using a combination of parameters and accessing a variable library means reusable notebooks are easier to write. This needs to become part of the best practice pattern being used.&lt;/p&gt;
&lt;h2 id="references"&gt;References
&lt;/h2&gt;&lt;p&gt;Microsoft learn covers Variable library utilities as part of the notebook utilities page.&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://learn.microsoft.com/en-us/fabric/data-engineering/notebook-utilities#variable-library-utilities?wt.mc_id=DX-MVP-5003563" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/en-us/fabric/data-engineering/notebook-utilities#variable-library-utilities&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Microsoft Fabric – Variable Library</title><link>https://hatfullofdata.blog/variable-library/</link><pubDate>Tue, 06 Jan 2026 13:27:41 +0000</pubDate><guid>https://hatfullofdata.blog/variable-library/</guid><description>&lt;img src="https://hatfullofdata.blog/variable-library/cover.png" alt="Featured image of post Microsoft Fabric – Variable Library" /&gt;&lt;p&gt;This post to help you get started creating a variable library. When multiple dataflows, notebooks and pipelines are using the same details to perform tasks it helps if those values are stored in one place. When you move to use deployment pipelines and those values change from your development workspace to your test workspace to your prod, it helps if that is easy. The solution in Microsoft Fabric is a Variable Library to store those common values.&lt;/p&gt;
&lt;h2&gt;Variable Library Series&lt;/h2&gt;
&lt;p&gt;Variable libraries should be part of every project. This post is part of my series to help get you started creating the library and then using the variables and finally seeing your hard work pay back when it comes to deployment pipelines.&lt;/p&gt;
&lt;ol&gt;
 &lt;li&gt;&lt;strong&gt;Getting started with variable libraries&lt;/strong&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/accessing-a-variable-library-in-a-notebook/"&gt;Variable Values in a Fabric Notebook&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/using-a-variable-library-in-a-data-pipeline/"&gt;Variable Values in a Data Pipeline&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/using-a-variable-library-in-lakehouse-shortcuts/"&gt;Variable Values in Lakehouse Shortcuts&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href="https://hatfullofdata.blog/using-variable-library-in-a-dataflow/"&gt;Variable Values in Dataflows&lt;/a&gt;&lt;/li&gt;
 &lt;li&gt;&lt;a href=""&gt;Variable Libraries in Deployment Pipelines&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="create-a-variable-library"&gt;Create a Variable Library
&lt;/h2&gt;&lt;p&gt;This post assumes the workspace is backed with a Fabric capacity. A trial capacity works just fine.&lt;/p&gt;
&lt;p&gt;Either from a Develop task add item or from the Add item button select Variable Library. Enter in a meaningful name for the variable library, letters, numbers and spaces are allowed. Then click the Create button and your new library will be opened. I recommend you create a naming convention that all your Fabric developers like and agree to use.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Creating a Variable library in the workspace" class="gallery-image" data-flex-basis="250px" data-flex-grow="104" height="980" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/variable-library/Variable-Library-001.png" srcset="https://hatfullofdata.blog/variable-library/Variable-Library-001_hu_6eefbd6f398d0d6b.png 800w, https://hatfullofdata.blog/variable-library/Variable-Library-001.png 1024w" width="1024"&gt;&lt;/p&gt;
&lt;h2 id="add-a-variable"&gt;Add a Variable
&lt;/h2&gt;&lt;p&gt;Your library starts empty, so the next task is to add variables. You can create a new variable row by clicking on + New Variable on the Home ribbon. When there are no variables there will also be a green button in the center of the page to create a new variable.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shots of the new variable buttons and the columns Name, Note, Type and Default Value." class="gallery-image" data-flex-basis="482px" data-flex-grow="201" height="338" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/variable-library/image-1.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Enter in a meaningful name and select a data type. A name can only include letters, numbers and underscores. An incorrect name will prevent the library from being saved. Please note some types are not usable in some Fabric artifacts, no I haven’t worked out the logic yet but I’m working on it. Enter in a value for the Default value set. Value sets are used when you are using deployment pipelines for the different values you use development,test and production workspaces. Creating and using variable sets will be covered in another post.&lt;/p&gt;
&lt;h2 id="adding-notes"&gt;Adding Notes
&lt;/h2&gt;&lt;p&gt;So that “future you” doesn’t hate the “current you”, it is worth adding notes to variables to explain the purpose of the variable. This should be part of the best practice rules for Fabric development.&lt;/p&gt;
&lt;p&gt;&lt;img alt="screen grab showing the note button next to the variable name and the Add note to variable dialog box." class="gallery-image" data-flex-basis="290px" data-flex-grow="120" height="562" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/variable-library/image-2.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Click on the icon in the note column. When there is no note it has a plus symbol and when there is a note it has a pencil symbol.&lt;/p&gt;
&lt;h2 id="saving"&gt;Saving
&lt;/h2&gt;&lt;p&gt;Variable libraries do not auto-save. You need to click the save button on home ribbon. Indicators of black dots will show unsaved items you have open and the save button will only be active when there are changes to save.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;I highly recommend starting any Fabric project with creating a variable library. Then everytime a value is used in an artifact such as a database name, key vault name etc a descision is made on if it should be in the variable library or if the value is already there. Some values to be more useful will need to be split across multiple variables.&lt;/p&gt;
&lt;p&gt;It should always be assumed that a workspace with Fabric items will eventually be in a deployment pipeline. This means that it should be coded to make deployment easier. The aim of these articles is for quick reference on how variable libraries are used across all the artifacts.&lt;/p&gt;
&lt;h2 id="references"&gt;References
&lt;/h2&gt;&lt;p&gt;Microsoft have some getting started articles on setting up a variable library and using it in a deployment pipeline.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/en-us/fabric/cicd/variable-library/variable-library-overview?wt.mc_id=DX-MVP-5003563" target="_blank" rel="noopener"
 &gt;Microsoft Learn Variable Libraries&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Microsoft Fabric – Using Copy Job with Dataverse</title><link>https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/</link><pubDate>Thu, 27 Nov 2025 15:35:41 +0000</pubDate><guid>https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/</guid><description>&lt;img src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/cover.png" alt="Featured image of post Microsoft Fabric – Using Copy Job with Dataverse" /&gt;&lt;p&gt;Dataverse is the data store behind parts of Dynamics and lots of Power Platform projects. So Dataverse can contain vital business data that will be needed for reporting. In this post we are going to look at one method which is using copy job with Dataverse to copy across data in Microsoft Fabric.&lt;/p&gt;
&lt;h2 id="table-of-contents"&gt;Table of Contents
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="#scenario" &gt;Scenario&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#first-copy-job-dataverse-connector" &gt;First Copy Job – Dataverse Connector&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#copy-job-run" &gt;Copy Job Run&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#copy-job-using-sql-server-connection" &gt;Copy Job using SQL Server connection&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#i" &gt;Incremental and Merge Running&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#trouble-shooting" &gt;Trouble Shooting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#alternative-options-to-using-copy-job-with-dataverse" &gt;Alternative Options to using Copy Job with Dataverse&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="#conclusion" &gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="scenario"&gt;Scenario
&lt;/h2&gt;&lt;p&gt;For this post we will look at 2 tables, Accounts and Contacts so all the code will be common to any Dataverse environment. I have 5 Account records and 10 Contact records. I also have the environment path org29d4c6d3.crm11.dynamics.com.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shots showing the records in dataverse" class="gallery-image" data-flex-basis="392px" data-flex-grow="163" height="416" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-17.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;In Microsoft Fabric I have a workspace, Finance Reporting, with a Lakehouse, Finance_Lakehouse.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="143px" data-flex-grow="59" height="802" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-18.png" width="479"&gt;&lt;/p&gt;
&lt;h2 id="first-copy-job--dataverse-connector"&gt;First Copy Job – Dataverse Connector
&lt;/h2&gt;&lt;p&gt;Copy Job is a great artifact to move data easily into Fabric. Simplest version just copies data, we can then add incremental and merging. More details can be found here &lt;a class="link" href="https://learn.microsoft.com/en-us/fabric/data-factory/what-is-copy-job?wt.mc_id=DX-MVP-5003563" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/en-us/fabric/data-factory/what-is-copy-job&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;For the first example we will copy from Dataverse using the Dataverse connector. The wizard that walks you through creating a Copy Job has 6 steps. For this first one we will walk through each step.&lt;/p&gt;
&lt;h3 id="create-copy-job"&gt;Create Copy Job
&lt;/h3&gt;&lt;p&gt;Either using a task flow Get Data’s add item or using Add item in the workspace, select Copy job. Type in a name and click Create.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Selecting Copy and naming it as described in the instructions" class="gallery-image" data-flex-basis="600px" data-flex-grow="250" height="272" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-19.png" width="680"&gt;&lt;/p&gt;
&lt;h3 id="choose-data-source"&gt;Choose Data Source
&lt;/h3&gt;&lt;p&gt;Next step is connecting to Dataverse. For this example we are using the Dataverse connector. Click on the Dataverse option under New sources. When the next screen appears enter in the Environment domain. If it is your first time connecting there you will be given the option to name your connection and select a privacy level. It will guess the authentication and login – this is not the blog to discuss options here.&lt;/p&gt;
&lt;p&gt;Once these are done click Next&lt;/p&gt;
&lt;p&gt;&lt;img alt="selecting the dataverse connector and entering details as described in the paragraph above" class="gallery-image" data-flex-basis="222px" data-flex-grow="92" height="732" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-20.png" width="680"&gt;&lt;/p&gt;
&lt;h3 id="choose-data"&gt;Choose Data
&lt;/h3&gt;&lt;p&gt;Choosing the data is very simple, the next screen lists the tables from dataverse using their display names and logical names in brackets. Yes they call them Entities…. No comment. If you expand a table the logical names of fields are listed. There is a search box that will allow you to search for a table using either of the names. If you have selected a table the search will expand to the field names as well. Interestingly for choice columns you only get the code column, not the name column. That is going to be another post!&lt;/p&gt;
&lt;p&gt;If you select a table all the columns will be imported. You select the required columns manually by selecting individual columns, its a touch manual and requires searching and scrolling lots in my experience. Next version is better in my opinion – feel free to scroll down!&lt;/p&gt;
&lt;p&gt;&lt;img alt="Showing table and column selection" class="gallery-image" data-flex-basis="497px" data-flex-grow="207" height="328" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-21.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;When you’ve selected your tables and columns click Next.&lt;/p&gt;
&lt;h3 id="choose-data-destination"&gt;Choose Data Destination
&lt;/h3&gt;&lt;p&gt;Data destination is another easy step. Select your lakehouse from the OneLake catalog.&lt;/p&gt;
&lt;p&gt;&lt;img alt="OneLake catalog" class="gallery-image" data-flex-basis="562px" data-flex-grow="234" height="290" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-22.png" width="680"&gt;&lt;/p&gt;
&lt;h3 id="choose-copy-job-mode"&gt;Choose copy job mode
&lt;/h3&gt;&lt;p&gt;With the dataverse connector you only get one option, Full copy. In the Map to destination you get to choose if that is an append or overwrite.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Full copy - sadly the only option" class="gallery-image" data-flex-basis="877px" data-flex-grow="365" height="186" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-23.png" width="680"&gt;&lt;/p&gt;
&lt;h3 id="map-to-destination"&gt;Map to destination
&lt;/h3&gt;&lt;p&gt;The next screen shows update method and the tables being imported. Clicking on Edit update method will give you the option of Append or Overwrite. Append is the default but this will just duplicate you data every time you run this copy job. I have changed it to Overwrite. Merge is not available in this version.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Map to destination screen highlighting links to Edit update method and the Edit column mappings links" class="gallery-image" data-flex-basis="422px" data-flex-grow="176" height="386" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-24.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;You can enter names for your destination tables and click Edit column mappings to tweak column names or remove some mapping. The columns selected will match the columns you selected back in Choose data.&lt;/p&gt;
&lt;p&gt;Click Next once you are happy.&lt;/p&gt;
&lt;h3 id="review--save"&gt;Review + save
&lt;/h3&gt;&lt;p&gt;The final screen will give you an overview of what the copy job is going to do. You can select if you want it to run now, run once or scheduled. I’m choosing to let it run so I’ll just click Save + run&lt;/p&gt;
&lt;p&gt;&lt;img alt="Save and review screen for the copy job" class="gallery-image" data-flex-basis="463px" data-flex-grow="193" height="352" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-25.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="copy-job-run"&gt;Copy Job Run
&lt;/h2&gt;&lt;p&gt;When a copy job runs such as after saving in the previous steps you can see the execution happening. Each table is listed and when it succeeds you will see how many rows were read and how many were written. In our example read and written are the same.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Run showing using copy job with dataverse" class="gallery-image" data-flex-basis="462px" data-flex-grow="192" height="353" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-26.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Once the run has completed we can go check the Lakehouse and we can see tables. It might need a refresh to show.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Lakehouse showing tables Account_v1 and contact_v1" class="gallery-image" data-flex-basis="493px" data-flex-grow="205" height="331" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-28.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="copy-job-using-sql-server-connection"&gt;Copy Job using SQL Server connection
&lt;/h2&gt;&lt;p&gt;Although the dataverse connector works, the selection of columns is very manual. You also get no option for incremental updates or using merge. So the next example will use SQL Server connector. In a previous post &lt;a class="link" href="https://hatfullofdata.blog/using-sql-on-dataverse-for-power-bi/" target="_blank" rel="noopener"
 &gt;https://hatfullofdata.blog/using-sql-on-dataverse-for-power-bi/&lt;/a&gt; I show how you can use SQL on Dataverse with some great hints from Scott Sewell.&lt;/p&gt;
&lt;p&gt;From that post and with the addition of the modifiedon field here is the SQL for the accounts table. We will use this later.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;span class="lnt"&gt;9
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Select
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	accountid as AccountID,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	name as Account,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	industrycodename as Industry,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; modifiedon,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	statecode,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	statecodename
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	dbo.account
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="new-copy-job-using-sql-server"&gt;New Copy Job using SQL Server
&lt;/h3&gt;&lt;p&gt;Create a copy job as before giving it a name. For the connector select SQL Server. The Server is the environment path as used before, e.g. org29d4c6d3.crm11.dynamics.com. Remember to edit the connection name and privacy level. There is no point adding a Database, it makes no difference. After you press next you need to wait for the database list to load and then select the only database offered.&lt;/p&gt;
&lt;p&gt;&lt;img alt="connecting to" class="gallery-image" data-flex-basis="463px" data-flex-grow="193" height="352" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-27.png" width="680"&gt;&lt;/p&gt;
&lt;h3 id="choose-data-1"&gt;Choose Data
&lt;/h3&gt;&lt;p&gt;The next screen for choosing the data starts by showing you an error. Ignore that, it means you can’t use the interface to select your tables and columns but you can add queries. Expand Queries in the bottom left and click on New query. Type in a name, eg Accounts and then in the query box on the right put in your query. You can check it returns the right data by clicking on preview data.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Creating queries with points highlighted to match the instructions" class="gallery-image" data-flex-basis="508px" data-flex-grow="211" height="321" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-32.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Repeat the above for each of your tables and then click Next.&lt;/p&gt;
&lt;h3 id="incremental-and-merge-setup"&gt;Incremental and Merge setup
&lt;/h3&gt;&lt;p&gt;When you choose your lakehouse in the data destination and move onto the copy job mode screen you now get 2 options, Full copy and Incremental copy. The incremental copy will initially copy everything and then in the future will only copy across changes. In order to recognise which records have changed you need a data time column of when it last changed. Hence we have included the modifiedon column.&lt;/p&gt;
&lt;p&gt;So incremental is only going to process updated or new rows, but what do you want done with those new rows? Append will add the newly updated rows giving you the complete history of each row. Overwrite you will loose rows that have not been modified. Merge is currently in preview but would allow you to update the row that matches on a unique field, e.g. Account Id.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Map to destination screen and the update method screen as described in the instructions" class="gallery-image" data-flex-basis="773px" data-flex-grow="322" height="211" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-30.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Click Incremental and then Next. In the Map to destination screen, click on Edit update method and select Merge and then select the unique id column for each table. When you click next you will be prompted to select the incremental date time column for each table. Click next to the final stage.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Setting up the Incremental columns for each table" class="gallery-image" data-flex-basis="866px" data-flex-grow="361" height="188" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-31.png" width="679"&gt;&lt;/p&gt;
&lt;h3 id="save-review-and-schedule"&gt;Save, Review and Schedule
&lt;/h3&gt;&lt;p&gt;On the final screen not only do you get to save and review but you also get to schedule due to us picking incremental. You can pick repeat by the minute or hourly and pick dates etc. Be aware incremental requires more compute so will consume compute faster than a straight copy but on huge tables the reduced copy will be worth it.&lt;/p&gt;
&lt;p&gt;Select your options and Save and Run&lt;/p&gt;
&lt;h2 id="incremental-and-merge-running"&gt;Incremental and Merge Running
&lt;/h2&gt;&lt;p&gt;The first time we run just as before the rows read and written include all the data. If we go and edit one row in the accounts table and re-run the copy job, only one row is read and written for the accounts table and nothing for the contacts table.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The run history of the initial run showing 10 contacts rows and 5 accounts rows were read and written. And below the second run after a single row in the accounts table was edited in dataverse. It shows one row was read and written in accounts and 0 in contacts." class="gallery-image" data-flex-basis="414px" data-flex-grow="172" height="394" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-33.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="trouble-shooting"&gt;Trouble Shooting
&lt;/h2&gt;&lt;p&gt;In preparation for this post I’ve hit a number of issues.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Although there is a back button in the wizard, going back to the data source and tweaking the queries just breaks the copy job.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;You name a column in the SQL with a space, that update will fail with a weird error. No spaces in column names!&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="alternative-options-to-using-copy-job-with-dataverse"&gt;Alternative Options to using Copy Job with Dataverse
&lt;/h2&gt;&lt;h3 id="link-to-microsoft-fabric"&gt;Link to Microsoft Fabric
&lt;/h3&gt;&lt;p&gt;Using the Link to Microsoft Fabric in Dataverse sounds like a great option. You will be able to add shortcuts in a Lakehouse to the data and it will all be awesome.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Setting up Link to Microsoft Fabric." class="gallery-image" data-flex-basis="441px" data-flex-grow="183" height="370" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-using-copy-job-with-dataverse/image-16.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Just after you select the workspace that the data will go to there are 2 short sentences that you should read carefully.&lt;/p&gt;
&lt;p&gt;“We will link all tables so that you don’t have to choose. You may incur additional charges.”&lt;/p&gt;
&lt;p&gt;I’ll not comment on the “so you don’t have to choose” as I’m not sure I have anything polite to say. That additional storage is in Dataverse which could cost $40 per 1GB per month and with all the tables that could easily become a huge expense, even empty tables take up space. All this so we can have a shortcut in Fabric.&lt;/p&gt;
&lt;p&gt;Platform Guardian blog has a great post to walk you through doing this&lt;a class="link" href="https://platformguardian.blog/2023/11/05/creating-the-dataverse-connector-in-fabric/" target="_blank" rel="noopener"
 &gt;https://platformguardian.blog/2023/11/05/creating-the-dataverse-connector-in-fabric/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Copy Job is one of my favourite Fabric artifacts because they are simple to set up. Editing them is foul so I end up re-building them. Its a brilliant low-code solution to copying across data from dataverse and into a lakehouse. Be aware incremental is going to eat capacity so don’t bother with small tables just do a full copy over writing every time.&lt;/p&gt;
&lt;p&gt;I don’t see any benefit using the dataverse connector except you don’t have to write SQL. A simple select statement is not complex I’m sure an AI prompt somewhere will help you out.&lt;/p&gt;</description></item><item><title>Microsoft Fabric – Direct Lake and User Permissions</title><link>https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/</link><pubDate>Fri, 07 Nov 2025 19:40:06 +0000</pubDate><guid>https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/</guid><description>&lt;img src="https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/cover.png" alt="Featured image of post Microsoft Fabric – Direct Lake and User Permissions" /&gt;&lt;p&gt;Direct Lake is the best way to build a semantic model on data in a Lakehouse or a Warehouse. We can then use Power BI to build reports and possibly even a make a Workspace App to deliver those reports to the business. So what permissions do the business users need to view those reports? This post will explore using Direct Lake and User Permissions to make sure everyone can see data in the reports.&lt;/p&gt;
&lt;h2 id="important"&gt;IMPORTANT
&lt;/h2&gt;&lt;p&gt;This is the simplest method of fixing permissions so someone can view a report using direct lake. If your lakehouse or warehouse contains data they should not have access to this is not the method to use.&lt;/p&gt;
&lt;h2 id="scenario"&gt;Scenario
&lt;/h2&gt;&lt;p&gt;For this post I have built the following :&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Workspace that has a workspace app built and up to date.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Lakehouse_Report connected to a semantic model, Lakehouse_Model, that has a direct lake connection to a lakehouse, Permissions_Demo_Lakehouse&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Warehouse_Report connected to a semantic model, Warehouse_Model, that has a direct lake connection to a lakehouse, Permissions_Demo_Warehouse&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Both the Warehouse and Lakehouse contain one table, Projects with 10 rows of data. Both reports show this in a chart.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img alt="Lineage view of the items described above" class="gallery-image" data-flex-basis="630px" data-flex-grow="262" height="259" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/image.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;I have given one user, Dan, Vistor access to the workspace and I’ve given the Project team security group access to the workspace app.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen grabs showing the permissions as described above." class="gallery-image" data-flex-basis="369px" data-flex-grow="153" height="442" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/image-6.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Both reports work fine for me as the workspace owner. The report is direct lake and user permissions are admin.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="965px" data-flex-grow="402" height="169" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/image-3.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="viewing-reports-as-dan"&gt;Viewing Reports as Dan
&lt;/h2&gt;&lt;p&gt;Viewing the report as Dan is an example of a report that is direct lake and user permission is viewer. Dan can see the warehouse data but he cannot see the lakehouse data.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of the two reports. Lakehouse report shows an error and no chart, warehouse report shows the chart correctly." class="gallery-image" data-flex-basis="947px" data-flex-grow="394" height="172" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/image-4.png" width="679"&gt;&lt;/p&gt;
&lt;h2 id="viewing-workspace-app-as-sam"&gt;Viewing Workspace App as Sam
&lt;/h2&gt;&lt;p&gt;Viewing the report as Sam, who is a member of the Project team security is an example of a reports that are direct lake and user permission is app only. Sam cannot see either the lakehouse or the warehouse report charts.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shots of both reports in the app. Both reports are not showing the chart but are showing an error" class="gallery-image" data-flex-basis="886px" data-flex-grow="369" height="184" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/image-5.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="permissions"&gt;Permissions
&lt;/h2&gt;&lt;p&gt;Whenever data is not coming through for some but not others it is usually an issue with permissions somewhere. Everyone can see the report, they get the headings. The connection is direct lake into the semantic model we need to look at user permissions where the data lives, the lakehouse and the warehouse.&lt;/p&gt;
&lt;p&gt;Each item in the workspace has permissions. By default permissions are inherited from the workspace. There are two fixes to do. The first is Dan’s access to the lakehouse and the second is project team access to both lakehouse and the warehouse.&lt;/p&gt;
&lt;h2 id="fix-dans-lakehouse-access"&gt;Fix Dan’s Lakehouse Access
&lt;/h2&gt;&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="376px" data-flex-grow="157" height="433" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/image-7.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;In the workspace, click on the three dots on the lakehouse. Then from the menu select Manage permissions. This shows a list of the people with access and the Role which gave them that access. We can see Dan has Read and ViewOutput&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="1191px" data-flex-grow="496" height="137" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/image-8.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Read only gives the user permission to connect to the lakehouse, it does not let them see the data. Neither does ViewOutput. I’d love to find documentation as to what ViewOutput allows but I’ve not found it yet. I will update this post when I do.&lt;/p&gt;
&lt;p&gt;Click on the three dots at the end of permissions and select Add ReadAll. Now when Dan looks at the reports the Lakehouse one will work. Sometimes it takes 10-15 minutes for the permissions to work..&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="706px" data-flex-grow="294" height="231" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/image-9.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="fix-sams-access-via-the-workspace-app"&gt;Fix Sam’s Access via the Workspace App
&lt;/h2&gt;&lt;p&gt;Sam gains access to the workspace app through being a member of the Project Team security group. The security group is not mentioned in the permissions of the lakehouse or warehouse. If you go look it is listed in the permissions of the semantic model as App.&lt;/p&gt;
&lt;p&gt;In the lakehouse permissions, click on +Add user. In the Grant people access dialog add the user group or people into the box. Decide if you are emailing them and add a message, I’m not emailing anyone an auto generated email! I have not ticked any of the additional permissions. Then click Grant.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Fixing direct lake and user permissions" class="gallery-image" data-flex-basis="260px" data-flex-grow="108" height="627" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/image-10.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;This will give them Read access. Then as we did for Dan, click on the three dots and click Add ReadAll and this.&lt;/p&gt;
&lt;p&gt;Warehouse permissions are slightly different. Dan has Read and ReadData permissions which gives enough access for him to view the report. So we can use the same process as on the lakehouse and duplicate those permissions. Note that in the Grant people access dialog no additional permissions were ticked.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="390px" data-flex-grow="162" height="418" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/image-11.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;And after a few minutes when Sam refreshes the Workspace App they can see the reports both working.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Workspace app that uses Direct lake and user permissions are fixed" class="gallery-image" data-flex-basis="981px" data-flex-grow="409" height="166" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-direct-lake-and-user-permissions/image-13.png" width="679"&gt;&lt;/p&gt;
&lt;h2 id="note"&gt;Note!
&lt;/h2&gt;&lt;p&gt;The permissions given do mean that if Sam now has access to run SQL against the Warehouse but not the Lakehouse which is behind the semantic model so any row level security in the model will not apply. They do allow Sam to explore the data in both the semantic models.&lt;/p&gt;
&lt;h2 id="resources"&gt;Resources
&lt;/h2&gt;&lt;p&gt;The reason I wrote this blog post was I couldn’t find a resource to show the simple fix of manage permissions. &lt;a class="link" href="https://learn.microsoft.com/en-us/fabric/data-engineering/lakehouse-sharing" target="_blank" rel="noopener"
 &gt;Lakehouse sharing and permission management – Microsoft Fabric | Microsoft Learn&lt;/a&gt; is the closest I got.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Giving someone access to the whole lakehouse or warehouse could be dangerous. This post gives the simplest of fixes assuming the report viewer is allowed to see all the data with a report that is direct lake and user permissions are read only in the workspace or app only.&lt;/p&gt;
&lt;p&gt;With new security features now available we can make the permissions fix more complex requirements. Handling Direct and User permissions needs careful consideration and should be discussed as part of your data governance.&lt;/p&gt;
&lt;h2 id="other-posts-that-might-interest"&gt;Other Posts that might Interest
&lt;/h2&gt;&lt;h2 id="microsoft-fabric-quick-guides"&gt;Microsoft Fabric Quick Guides
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-create-a-lakehouse/" target="_blank" rel="noopener"
 &gt;Create a Lakehouse&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-upload-a-file-and-folder/" target="_blank" rel="noopener"
 &gt;Load CSV file and folder&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-create-table-from-csv-file/" target="_blank" rel="noopener"
 &gt;Create a table from a CSV file&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/" target="_blank" rel="noopener"
 &gt;Create a Table with a Dataflow&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/" target="_blank" rel="noopener"
 &gt;Create a Table using a Notebook and Data Wrangler&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Exploring the SQL End Point&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Power BI Report&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Paginated Report&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Lewis and Laura vs. Notebook and Microsoft Graph: Part 2</title><link>https://hatfullofdata.blog/notebook-and-microsoft-graph-part-2/</link><pubDate>Tue, 26 Aug 2025 13:07:20 +0000</pubDate><guid>https://hatfullofdata.blog/notebook-and-microsoft-graph-part-2/</guid><description>&lt;img src="https://hatfullofdata.blog/notebook-and-microsoft-graph-part-2/cover.png" alt="Featured image of post Lewis and Laura vs. Notebook and Microsoft Graph: Part 2" /&gt;&lt;p&gt;A recent project made me reach out to Lewis Baybutt to scream “Help!, I need help getting with authentication for an Excel file in SharePoint in a Microsoft Fabric Notebook”. Yes all the delights of Excel and SharePoint in one project. So started the battle with understanding authentication, permissions and apparently a Notebook and Microsoft Graph is the way.&lt;/p&gt;
&lt;p&gt;The reason for the project was the original solution was using Gen2 Dataflows and we ran out of capacity. Datameerkat has done a nice summary of comparing Dataflow to Copy Activity to a Notebook, &lt;a class="link" href="https://datameerkat.com/copy-activity-dataflows-gen2-and-notebooks-vs-sharepoint-lists" target="_blank" rel="noopener"
 &gt;https://datameerkat.com/copy-activity-dataflows-gen2-and-notebooks-vs-sharepoint-lists&lt;/a&gt;. Its for lists but the same logic works for files in SharePoint. So for this project we selected the Notebook route.&lt;/p&gt;
&lt;h2 id="final-goal-of-notebook-and-microsoft-graph"&gt;Final Goal of Notebook and Microsoft Graph
&lt;/h2&gt;&lt;p&gt;On a SharePoint site there is an Excel file that contains some data I want to load into a table in a Microsoft Fabric Lakehouse. The Pandas library includes a method called read_excel that can pull the data into a dataframe if it has the file content. And we know how to write a dataframe into table, so the real goal is to get the file content of a file on a SharePoint site.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shot of a SharePoint Library with a few files and screen shot of the Excel file opened showing a " class="gallery-image" data-flex-basis="593px" data-flex-grow="247" height="275" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/notebook-and-microsoft-graph-part-2/image-2.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;We save the details of file name etc into variables to use later.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sharepoint_domain = &amp;#34;YOURDOMAIN.sharepoint.com&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;site_name = &amp;#34;FabricDemo&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;library_name = &amp;#34;Documents&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;file_name = &amp;#34;PandaDemo.xlsx&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;sheet_name = &amp;#34;Demo 1&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="service-principal-permissions-etc"&gt;Service Principal, Permissions Etc
&lt;/h2&gt;&lt;p&gt;The first part of this series is definitely not my skill set, it involved Power Shell! So we agreed he would write the first part and I would write part 2. So Lewis has covered that topic in Part 1 which can be found here &lt;a class="link" href="https://www.lewisdoes.dev/blog/lewis-and-laura-vs-fabric-notebooks-and-microsoft-graph-part-1/" target="_blank" rel="noopener"
 &gt;https://www.lewisdoes.dev/blog/lewis-and-laura-vs-fabric-notebooks-and-microsoft-graph-part-1/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The credentials created in the post should be stored in Azure Key Vault. I wrote a blog post how to do that and another one how to retrieve it into notebook&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/create-azure-key-vault-to-store-id-and-secret/" target="_blank" rel="noopener"
 &gt;https://hatfullofdata.blog/create-azure-key-vault-to-store-id-and-secret/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/get-secret-from-azure-key-vault/" target="_blank" rel="noopener"
 &gt;https://hatfullofdata.blog/get-secret-from-azure-key-vault/&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I created a code block to create three variables, tenant_id, client_id and client_secret. Swap in your TENANT ID etc to make it work for you. The notebookutils library is always loaded in a Microsoft Fabric Notebook.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;span class="lnt"&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Authentication details
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tenant_id = &amp;#34;TENANT ID&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client_id = &amp;#34;CLIENT ID&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Get secret from Key Vault
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azure_key_vault_name = &amp;#34;VAULT NAME&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azure_key_vault_secret_name = &amp;#34;SECRET NAME&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azure_key_vault_url = f&amp;#34;https://{azure_key_vault_name}.vault.azure.net/&amp;#34; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client_secret = notebookutils.credentials.getSecret(azure_key_vault_url,azure_key_vault_secret_name)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="requests-library"&gt;Requests Library
&lt;/h2&gt;&lt;p&gt;This whole post is lots of HTTP get requests made way easier using the Requests library. Documentation for this library can is here &lt;a class="link" href="https://docs.python-requests.org/en/latest/index.html" target="_blank" rel="noopener"
 &gt;Requests: HTTP for Humans™ — Requests 2.32.5 documentation&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;We use two patterns very similar, obviously there is a import requests statement in a previous code block.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;reponse = requests.post(url , data=token_data)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Raise error if request fails
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;response.raise_for_status()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;reponse = requests.get(url , headers=headers)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Raise error if request fails
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;response.raise_for_status()
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="get-access-token"&gt;Get Access Token
&lt;/h2&gt;&lt;p&gt;Before we can use Notebook and Microsoft Graph together we need an access token. For all the requests.get we need headers which includes an access token. So the next task is to get that access token which uses the first pattern from above. If you’ve used the tenant_id, client_id and client_secret variables you can just copy and paste this code into a block&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;span class="lnt"&gt;14
&lt;/span&gt;&lt;span class="lnt"&gt;15
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;token_url = f&amp;#34;https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;token_data = {
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;grant_type&amp;#34;: &amp;#34;client_credentials&amp;#34;,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;client_id&amp;#34;: client_id,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;client_secret&amp;#34;: client_secret,
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &amp;#34;scope&amp;#34;: &amp;#34;https://graph.microsoft.com/.default&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;}
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;response = requests.post(token_url, data=token_data)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;response.raise_for_status() # Raise error if request fails
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;access_token = response.json().get(&amp;#34;access_token&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Print the result
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(&amp;#34; Access Token Received:&amp;#34;, access_token[:50], &amp;#34;...&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;headers = {&amp;#34;Authorization&amp;#34;: f&amp;#34;Bearer {access_token}&amp;#34;}
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The last step is to put the access token into a JSON object called headers which will be used for the next stages.&lt;/p&gt;
&lt;h2 id="getting-the-site-id-and-drive-id"&gt;Getting the Site ID and Drive ID
&lt;/h2&gt;&lt;p&gt;We need the url to download the file content. The request to get that url is&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://graph.microsoft.com/v1.0/sites/%7bsite_id%7d/drives/%7bdrive_id%7d/root:/%7bfile_name%7d:/content" target="_blank" rel="noopener"
 &gt;https://graph.microsoft.com/v1.0/sites/{site_id}/drives/{drive_id}/root:/{file_name}:/content&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;So we need the site_id and the drive_id. Btw drives are document libraries… yeah naming confusion, don’t blame me! We already have the file_name, if its in a folder the name needs to include that.&lt;/p&gt;
&lt;h3 id="site-id"&gt;Site ID
&lt;/h3&gt;&lt;p&gt;Using &lt;a class="link" href="https://graph.microsoft.com/v1.0/sites/%7bsharepoint_domain%7d:/sites/%7bsite_name%7d" target="_blank" rel="noopener"
 &gt;https://graph.microsoft.com/v1.0/sites/{sharepoint_domain}:/sites/{site_name}&lt;/a&gt; with the headers we built earlier in a requests.get we get a json response that includes an id value&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;site_id_url = f&amp;#34;https://graph.microsoft.com/v1.0/sites/{sharepoint_domain}:/sites/{site_name}&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(&amp;#34;Site ID URL:&amp;#34;,site_id_url)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;response = requests.get(site_id_url, headers=headers)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;response.raise_for_status() # Raise error if request fails
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;display(response.json())
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Produces&lt;/p&gt;
&lt;p&gt;&lt;img alt="The response JSON from getting the site JSON showing it has an id field" class="gallery-image" data-flex-basis="943px" data-flex-grow="393" height="173" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/notebook-and-microsoft-graph-part-2/image-4.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;So we then use the following code to get the site_id and print it for debugging.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;site_id=response.json()[&amp;#39;id&amp;#39;]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(&amp;#34;Site ID:&amp;#34;,site_id[:50], &amp;#34;...&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="drive-id"&gt;Drive ID
&lt;/h3&gt;&lt;p&gt;Using &lt;a class="link" href="https://graph.microsoft.com/v1.0/sites/%7bsite_id%7d/drives?$select=name,id" target="_blank" rel="noopener"
 &gt;https://graph.microsoft.com/v1.0/sites/{site_id}/drives?$select=name,id&lt;/a&gt; will give us a list of the document libraries on the site. A site can have more than one library so we need to handle multiple rows being returned. My choice was to save it into dataframe and then filter that to get the result.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;drive_id_url = f&amp;#34;https://graph.microsoft.com/v1.0/sites/{site_id}/drives?$select=name,id&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;response = requests.get(drive_id_url, headers=headers)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;response.raise_for_status() # Raise error if request fails
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Convert response json into a dataframe
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;df_drives = spark.createDataFrame(response.json()[&amp;#39;value&amp;#39;])
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;display(df_drives)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Filter the dataframe to the specified library and get the id
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;drive_id = df_drives.filter(col(&amp;#34;name&amp;#34;)== library_name).collect()[0][&amp;#34;id&amp;#34;]
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(&amp;#34;Drive ID:&amp;#34;,drive_id[:25], &amp;#34;...&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;That gives this output&lt;/p&gt;
&lt;p&gt;&lt;img alt="Table of the drive results showing columns id and name. Followed by a line with Drive ID: then a guid value" class="gallery-image" data-flex-basis="405px" data-flex-grow="169" height="402" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/notebook-and-microsoft-graph-part-2/image-6.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;So now we have the site id and the drive id so now we can get the file content using our Notebook and Microsoft Graph.&lt;/p&gt;
&lt;h2 id="get-the-file-content"&gt;Get the File Content
&lt;/h2&gt;&lt;p&gt;This uses the same pattern as the previous 2 requests, the difference is the path includes /content on the end to indicate we want the content. There is very little we can print out to debug the response as the file contant is binary&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Retrieve the File Content from SharePoint using Graph API
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;file_url = f&amp;#34;https://graph.microsoft.com/v1.0/sites/{site_id}/drives/{drive_id}/root:/{file_name}:/content&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;print(&amp;#34;File URL:&amp;#34;,file_url[:75], &amp;#34;...&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;response = requests.get(file_url, headers=headers)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;response.raise_for_status() # Raise error if request fails
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="pandas-and-file-content"&gt;Pandas and File Content
&lt;/h2&gt;&lt;p&gt;Pandas read_excel method wants a file type to work with. Using BytesIO from io library we can create that. Documentation for BytesIO can be found here &lt;a class="link" href="https://docs.python.org/3/library/io.html" target="_blank" rel="noopener"
 &gt;https://docs.python.org/3/library/io.html&lt;/a&gt;. We can then use read_excel from Pandas library to fetch the data from the sheet. I’ve kept it simple, the tricks on handling more complex data in Excel is for another post.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Import methods
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from io import BytesIO
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;from pandas import read_excel
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Convert response
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xls = BytesIO(response.content)
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Get data from sheet
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;df = read_excel(xls, sheet_name=sheet_name) 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;display(df)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;From the above code we get the following in a panda dataframe ready to save into a table.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Table pulled from the Excel file using Notebook and Microsoft Graph" class="gallery-image" data-flex-basis="502px" data-flex-grow="209" height="325" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/notebook-and-microsoft-graph-part-2/image-7.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="final-notebook"&gt;Final Notebook
&lt;/h2&gt;&lt;p&gt;The complete notebook that could be imported into a Fabric Workspace can be found here &lt;a class="link" href="https://github.com/HatFullOfData/CodeStuff/blob/main/Sample%20Files/Access%20SharePoint%20using%20Microsoft%20Graph.ipynb" target="_blank" rel="noopener"
 &gt;https://github.com/HatFullOfData/CodeStuff/blob/main/Sample%20Files/Access%20SharePoint%20using%20Microsoft%20Graph.ipynb&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Congratulations on getting this far with Notebook and Microsoft Graph. The above looks like hard work when connecting from a Gen2 Dataflow is so much easier. But the saving on capacity usage and the flexibility of a notebook I think gives us more options in the future.&lt;/p&gt;</description></item><item><title>Get Secret from Azure Key Vault in a Microsoft Fabric Notebook</title><link>https://hatfullofdata.blog/get-secret-from-azure-key-vault/</link><pubDate>Thu, 21 Aug 2025 16:33:55 +0000</pubDate><guid>https://hatfullofdata.blog/get-secret-from-azure-key-vault/</guid><description>&lt;img src="https://hatfullofdata.blog/get-secret-from-azure-key-vault/cover.png" alt="Featured image of post Get Secret from Azure Key Vault in a Microsoft Fabric Notebook" /&gt;&lt;p&gt;I’ve recently been working with Notebooks in Microsoft Fabric and have needed to get a credentials information that should be kept secure. The obvious place to store such credentials is Azure Key Vault so now we need to get our secret from there.&lt;/p&gt;
&lt;p&gt;This is a really short post to help me out when I need a fast explanation on projects.&lt;/p&gt;
&lt;h2 id="azure-key-vault-part"&gt;Azure Key Vault Part
&lt;/h2&gt;&lt;p&gt;I’ve previously blogged how to setup a key vault and add a secret – &lt;a class="link" href="https://hatfullofdata.blog/create-azure-key-vault-to-store-id-and-secret/" target="_blank" rel="noopener"
 &gt;https://hatfullofdata.blog/create-azure-key-vault-to-store-id-and-secret/&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;For this post I have a vault called LGB-Secrets and it has a secret called SPConnectorSecret.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screenshot of the Key Vault site showing the list of secrets." class="gallery-image" data-flex-basis="421px" data-flex-grow="175" height="387" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/get-secret-from-azure-key-vault/image.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;The vault URI is &lt;a class="link" href="https://lgb-secrets.vault.azure.net/" target="_blank" rel="noopener"
 &gt;https://lgb-secrets.vault.azure.net/&lt;/a&gt; which can be calculated from the vault name.&lt;/p&gt;
&lt;h2 id="python-to-get-secret-from-azure-key-vault"&gt;Python to Get Secret from Azure Key Vault
&lt;/h2&gt;&lt;p&gt;Notebookutils is a built in package for Microsoft Fabric notebooks. It was previously known as MSSparkUtils. It contains plenty of really useful methods to perform tasks with files, environments and credentials. Microsoft’s documentation can be found at :&lt;/p&gt;
&lt;p&gt;&lt;a class="link" href="https://learn.microsoft.com/en-us/fabric/data-engineering/notebook-utilities#credentials-utilities?wt.mc_id=DX-MVP-5003563" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/en-us/fabric/data-engineering/notebook-utilities#credentials-utilities&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;The method notebookutils.credentials.getSecret requires 2 parameters, vault URI and secret name. This code block looks like this.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azure_key_vault_name = &amp;#34;lgb-secrets&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azure_key_vault_secret_name = &amp;#34;SPConnectorSecret&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;azure_key_vault_url = f&amp;#34;https://{azure_key_vault_name}.vault.azure.net/&amp;#34; 
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;client_secret = notebookutils.credentials.getSecret(azure_key_vault_url,azure_key_vault_secret_name)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The account being used to run the notebook will need access to the key vault.&lt;/p&gt;
&lt;h2 id="reacted"&gt;Reacted!
&lt;/h2&gt;&lt;p&gt;The notebook understands that the value you fetched from the key vault should be kept secure. So if you try to print the client_secret it will not show you the result and will show REDACTED instead.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Showing the result of a print client_secret and shows REDACTED" class="gallery-image" data-flex-basis="511px" data-flex-grow="213" height="319" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/get-secret-from-azure-key-vault/image-1.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;I know this is a very short post, which is a good thing as that means its a simple concept. It is here because I also wanted a short post that contains the code block I want to be able to copy and use easily.&lt;/p&gt;</description></item><item><title>Microsoft Fabric – Create a Data Pipeline with Parameters</title><link>https://hatfullofdata.blog/data-pipeline-with-parameters/</link><pubDate>Thu, 05 Jun 2025 10:26:00 +0000</pubDate><guid>https://hatfullofdata.blog/data-pipeline-with-parameters/</guid><description>&lt;p&gt;One of the skills of creating good solutions on any platform is building reusable modules. For a part to be reusable we reduce the hard coding and pass in parameters. This is true for data pipelines. So this post post covers creating a data pipeline with parameters.&lt;/p&gt;
&lt;h2 id="initial-scenario"&gt;Initial Scenario
&lt;/h2&gt;&lt;p&gt;In order to demonstrate how to create a data pipeline with parameters we need a simple data pipeline as a demo. For this post we are going to use the Star Wars api called SWAPI. The details of the api can be found at &lt;a class="link" href="https://swapi.info/" target="_blank" rel="noopener"
 &gt;https://swapi.info/&lt;/a&gt;. Its a very simple api that allows anonymous connections and returns data in a JSON format.&lt;/p&gt;
&lt;p&gt;In our pipeline we add a copy data activity. For the Source, the connection is a http connection to &lt;a class="link" href="https://swapi.info/api/" target="_blank" rel="noopener"
 &gt;https://swapi.info/api/&lt;/a&gt; and the relative URL is the table name, in this case films. And the file format is JSON.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Filling in the source details of the copy data activity" class="gallery-image" data-flex-basis="850px" data-flex-grow="354" height="192" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/data-pipeline-with-parameters/image.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;For the destination the connection is to a Lakehouse. The Root folder is files with the file path being the table name + .json so in this case films.json. To match the source the file format is JSON.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Filling in the destination details of the copy data activity" class="gallery-image" data-flex-basis="747px" data-flex-grow="311" height="218" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/data-pipeline-with-parameters/image-1.png" width="679"&gt;&lt;/p&gt;
&lt;p&gt;The issue with the above is the “films” is hard coded. If this pipeline is going to be reusable for other tables from this api we need to move the “films” into a parameter.&lt;/p&gt;
&lt;h2 id="adding-parameters-to-the-data-pipeline"&gt;Adding Parameters to the Data Pipeline
&lt;/h2&gt;&lt;p&gt;In the data pipeline click on the grey background around the activities to make sure no activity is selected. In the bottom panel you should now see options including Parameters. Click on the + New to add a parameter. Then add a name, select a type and give a default value.&lt;/p&gt;
&lt;p&gt;&lt;img alt="panel to create Data Pipeline with Parameters" class="gallery-image" data-flex-basis="510px" data-flex-grow="212" height="319" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/data-pipeline-with-parameters/image-2.png" width="679"&gt;&lt;/p&gt;
&lt;p&gt;Multiple parameters can be added. When the data pipeline is run the parameters can be updated. You now have a data pipeline with parameters you just need to use them in activities.&lt;/p&gt;
&lt;h2 id="using-parameters-in-activities"&gt;Using Parameters in Activities
&lt;/h2&gt;&lt;p&gt;We now need to edit the copy data activity to use the TableName parameter rather than the hard coded films. Edit the copy data action and on the source tab clear the Relative URL value. Click on the Add dynamic content or Alt+Shift+D. Then in the panel, under Parameters click the parameter, in this case TableName. This puts the formula in the expression builder. Then click OK to put the expression back into the Relative URL.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Using the parameter value in the Relative URL box" class="gallery-image" data-flex-basis="471px" data-flex-grow="196" height="346" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/data-pipeline-with-parameters/image-5.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;The above example was using the parameter straight. For the file name in the destination we need to concatenate “.json” onto the table name. In the expression builder Functions such as concat can be found in the Functions tab and in the right category group.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Selecting a function from the Functions list in the expression builder" class="gallery-image" data-flex-basis="169px" data-flex-grow="70" height="963" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/data-pipeline-with-parameters/image-6.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;If you know the function name that you want to use there is intellisense and typing in “@conc” will give you a list of matching functions to use.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="549px" data-flex-grow="228" height="297" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/data-pipeline-with-parameters/image-8.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Clicking OK will add the expression to the filename box.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Destination details with an expression in the File Path" class="gallery-image" data-flex-basis="766px" data-flex-grow="319" height="213" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/data-pipeline-with-parameters/image-9.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="testing-the-data-pipeline-with-parameters"&gt;Testing the Data Pipeline with Parameters
&lt;/h2&gt;&lt;p&gt;When the pipeline is run manually a panel appears prompting for the parameter values. Enter in the values and click OK. When the pipeline completes the run successfully we can see in the lakehouse the new file has been created.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="725px" data-flex-grow="302" height="225" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/data-pipeline-with-parameters/image-10.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;I first learnt best programming techniques over 30 years ago. It included concepts I still use and teach today. This is one of them. Of course the pipeline could be more complex, include more parameters and more activities but the concept is still the same, make things reusable by creating data pipeline with parameters.&lt;/p&gt;</description></item><item><title>First refresh it broke!</title><link>https://hatfullofdata.blog/first-refresh-it-broke-laurabrokeit/</link><pubDate>Mon, 12 May 2025 15:57:47 +0000</pubDate><guid>https://hatfullofdata.blog/first-refresh-it-broke-laurabrokeit/</guid><description>&lt;img src="https://hatfullofdata.blog/first-refresh-it-broke-laurabrokeit/cover.png" alt="Featured image of post First refresh it broke!" /&gt;&lt;p&gt;I set up my dataflow and it was working great. Then it broke on the refresh. Here is how I fixed it.&lt;/p&gt;
&lt;h2 id="sharepoint-and-microsoft-fabric"&gt;SharePoint and Microsoft Fabric
&lt;/h2&gt;&lt;p&gt;SharePoint is no database but we keep putting data there so here are my findings and notes from working with SharePoint libraries and lists in Microsoft Fabric.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/sharepoint-folder-into-microsoft-fabric/" target="_blank" rel="noopener"
 &gt;Ingest a SharePoint folder of Excel Files&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/first-refresh-it-broke-laurabrokeit/" target="_blank" rel="noopener"
 &gt;Fixing the broken query&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="previously"&gt;Previously
&lt;/h2&gt;&lt;p&gt;In the previous post we ingested a SharePoint folder into a table in a Lakehouse. That is a well known process and nothing new except for one thing. I split the process into two stages, firstly the FullFileList which contained the list of files and the binary content of the files and then a separate query to combine data from those files. Power Query created Helper queries to perform the combining. Then it broke.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="1371px" data-flex-grow="571" height="119" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/first-refresh-it-broke-laurabrokeit/image-14.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="it-broke"&gt;It Broke
&lt;/h2&gt;&lt;p&gt;It all appears to work fine. Then I try a refresh and it fails. On going back to look at the dataflow I see that there are 2 extra steps in FullFileList that have been added by Microsoft Fabric.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Query steps from the FullFileList Query showing the steps the made it broke" class="gallery-image" data-flex-basis="499px" data-flex-grow="207" height="327" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/first-refresh-it-broke-laurabrokeit/image-15.png" width="680"&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;let
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; Source = SharePoint.Files(&amp;#34;https://lgb123.sharepoint.com/sites/FabricDemo/&amp;#34;, [ApiVersion = 15]),
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; #&amp;#34;Filtered rows&amp;#34; = Table.SelectRows(Source, each [Folder Path] = &amp;#34;https://lgb123.sharepoint.com/sites/FabricDemo/Budgets/&amp;#34;),
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; #&amp;#34;From Value&amp;#34; = Table.FromValue(#&amp;#34;Filtered rows&amp;#34;),
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; #&amp;#34;Remove Columns&amp;#34; = Table.RemoveColumns(#&amp;#34;From Value&amp;#34;, Table.ColumnsOfType(#&amp;#34;From Value&amp;#34;, {type table, type record, type list, type nullable binary, type binary, type function}))
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;in
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; #&amp;#34;Remove Columns&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;The last step Remove Columns, removes all columns of type table, record, list, binary or function. So this removes the Content column that is binary and therefore the queries doing the combine of the Content column all fail. Hence it broke.&lt;/p&gt;
&lt;h2 id="it-broke-in-the-staging"&gt;It Broke in the Staging
&lt;/h2&gt;&lt;p&gt;To improve performance and reliability, Dataflow Gen2 uses staging items to store intermediate data during data transformation&lt;/p&gt;
&lt;p&gt;The above quote is from &lt;a class="link" href="https://learn.microsoft.com/en-us/fabric/data-factory/data-in-staging-artifacts?wt.mc_id=DX-MVP-5003563" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/en-us/fabric/data-factory/data-in-staging-artifacts&lt;/a&gt; It stores the intermediate queries, so FullFileList would have been stored as a table in the staginglakehouse or stagingwarehouse. So Fabric is adding the step to remove the binary column so staging can work.&lt;/p&gt;
&lt;h2 id="turn-off-staging"&gt;Turn Off Staging
&lt;/h2&gt;&lt;p&gt;When I right click on the FullFileList query in the query list the menu includes Enable Staging, by default it is turned on, indicated with a tick. So I click on Enable staging to remove the tick and turn it off. I publish the dataflow and wait. Yes! the refresh works, I test it multiple times.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Turning off enable staging" class="gallery-image" data-flex-basis="232px" data-flex-grow="96" height="623" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/first-refresh-it-broke-laurabrokeit/image-16.png" width="603"&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;I am curious as to how turning off staging will impact the dataflow. So I will be keeping an eye on this one. But this appears to be the fix we need to get it working again for now. I will do my enquiries and retests to see if this is still needed.&lt;/p&gt;</description></item><item><title>SharePoint Folder into Microsoft Fabric</title><link>https://hatfullofdata.blog/sharepoint-folder-into-microsoft-fabric/</link><pubDate>Fri, 09 May 2025 17:08:15 +0000</pubDate><guid>https://hatfullofdata.blog/sharepoint-folder-into-microsoft-fabric/</guid><description>&lt;img src="https://hatfullofdata.blog/sharepoint-folder-into-microsoft-fabric/cover.png" alt="Featured image of post SharePoint Folder into Microsoft Fabric" /&gt;&lt;p&gt;SharePoint folder has been a connector into Power Query for Excel, Power BI Desktop and dataflows for quite a while. This post is to cover the basics before I write another post to explain a more complex scenario. This post will use GEN2 Dataflows in Microsoft Fabric. Power Query can take files on a SharePoint site and from a selected sheet, table or named range append the contents to one big table. This post explains what you should be aware of when doing this.&lt;/p&gt;
&lt;h2 id="sharepoint-and-microsoft-fabric"&gt;SharePoint and Microsoft Fabric
&lt;/h2&gt;&lt;p&gt;SharePoint is no database but we keep putting data there so here are my findings and notes from working with SharePoint libraries and lists in Microsoft Fabric.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/sharepoint-folder-into-microsoft-fabric/" target="_blank" rel="noopener"
 &gt;Ingest a SharePoint folder of Excel Files&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/first-refresh-it-broke-laurabrokeit/" target="_blank" rel="noopener"
 &gt;Fixing the broken query&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="sharepoint-library"&gt;SharePoint Library
&lt;/h2&gt;&lt;p&gt;I have a SharePoint library on a site called Budgets. It contains 3 files which are all the same format, 2 tabs, 1 table and 2 named regions.&lt;/p&gt;
&lt;p&gt;&lt;img alt="SharePoint library containing 3 files." class="gallery-image" data-flex-basis="688px" data-flex-grow="286" height="237" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/sharepoint-folder-into-microsoft-fabric/image.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;The URL to the library is &lt;a class="link" href="https://lgb123.sharepoint.com/sites/FabricDemo/Budgets/Forms/AllItems.aspx" target="_blank" rel="noopener"
 &gt;https://lgb123.sharepoint.com/sites/FabricDemo/Budgets/Forms/AllItems.aspx&lt;/a&gt; . From this I can work out the URL to the SharePoint site is &lt;a class="link" href="https://lgb123.sharepoint.com/sites/FabricDemo/Budgets/" target="_blank" rel="noopener"
 &gt;https://lgb123.sharepoint.com/sites/FabricDemo/Budgets/&lt;/a&gt; You can always test it by making sure the site url takes you to the front page.&lt;/p&gt;
&lt;h2 id="connecting-to-sharepoint-folder"&gt;Connecting to SharePoint Folder
&lt;/h2&gt;&lt;p&gt;In a GEN2 Dataflow, from the Home ribbon select Get Data and then more. If SharePoint folder isn’t showing in the dialog that appears, search for SharePoint. Then select SharePoint folder. Then enter in your site URL. Please note the full library url will not work.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Setting up the SharePoint Folder connector" class="gallery-image" data-flex-basis="494px" data-flex-grow="206" height="330" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/sharepoint-folder-into-microsoft-fabric/image-6.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;If this is the first time you’ve connected to this SharePoint site you will need to set up the connection. All you need to do is change the Authentication kind to Organizational account and make sure you are signed in. Click Next to move onto the Preview folder data. If you have more than one library or folders it will show too many files, don’t worry we will fix this.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Preview folder data dialog showing files from multiple folders" class="gallery-image" data-flex-basis="600px" data-flex-grow="250" height="272" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/sharepoint-folder-into-microsoft-fabric/image-7.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Click Create, rather than Combine so we can control which files get combined.&lt;/p&gt;
&lt;h2 id="filtering-to-the-right-sharepoint-folder"&gt;Filtering to the right SharePoint Folder
&lt;/h2&gt;&lt;p&gt;In my example I have multiple SharePoint libraries in the same site, so the initial list returned contains too many files. There is a column called Folder Path. I find a row that contains the value I want, right click on the value. Then select Text filters – Equals. This will add a filter a step to the query to filter to only files in that path.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Adding a text filter to the Folder Path column." class="gallery-image" data-flex-basis="322px" data-flex-grow="134" height="506" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/sharepoint-folder-into-microsoft-fabric/image-8.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Even if your current site only has one document library so currently this step is not required, I would add it anyway. Then when anyone adds files a new library it will not break your query.&lt;/p&gt;
&lt;h2 id="combining-the-files"&gt;Combining the Files
&lt;/h2&gt;&lt;p&gt;In order to make future additions to these queries easier and to reduce repeated work happening I would rename the query so far to FullFileList or similar and the right click on the query and select Reference. Rename the new query to something suitable, in my case it was Budget. The diagram will now show the two queries connected.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Creating a " class="gallery-image" data-flex-basis="820px" data-flex-grow="341" height="199" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/sharepoint-folder-into-microsoft-fabric/image-9.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;The next stage is to do the combining. Make sure the Content column has a data type of Binary. Then click the button in the top corner of the Content column to start the file combination. After a few seconds the Combine Files will appear requesting you to select which sheet, table or named range you are combining.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Showing the button in the Content for combining, the combine dialog and the resulted combined data" class="gallery-image" data-flex-basis="584px" data-flex-grow="243" height="279" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/sharepoint-folder-into-microsoft-fabric/image-11.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Once you click Combine it will create the Helper queries and related queries and will combine the files. You then will have a query with the first column Source.Name and the rest the data from the selected item.&lt;/p&gt;
&lt;h2 id="adding-a-destination"&gt;Adding a Destination
&lt;/h2&gt;&lt;p&gt;There might be other transformation steps you need to add before your data is ready. I’ve added an unpivot to my data, but that would a complete post on its own. Finally we get to add a destination to save the data to. If you are going to a Lakehouse, Warehouse or Database you should be aware of option available to you.&lt;/p&gt;
&lt;p&gt;The first option is if you are saving to an existing table or creating a new table.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Choosing a destination target to either a New or Existing table" class="gallery-image" data-flex-basis="390px" data-flex-grow="162" height="418" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/sharepoint-folder-into-microsoft-fabric/image-12.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;When you click next the second option is available. Turning off Use automatic settings will give you the options. Is the update an append or a replace? Is the schema dynamic or fixed, ie if your query adds a new column what happens? I’ve picked replace, the default option but as the SharePoint folder grows I might look to more clever file filters so that only new data is selected and therefore can be appended.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Showing options for append or replace" class="gallery-image" data-flex-basis="558px" data-flex-grow="232" height="292" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/sharepoint-folder-into-microsoft-fabric/image-13.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Uploading multiple Excel files will always be a requirement. So its worth knowing what Power Query can do for us in a dataflow to do that. There are probably more capacity efficient methods which need exploring.&lt;/p&gt;</description></item><item><title>Trigger Microsoft Fabric Data Pipeline using Power Automate</title><link>https://hatfullofdata.blog/trigger-microsoft-fabric-data-pipeline/</link><pubDate>Sun, 06 Oct 2024 14:18:24 +0000</pubDate><guid>https://hatfullofdata.blog/trigger-microsoft-fabric-data-pipeline/</guid><description>&lt;img src="https://hatfullofdata.blog/trigger-microsoft-fabric-data-pipeline/cover.png" alt="Featured image of post Trigger Microsoft Fabric Data Pipeline using Power Automate" /&gt;&lt;p&gt;Microsoft Fabric Data Pipelines can be scheduled to happen at regular times. What happens when you want trigger Microsoft Fabric data pipelines to run as a reaction to an event? For example someone pressing a button in an app. For this we can use Power Automate to start a pipeline using a http request.&lt;/p&gt;
&lt;h2 id="fixed"&gt;Fixed
&lt;/h2&gt;&lt;p&gt;This post has incorrect details for the connector. These have now been fixed.&lt;/p&gt;
&lt;h2 id="youtube-version"&gt;YouTube Version
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://youtu.be/9-aNXqDQaZE" target="_blank" rel="noopener"
 &gt;&lt;img class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="383" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/trigger-microsoft-fabric-data-pipeline/Power-Automate-Trigger-Microsoft-Fabric-Data-Pipeline-Time-0_00_0000.png" width="680"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="workspace-and-pipeline-guids"&gt;Workspace and Pipeline GUIDs
&lt;/h2&gt;&lt;p&gt;The flow is going to use a http action that uses a URL that includes GUIDs for both the workspace and the data pipeline. Open the data pipeline that will be triggered. Look at the URL in the browser. The Workspace GUID is the string after /groups/ and the data pipeline GUID is the string after /pipelines/.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shot of the data pipeline opened n a browser with highlights around the 2 GUIDs." class="gallery-image" data-flex-basis="712px" data-flex-grow="296" height="229" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/trigger-microsoft-fabric-data-pipeline/image-10.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="start-flow-and-add-variables"&gt;Start Flow and Add Variables
&lt;/h2&gt;&lt;p&gt;Now we have the required GUIDS we can start writing the flow. For this example we are going to use a manually triggered flow. Then we add an actions to initialise variables WorkspaceID and PipelineID and select Type of string and put in the values from the previous step.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Flow with a trigger of Manually trigger a flow and 2 Initialize variables for WorkspaceID and PipelineID, with the former selected and showing parameters." class="gallery-image" data-flex-basis="602px" data-flex-grow="250" height="271" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/trigger-microsoft-fabric-data-pipeline/image-11.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="url-of-the-trigger-microsoft-fabric-data-pipeline-request"&gt;URL of the Trigger Microsoft Fabric Data Pipeline request
&lt;/h2&gt;&lt;p&gt;Next I recommend you use a compose step to calculate the URL for the HTTP call. Interestingly the api uses workspaces rather than groups. Make sure you have the corrects /s and no spaces between. If you have called your variables WorkspaceID and PipelineID you can just copy the code below into a Compose action.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://api.fabric.microsoft.com/v1/workspaces/@{variables(&amp;#39;WorkspaceID&amp;#39;)}/items/@{variables(&amp;#39;PipelineID&amp;#39;)}/jobs/instances?jobType=Pipeline
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;&lt;img alt="Compose step containing the above code" class="gallery-image" data-flex-basis="911px" data-flex-grow="379" height="179" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/trigger-microsoft-fabric-data-pipeline/image-14.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;The above url including all the flags is documented by Microsoft here – &lt;a class="link" href="https://learn.microsoft.com/en-us/fabric/data-factory/pipeline-rest-api#run-on-demand-item-job?wt.mc_id=DX-MVP-5003563" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/en-us/fabric/data-factory/pipeline-rest-api#run-on-demand-item-job&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="http-request"&gt;HTTP Request
&lt;/h2&gt;&lt;p&gt;For this action we are going to use HTTP with Microsoft Entra ID (preauthorized) connection’s Invoke an HTTP request action. Search for HTTP and scroll down till you find it.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Adding the connection details for the HTTP action" class="gallery-image" data-flex-basis="715px" data-flex-grow="298" height="228" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/trigger-microsoft-fabric-data-pipeline/image-18.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;If this is the first time you’ve used this action you will need to setup the connection to connect to this api you will need to set it up. The two urls required are below, sometimes they appear the other way around.&lt;/p&gt;
&lt;h4 id="base-resource-url"&gt;Base Resource URL
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://api.fabric.microsoft.com/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h4 id="microsoft-entra-id-resource-uri"&gt;Microsoft Entra ID Resource URI
&lt;/h4&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://analysis.windows.net/powerbi/api
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Once you have the connection sorted you can enter in the details of the request. The Method is POST and the Url of the request is the output from the compose step.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Invoke an HTTP request action" class="gallery-image" data-flex-basis="750px" data-flex-grow="312" height="217" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/trigger-microsoft-fabric-data-pipeline/image-15.png" width="679"&gt;&lt;/p&gt;
&lt;h2 id="testing-trigger-microsoft-fabric-data-pipeline-flow"&gt;Testing Trigger Microsoft Fabric Data Pipeline Flow
&lt;/h2&gt;&lt;p&gt;The flow requires no inputs so can just be run. When the flow runs it appears to fail, but if you check the data pipeline run history you will see it was triggered just fine.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Test to Trigger Microsoft Fabric Data Pipeline" class="gallery-image" data-flex-basis="461px" data-flex-grow="192" height="354" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/trigger-microsoft-fabric-data-pipeline/image-17.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;If you look in the documentation found at &lt;a class="link" href="https://learn.microsoft.com/en-us/fabric/data-factory/pipeline-rest-api#run-on-demand-item-job" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/en-us/fabric/data-factory/pipeline-rest-api#run-on-demand-item-job&lt;/a&gt;. There is a note that says “There is no body returned currently”. Eventually it will return the job id of the pipeline run, so I am guessing because that is not returned Power Automate assumes it failed.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Data pipelines are the orchestration tool of Microsoft Fabric so being able to connect it to the Power Platform orchestration tool makes perfect sense. I look forward to the day I can mark this post as redundant and there is a Power Automate connector with an obvious action for this.&lt;/p&gt;
&lt;h2 id="more-power-automate-posts"&gt;More Power Automate Posts
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-flow-creating-adaptive-cards/" target="_blank" rel="noopener"
 &gt;Creating Adaptive Cards&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/refreshing-datasets-automatically-with-dataflow/" target="_blank" rel="noopener"
 &gt;Refreshing Datasets Automatically with Power BI Dataflows&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/power-automate-child-flow/" target="_blank" rel="noopener"
 &gt;Power Automate Child Flow&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/power-automate-get-data-from-a-power-bi-dataset/" target="_blank" rel="noopener"
 &gt;Get data from a Power BI dataset&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/power-automate-button-in-a-power-bi-report/" target="_blank" rel="noopener"
 &gt;Power Automate Button in a Power BI Report&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/power-automate-write-me-a-flow/" target="_blank" rel="noopener"
 &gt;Write Me a Flow&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/connecting-power-automate-to-devops/" target="_blank" rel="noopener"
 &gt;Power Automate and DevOps series&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/power-automate-and-power-bi-rest-api/" target="_blank" rel="noopener"
 &gt;Power Automate and Power BI Rest API series&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/power-automate-save-a-file-to-onelake-lakehouse/" target="_blank" rel="noopener"
 &gt;Save a File to OneLake Lakehouse&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/trigger-microsoft-fabric-data-pipeline/" target="_blank" rel="noopener"
 &gt;Trigger Microsoft Fabric Data Pipeline using Power Automate&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Power Automate – Save a File to OneLake Lakehouse</title><link>https://hatfullofdata.blog/power-automate-save-a-file-to-onelake-lakehouse/</link><pubDate>Thu, 03 Oct 2024 14:48:09 +0000</pubDate><guid>https://hatfullofdata.blog/power-automate-save-a-file-to-onelake-lakehouse/</guid><description>&lt;img src="https://hatfullofdata.blog/power-automate-save-a-file-to-onelake-lakehouse/cover.png" alt="Featured image of post Power Automate – Save a File to OneLake Lakehouse" /&gt;&lt;p&gt;Currently there is no Microsoft Fabric connector in Power Automate. When we want Power Automate to save a file to OneLake Lakehouse, we need to use a workaround. This post walks through the demo I did for the Microsoft Fabric European Conference 2024. You need to be aware that this uses a premium connector!&lt;/p&gt;
&lt;h2 id="youtube-version"&gt;YouTube Version
&lt;/h2&gt;&lt;p&gt;&lt;img alt="YouTube thumbnail" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="383" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/power-automate-save-a-file-to-onelake-lakehouse/Power-Automate-Copy-File-from-SharePoint-to-Lakehouse-Time-0_00_0000.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="getting-the-file-content"&gt;Getting the File Content
&lt;/h2&gt;&lt;p&gt;Before we can save a file anywhere we need the file content we are going to save. For this post I am going to work with the flow triggering from a new file in a SharePoint library and getting the file content action.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The trigger showing When a file is created and an action of Get file content" class="gallery-image" data-flex-basis="562px" data-flex-grow="234" height="290" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/power-automate-save-a-file-to-onelake-lakehouse/image.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;From the SharePoint connector triggers, select the When a file is created (properties only) and populate the site address and library name. Next add a SharePoint action, Get file content. Populate the Site Address same as the trigger. For the File Identifier, select Identifier from the dynamic content from the trigger.&lt;/p&gt;
&lt;h2 id="lakehouse-folder-url"&gt;Lakehouse Folder URL
&lt;/h2&gt;&lt;p&gt;Next we need to know the url of the Lakehouse folder where we want the file to go. This can be found in the Lakehouse by clicking on the three dots next to the required folder and from the menu selecting properties. This will open the properties pane on the right hand side. Click the copy button next to the URL.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Lakehouse folder menu with Properties highlighted and the Properties pane with URL copy button highlighted" class="gallery-image" data-flex-basis="630px" data-flex-grow="262" height="259" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/power-automate-save-a-file-to-onelake-lakehouse/image-1.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;To make life easy for ourselves we put this into a compose step followed by name of the file that triggered the flow. This is in the dynamic content from the trigger and is called File name with extension. Please note there is a / before the file name.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Compose step with the URL pasted in followed by the dynamic value from the trigger of File name with extension" class="gallery-image" data-flex-basis="597px" data-flex-grow="249" height="273" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/power-automate-save-a-file-to-onelake-lakehouse/image-2.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="create-the-file-in-the-lakehouse"&gt;Create the file in the LakeHouse
&lt;/h2&gt;&lt;h3 id="set-up-the-connection"&gt;Set up the connection
&lt;/h3&gt;&lt;p&gt;We are going to use the HTTP with Microsoft Entra ID (preauthorised) action to interact with the Lakehouse to create the file. When you add the new action search for http and then scroll down to find the right action.&lt;/p&gt;
&lt;p&gt;&lt;img alt="search and select http to save a file to onelake lakehouse" class="gallery-image" data-flex-basis="680px" data-flex-grow="283" height="240" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/power-automate-save-a-file-to-onelake-lakehouse/image-3.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;If this is the first time you’ve used this action you will need to set-up the connection. Also if this is the first time you’ve connected to the Lakehouse in this way you need to setup a new connection. It asks for two URLS. Once connected you are ready to save a File to OneLake Lakehouse&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://onelake.dfs.fabric.microsoft.com/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;https://storage.azure.com/
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h3 id="create-blank-file"&gt;Create Blank File
&lt;/h3&gt;&lt;p&gt;The first stage is to save a file to OneLake Lakehouse that is empty. This is a simple PUT action with a parameter of ?resource=file after the path created in the compose. So select PUT for the method. In the URL of the request but the Output from the compose and add on ?resource=file. I also renamed the action.&lt;/p&gt;
&lt;p&gt;&lt;img alt="HTTP" class="gallery-image" data-flex-basis="521px" data-flex-grow="217" height="313" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/power-automate-save-a-file-to-onelake-lakehouse/image-5.png" width="680"&gt;&lt;/p&gt;
&lt;h3 id="append-content"&gt;Append Content
&lt;/h3&gt;&lt;p&gt;Finally the last action is to append the file content from SharePoint onto the file. Change the Method to PATCH. The Url of the request is the output from the compose followed by three parameters (copy from below). Expand the Advanced parameters and into the body of the request select File Content from the dynamic content.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="437px" data-flex-grow="182" height="373" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/power-automate-save-a-file-to-onelake-lakehouse/image-7.png" width="680"&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;?action=append&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;position=0&lt;span class="err"&gt;&amp;amp;&lt;/span&gt;flush=true
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;h2 id="test-save-a-file-to-onelake-lakehouse"&gt;Test Save a File to OneLake Lakehouse
&lt;/h2&gt;&lt;p&gt;Save your flow and add a file to your SharePoint library and wait a minute or 2 for the flow to trigger. A file should appear in your Lake House.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shot of green success tips against all the actions in the flow and the file in SharePoint and the file in the Lakehouse" class="gallery-image" data-flex-basis="297px" data-flex-grow="124" height="548" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/power-automate-save-a-file-to-onelake-lakehouse/image-8.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;There are plenty of business cases of use cases to be able to store a file into OneLake. Various legacy systems email daily exports which will need to be saved and processed in the LakeHouse. When / If we get a Fabric connector I look forward to making this post as redundant!&lt;/p&gt;
&lt;h2 id="more-power-automate-posts"&gt;More Power Automate Posts
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-flow-creating-adaptive-cards/" target="_blank" rel="noopener"
 &gt;Creating Adaptive Cards&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/refreshing-datasets-automatically-with-dataflow/" target="_blank" rel="noopener"
 &gt;Refreshing Datasets Automatically with Power BI Dataflows&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/power-automate-child-flow/" target="_blank" rel="noopener"
 &gt;Power Automate Child Flow&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/power-automate-get-data-from-a-power-bi-dataset/" target="_blank" rel="noopener"
 &gt;Get data from a Power BI dataset&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/power-automate-button-in-a-power-bi-report/" target="_blank" rel="noopener"
 &gt;Power Automate Button in a Power BI Report&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/power-automate-write-me-a-flow/" target="_blank" rel="noopener"
 &gt;Write Me a Flow&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/connecting-power-automate-to-devops/" target="_blank" rel="noopener"
 &gt;Power Automate and DevOps series&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/power-automate-and-power-bi-rest-api/" target="_blank" rel="noopener"
 &gt;Power Automate and Power BI Rest API series&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/power-automate-save-a-file-to-onelake-lakehouse/" target="_blank" rel="noopener"
 &gt;Save a File to OneLake Lakehouse&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/trigger-microsoft-fabric-data-pipeline/" target="_blank" rel="noopener"
 &gt;Trigger Microsoft Fabric Data Pipeline using Power Automate&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</description></item><item><title>Microsoft Fabric – Notebook and Data Wrangler</title><link>https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/</link><pubDate>Mon, 13 Nov 2023 16:22:16 +0000</pubDate><guid>https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/</guid><description>&lt;p&gt;Before I started with Microsoft Fabric I had never created a spark notebook. This doesn’t stop me though. By using a combination of Notebook and Data Wrangler means I can transform data and write to table writing very little code by hand.&lt;/p&gt;
&lt;h2 id="microsoft-fabric-quick-guides"&gt;Microsoft Fabric Quick Guides
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-create-a-lakehouse/" target="_blank" rel="noopener"
 &gt;Create a Lakehouse&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-upload-a-file-and-folder/" target="_blank" rel="noopener"
 &gt;Load CSV file and folder&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-create-table-from-csv-file/" target="_blank" rel="noopener"
 &gt;Create a table from a CSV file&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/" target="_blank" rel="noopener"
 &gt;Create a Table with a Dataflow&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/" target="_blank" rel="noopener"
 &gt;Create a Table using a Notebook and Data Wrangler&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Exploring the SQL End Point&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Power BI Report&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Paginated Report&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="youtube-version"&gt;YouTube Version
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://youtu.be/tE-eCnlvY9k" target="_blank" rel="noopener"
 &gt;&lt;img alt="YouTube thumbnail" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="383" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/Microsoft-Fabric-Notebook-and-Data-Wrangler-Time-0_00_0000.png" width="680"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="create-and-rename-a-notebook"&gt;Create and rename a Notebook
&lt;/h2&gt;&lt;p&gt;Inside the Lakehouse, on the ribbon drop down Open notebook and select New notebook. This will create an empty notebook with a default name. We can rename the notebook by clicking on the down arrow next to the name and entering a new name.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The Open notebook menu showing New notebook and the drop down from the notebook name to rename the notebook." class="gallery-image" data-flex-basis="637px" data-flex-grow="265" height="256" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/2023-11-12_14-57-03.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="adding-a-markdown-title-cell"&gt;Adding a Markdown Title cell
&lt;/h2&gt;&lt;p&gt;Notebooks use 2 different types of cells, Code and Markdown. The Markdown cells allow for documentation to be included in the notebook. Any cell in the notebook can be converted into a Markdown cell. Below are screen grabs of converting the default cell into a Markdown cell, by clicking on the M button so giving a title cell to the notebook.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen grabs showing the default block to be edited to show a heading 1 of Load Products table." class="gallery-image" data-flex-basis="338px" data-flex-grow="141" height="482" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/2023-11-12_15-04-37.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Markdown includes syntax for lots of different text formatting. A good reference can be found at &lt;a class="link" href="https://www.markdownguide.org/basic-syntax/" target="_blank" rel="noopener"
 &gt;https://www.markdownguide.org/basic-syntax/&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="load-the-file-into-a-data-frame"&gt;Load the file into a data frame
&lt;/h2&gt;&lt;p&gt;Notebooks use data frames to handle blocks of data. The next task is to load a csv file. On the left hand side select Files to list the right file. Then on the Products.csv, click on the three dots menu. Next select Load data and then Spark. This will add a new code cell to the notebook.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Showing the selected file menu and the Load data, Spark options. And below the code block that is created" class="gallery-image" data-flex-basis="454px" data-flex-grow="189" height="359" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/2023-11-12_15-11-43.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="run-a-code-cell"&gt;Run a code cell
&lt;/h2&gt;&lt;p&gt;Each code cell has a blue arrow on the left, clicking this runs the code in the cell. The function display lists the data frame contents below the code cell. Being able to run each cell in turn really helps with development. There is a run all option on the toolbar.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shot showing the code block with the run arrow on the left hand side and showing the results" class="gallery-image" data-flex-basis="432px" data-flex-grow="180" height="377" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/2023-11-12_15-17-36.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;We can limit the display function to only list a few lines by using a method on the data frame called take. df.take(4) just returns 4 rows of data. Another method that is useful to examine a dataframe is dtypes. This returns all the datatypes of the data frame. So I edit the code and re-run the cell.&lt;/p&gt;
&lt;p&gt;&lt;img alt="modified code to only show 4 lines and show the datatypes" class="gallery-image" data-flex-basis="545px" data-flex-grow="227" height="299" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/2023-11-12_15-21-03.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="data-wrangler"&gt;Data Wrangler
&lt;/h2&gt;&lt;p&gt;Before I can write the data frame to a table there are transformations that need to be done. Firstly there are spaces in some of the column names. Next the ID and Price columns need to be numbers rather than strings. Finally I do not want to include the Notes column.&lt;/p&gt;
&lt;p&gt;I could do the searches and find the Spark code to do those transforms. There is an alternative introduced in Microsoft Fabric called Data Wrangler. This will write the code for the three changes we need. We launch Data Wrangler from the Data ribbon – Transform Data Frame in Data Wrangler. This will list your data frames – which means you need to have run the cell that populates the dataframe first. Then we get to see the Data Wrangler screen.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Data ribbon showing how to select the dataframe and a screen grab of the Data Wrangler" class="gallery-image" data-flex-basis="608px" data-flex-grow="253" height="268" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/2023-11-12_15-57-04.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="rename-columns"&gt;Rename Columns
&lt;/h2&gt;&lt;p&gt;Product ID column needs to be renamed. Clicking on the three dots on the Product ID column heading. Then select rename column and the Operations pane changes to show rename options. Enter the new name Product_ID and the data pane will update to show the old in red and the new in green. Finally click Apply to save the changes.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Showing how to change column names in Data Wrangler." class="gallery-image" data-flex-basis="547px" data-flex-grow="228" height="298" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/2023-11-12_15-58-43.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;The same needs to be done on the Base Price column to change it to Base_Price.&lt;/p&gt;
&lt;h2 id="changing-column-types"&gt;Changing Column Types
&lt;/h2&gt;&lt;p&gt;The next requirement is to change the column data types. This is very similar to renaming and can be found on the column heading menu. I change the Product_ID column to Int64 and the Base_Price column to Float64.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen grab showing the change column type options." class="gallery-image" data-flex-basis="491px" data-flex-grow="204" height="332" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/2023-11-12_16-02-19.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="dropping-a-column"&gt;Dropping a column
&lt;/h2&gt;&lt;p&gt;Finally we need to drop the Notes column. Again this is found on the column header menu.&lt;/p&gt;
&lt;p&gt;&lt;img alt="dropping a column" class="gallery-image" data-flex-basis="658px" data-flex-grow="274" height="248" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/2023-11-12_16-06-07.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="add-data-wrangler-code-to-notebook"&gt;Add Data Wrangler code to Notebook
&lt;/h2&gt;&lt;p&gt;Once we have finished all the transformations we are ready to add the code into the notebook. Click on the Add code to notebook. When the dialog appears, check the code and click Add.&lt;/p&gt;
&lt;p&gt;&lt;img alt="the ribbon in data wrangler showing Add code to notebook and the dialog to confirm adding the code" class="gallery-image" data-flex-basis="279px" data-flex-grow="116" height="583" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/2023-11-12_16-11-50.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="run-the-data-wrangler-code"&gt;Run the Data Wrangler code
&lt;/h2&gt;&lt;p&gt;When the new code cell appears, we can see it ends by creating a new data frame df_clean and displaying it. So if we run the code we can see the result of the transformations.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Executing the transformation code" class="gallery-image" data-flex-basis="372px" data-flex-grow="155" height="438" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/2023-11-12_16-12-59.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="write-data-frame-to-a-table"&gt;Write data frame to a table
&lt;/h2&gt;&lt;p&gt;After the transformation code has run, the data frame is ready to be saved into a table. This is the single line of code we have write by hand. A data frame has a write method which accepts format and mode options. Using Ctrl + Spacebar will get the autocomplete to help. Here is the required code.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Final code block with the save to table code" class="gallery-image" data-flex-basis="954px" data-flex-grow="397" height="171" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/2023-11-12_16-58-02.png" width="680"&gt;&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;# Save df_clean to a table called Products
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;df_clean.write.format(&amp;#34;delta&amp;#34;).mode(&amp;#34;overwrite&amp;#34;).saveAsTable(&amp;#34;Products&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;Once the code has run successfully, we can look in the Lakehouse and see the new table products.&lt;/p&gt;
&lt;p&gt;&lt;img alt="The new products table in the Lakehouse" class="gallery-image" data-flex-basis="788px" data-flex-grow="328" height="207" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/2023-11-12_16-58-50.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;For the newcomer, notebooks are daunting. With the addition of Data Wrangler we have a tool to help write the transformation code. One quote I heard was Data Wrangler is the Power Query tool for notebooks. I have yet to work out when I would use a notebook over a dataflow but I’m assuming there will be pros and cons that vary depending on the data involved.&lt;/p&gt;</description></item><item><title>Microsoft Fabric – Create tables with Dataflows</title><link>https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/</link><pubDate>Fri, 10 Nov 2023 09:09:14 +0000</pubDate><guid>https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/</guid><description>&lt;p&gt;As part of Microsoft Fabric, we have new Gen2 Dataflows and they have a new ability. A Gen2 Dataflow entity can have a destination. This means using a dataflow we can create a table in Fabric from another source, such as a folder of files.&lt;/p&gt;
&lt;h2 id="microsoft-fabric-quick-guides"&gt;Microsoft Fabric Quick Guides
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-create-a-lakehouse/" target="_blank" rel="noopener"
 &gt;Create a Lakehouse&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-upload-a-file-and-folder/" target="_blank" rel="noopener"
 &gt;Load CSV file and folder&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-create-table-from-csv-file/" target="_blank" rel="noopener"
 &gt;Create a table from a CSV file&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/" target="_blank" rel="noopener"
 &gt;Create a Table with a Dataflow&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/" target="_blank" rel="noopener"
 &gt;Create a Table using a Notebook and Data Wrangler&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Exploring the SQL End Point&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Power BI Report&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Paginated Report&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="youtube-version"&gt;YouTube Version
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://youtu.be/iiEx-47Ptr8" target="_blank" rel="noopener"
 &gt;&lt;img alt="thumbnail from YouTube" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="383" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/Microsoft-Fabric-Create-a-table-using-a-Dataflow-Time-0_00_00001.png" width="680"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="creating-gen2-dataflows"&gt;Creating Gen2 Dataflows
&lt;/h2&gt;&lt;p&gt;Open the Lakehouse and then from the Get data drop down on the Home ribbon select New Dataflow Gen2. This will create an empty dataflow with a default name. Clicking on the name in the top left, then a pop-up appears allowing you to change the name.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen grab of the get data drop down and the drop down when you click on" class="gallery-image" data-flex-basis="593px" data-flex-grow="247" height="275" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/2023-11-06_21-34-49.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;For this blog post we are going to load the csv files in Sales folder, loaded in an earlier post and video. The files have been loaded into the Lakehouse so the data source is OneLake. In the Power Query window, on the Home ribbon, click Get data. From the menu that appears, we select More.. When the Choose data source appears, the bottom half lists OneLake sources, select the Lakehouse.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen grab of the menu on Get Data and the Choose data source dialog." class="gallery-image" data-flex-basis="613px" data-flex-grow="255" height="266" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/2023-11-06_21-43-22.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;When the Choose data appears navigate to find the Sales folder. Then click Create. After a few moments a query will appear showing a row for every file in the folder.&lt;/p&gt;
&lt;p&gt;&lt;img class="gallery-image" data-flex-basis="591px" data-flex-grow="246" height="276" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/2023-11-06_21-54-48.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Power Query includes a feature to combine files, it requires the Content column to be binary. On the Content column, click on the datatype ABC/123 in the top left of the column and select binary. This will give you a column of binary&lt;/p&gt;
&lt;p&gt;&lt;img alt="Content column data type selection with binary highlighted and the final result of Content column full of Binary objects." class="gallery-image" data-flex-basis="341px" data-flex-grow="142" height="478" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/2023-11-09_15-12-17.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;The Content column is now the correct data type to combine the files. When you click on the top right icon it will start creating the helper queries to do the file combining. It will open a combine files dialog, showing you the content of the first file. When you click OK it will build the helper queries and the Sales query will now show the data from the files appended.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen grab of the Queries pane with the helper queries and the Sales query and the data" class="gallery-image" data-flex-basis="615px" data-flex-grow="256" height="265" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/2023-11-09_15-35-22.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="fixing-the-date-column"&gt;Fixing the date column
&lt;/h2&gt;&lt;p&gt;The CSV files contains dates in American format, MM/DD/YYYY. The dataflow is looking for dates in my format DD/MM/YYYY so makes the date column string format. This needs fixing before saving to a table.&lt;/p&gt;
&lt;p&gt;Click on the ABC in the top left of the Order Date column. Then from the data type options select Using locale. When the dialog appears, I select Date for the data type and the English (United States) for the locale. When I click okay it changes the strings into dates. This feature is awesome and probably deserves a post of its own!&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen grabs showing the path from a column of dates as a string to dates in date format" class="gallery-image" data-flex-basis="591px" data-flex-grow="246" height="276" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/2023-11-09_15-50-42.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="adding-a-destination"&gt;Adding a Destination
&lt;/h2&gt;&lt;p&gt;Now the data is ready we can set up the destination. In the bottom right of the screen it shows Data Destination and should show No data destination.&lt;/p&gt;
&lt;p&gt;Click on the plus next to Data destination and from the options select Lakehouse. You will get a connections window appear and you can just click Next. Then the next step asks you to select which workspace and then which container in that workspace. Once you have selected the right place you can update the Table Name. Now you are ready to click Next.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Showing the steps from clicking the plus right through to selecting the container in the workspace." class="gallery-image" data-flex-basis="386px" data-flex-grow="161" height="422" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/2023-11-09_16-02-57.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;The last step update method and column mapping. The update method is a choice between adding data to the bottom of the table, Append, or overwriting the data, Replace. We are going to use Replace in this instance. The column mapping takes the columns from the query and tries to use those for column name. Column names can only contain letters, numbers and underscores. So if you have column names that don’t fit that it offers to fix that. Once you are happy click Save Settings&lt;/p&gt;
&lt;p&gt;&lt;img alt="Choose destination settings last step showing options for Update method with Replace selectes" class="gallery-image" data-flex-basis="422px" data-flex-grow="176" height="386" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/2023-11-09_16-05-50.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="publishing-and-refreshing"&gt;Publishing and Refreshing
&lt;/h2&gt;&lt;p&gt;Now we have a query that shapes our data and we have a destination set up we can Publish the dataflow. This will save the dataflow and will refresh it. If you wanted to just save the dataflow and not refresh you can click the arrow next to Publish and select Publish later.&lt;/p&gt;
&lt;p&gt;Once the refresh has completed, we can open the Lakehouse and see the new Sales table has been created.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Explorer window on the left showing the list of tables inclu" class="gallery-image" data-flex-basis="590px" data-flex-grow="246" height="276" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/2023-11-09_16-48-25.png" width="679"&gt;&lt;/p&gt;
&lt;h2 id="gen2-dataflows-conclusion"&gt;Gen2 Dataflows Conclusion
&lt;/h2&gt;&lt;p&gt;Dataflows having a destination to write to is an exciting update. Power Platform has dataflows that can write to Dataverse but they have more issues than I’m willing to list here. Probably 90% of the transformations you need in Dataflows you can do by clicking rather than writing M. So this is mostly a low-code solution for getting data into Fabric. A later post will talk about how to handle not just overwriting the table.&lt;/p&gt;</description></item><item><title>Microsoft Fabric – Create table from CSV file</title><link>https://hatfullofdata.blog/fabric-create-table-from-csv-file/</link><pubDate>Thu, 09 Nov 2023 08:41:51 +0000</pubDate><guid>https://hatfullofdata.blog/fabric-create-table-from-csv-file/</guid><description>&lt;p&gt;In a previous post we uploaded a csv file into the Lakehouse. In this post we take the next step to create table from csv file loaded into the Lakehouse. This is the simplest method to create a table and requires no coding. The simplicity means that there are limitations.&lt;/p&gt;
&lt;h2 id="microsoft-fabric-quick-guides"&gt;Microsoft Fabric Quick Guides
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-create-a-lakehouse/" target="_blank" rel="noopener"
 &gt;Create a Lakehouse&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-upload-a-file-and-folder/" target="_blank" rel="noopener"
 &gt;Load CSV file and folder&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-create-table-from-csv-file/" target="_blank" rel="noopener"
 &gt;Create a table from a CSV file&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/" target="_blank" rel="noopener"
 &gt;Create a Table with a Dataflow&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/" target="_blank" rel="noopener"
 &gt;Create a Table using a Notebook and Data Wrangler&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Exploring the SQL End Point&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Power BI Report&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Paginated Report&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="youtube-version"&gt;YouTube Version
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://youtu.be/8PgeAhtK1c0" target="_blank" rel="noopener"
 &gt;&lt;img alt="thumbnail from YouTube video" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="383" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-create-table-from-csv-file/Microsoft-Fabric-Create-table-from-csv-file-Time-0_00_0000.png" width="680"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="create-table-from-csv-file"&gt;Create Table from CSV file
&lt;/h2&gt;&lt;p&gt;From within the Lakehouse, navigate to view the filename of the file you want to load into a table. Click on the 3 dots next to the filename. Then click on the arrow next to Load to Tables and select New table. When the next dialog appears, by default the table name will match the csv file name in lowercase. The name can be updated. Tick or untick the box regarding the headers, and click Load.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen grabs showing the filename with 3 dot menu highlighted and the popup menu and below that the Load file to new table dialog box" class="gallery-image" data-flex-basis="243px" data-flex-grow="101" height="671" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-create-table-from-csv-file/2023-11-05_14-25-46.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;After a short while the new table will appear in the Explorer pane. When you click on the table name, a preview will appear.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Explorer pane showing the table customers that has been selected so on the right a snapshot of 6 rows of data." class="gallery-image" data-flex-basis="741px" data-flex-grow="309" height="220" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-create-table-from-csv-file/2023-11-05_15-36-28.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="limitations"&gt;Limitations
&lt;/h2&gt;&lt;p&gt;This method of creating a table leaves the determination of column type to the process. So we have no control of that. For some files this will cause an issue. To avoid any issue on the date format I made sure the date format was YYYY-MM-DD.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Explorer pane showing the customers table expanded to show the column names and types" class="gallery-image" data-flex-basis="207px" data-flex-grow="86" height="473" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-create-table-from-csv-file/2023-11-05_16-20-55.png" width="408"&gt;&lt;/p&gt;
&lt;p&gt;You can see what the column types are in the table by clicking on the arrow next to the table name to expand it.&lt;/p&gt;
&lt;p&gt;You cannot change the column types from this view. The table is stored in delta format and clicking on the 3 dots menu will give you options to explore the properties and view the actual files that contain the data.&lt;/p&gt;
&lt;h2 id="updating-a-table"&gt;Updating a Table
&lt;/h2&gt;&lt;p&gt;When selecting to load into a table and selecting Existing table instead of New table will give a slightly different dialog box. You need to select the table and then select if the file data is to be appended or will overwrite the existing data. Be aware there is no undo.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Load file to existing table dialog with the radio buttons to Append or Overwrite highlighted." class="gallery-image" data-flex-basis="261px" data-flex-grow="108" height="625" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-create-table-from-csv-file/2023-11-05_16-34-37.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;For a clean, well structured CSV file, this is a great place to start. With a slow moving dimension table this could be a good solution as it just requires maintaining a csv file. For more complex files that require transformation there are better methods such as a dataflow or a notebook.&lt;/p&gt;</description></item><item><title>Microsoft Fabric – Upload a CSV file and folder</title><link>https://hatfullofdata.blog/fabric-upload-a-csv-file-and-folder/</link><pubDate>Tue, 07 Nov 2023 16:50:43 +0000</pubDate><guid>https://hatfullofdata.blog/fabric-upload-a-csv-file-and-folder/</guid><description>&lt;p&gt;The simplest way to add data to a Lakehouse is upload a csv file. In this blog post we will upload a csv file and upload a folder of csv files. You can upload other file types, but they take more work than csv files to quickly load into tables.&lt;/p&gt;
&lt;h2 id="microsoft-fabric-quick-guides"&gt;Microsoft Fabric Quick Guides
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-create-a-lakehouse/" target="_blank" rel="noopener"
 &gt;Create a Lakehouse&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-upload-a-file-and-folder/" target="_blank" rel="noopener"
 &gt;Load CSV file and folder&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-create-table-from-csv-file/" target="_blank" rel="noopener"
 &gt;Create a table from a CSV file&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/" target="_blank" rel="noopener"
 &gt;Create a Table with a Dataflow&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/" target="_blank" rel="noopener"
 &gt;Create a Table using a Notebook and Data Wrangler&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Exploring the SQL End Point&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Power BI Report&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Paginated Report&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="youtube-version"&gt;YouTube Version
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://youtu.be/CnQkB-aK6B8" target="_blank" rel="noopener"
 &gt;&lt;img alt="YouTube thumbnail" class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="383" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-upload-a-csv-file-and-folder/Fabric-Upload-File-and-Folder-Time-0_00_0000.png" width="680"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="upload-a-csv"&gt;Upload a CSV
&lt;/h2&gt;&lt;p&gt;We open the Lakehouse, see previous post on how to create one. Then in the Explorer pane on the left next to Files and click on the three dots. On the popup menu click on Upload and then Upload files. When the pane appears on the right, click on the folder icon in the input box. Once you’ve selected the file, click the Upload button.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen grab of Explorer menu and the popup menu and the Upload files pane." class="gallery-image" data-flex-basis="788px" data-flex-grow="328" height="207" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-upload-a-csv-file-and-folder/2023-11-01_08-49-08.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Once the file is uploaded it can be found by clicking on Files. If you click on the file it the content will be displayed.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen shot of Files showing customer.csv file loaded and then showing the file content" class="gallery-image" data-flex-basis="977px" data-flex-grow="407" height="167" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-upload-a-csv-file-and-folder/2023-11-01_08-58-18.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;Multiple files could have been selected to be uploaded at the same time. All the files would have been uploaded into the same location.&lt;/p&gt;
&lt;h2 id="upload-a-folder-of-files"&gt;Upload a Folder of Files
&lt;/h2&gt;&lt;p&gt;Uploading a folder is very similar to uploading a single file. In the explorer pane on the left, click on the three dots next to File, or a subfolder and select Upload. Then select Upload folder and the Upload folder pane will appear on the right. Clicking on the folder icon will allow you to select a folder. Finally you can click Upload and you will a progress line for every file in the folder.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen grans showing the path from select upload folder to a list successful uploads" class="gallery-image" data-flex-basis="487px" data-flex-grow="202" height="335" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-upload-a-csv-file-and-folder/2023-11-02_20-43-19.png" width="680"&gt;&lt;/p&gt;
&lt;p&gt;The list of files that have been uploaded can be seen by clicking on the folder name in the explorer pane on the left&lt;/p&gt;
&lt;p&gt;&lt;img alt="screen grab showing the folder name selected and the files listed in the main area" class="gallery-image" data-flex-basis="420px" data-flex-grow="175" height="388" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-upload-a-csv-file-and-folder/2023-11-02_20-47-05.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="updating-a-file-or-folder"&gt;Updating a File or Folder
&lt;/h2&gt;&lt;p&gt;Data is rarely the same forever so you will want to upload an updated file or folder. If you select a file or folder that already exists you will not be able to click the upload button unless you tick the Overwrite if files already exist.&lt;/p&gt;
&lt;p&gt;&lt;img alt="2 screen grabs of the Upload files pane. The first showing an error message of the following files already exist and the Upload button disabled. Second one with the Overwrite if files exist box ticked and the Upload button enbaled. " class="gallery-image" data-flex-basis="267px" data-flex-grow="111" height="610" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-upload-a-csv-file-and-folder/2023-11-02_21-02-51.png" width="680"&gt;&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion
&lt;/h2&gt;&lt;p&gt;Manually uploading files and folders is not a great solution for a large number of files but it is a good place to start. The OneLake app will be a great alternative when its fully available and using pipelines to orchestrate file management is also a good alternative and future posts will cover both.&lt;/p&gt;</description></item><item><title>Microsoft Fabric – Create a Lakehouse</title><link>https://hatfullofdata.blog/fabric-create-a-lakehouse/</link><pubDate>Thu, 02 Nov 2023 22:43:20 +0000</pubDate><guid>https://hatfullofdata.blog/fabric-create-a-lakehouse/</guid><description>&lt;p&gt;Lakehouses are one of the main building blocks in Microsoft Fabric. A lakehouse allows you to store structured and unstructured data in a single location. In this post we are going to create an empty one. Future posts will populate it.&lt;/p&gt;
&lt;h2 id="microsoft-fabric-quick-guides"&gt;Microsoft Fabric Quick Guides
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-create-a-lakehouse/" target="_blank" rel="noopener"
 &gt;Create a Lakehouse&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-upload-a-file-and-folder/" target="_blank" rel="noopener"
 &gt;Load CSV file and folder&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/fabric-create-table-from-csv-file/" target="_blank" rel="noopener"
 &gt;Create a table from a CSV file&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-fabric-create-tables-with-dataflows/" target="_blank" rel="noopener"
 &gt;Create a Table with a Dataflow&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a class="link" href="https://hatfullofdata.blog/microsoft-fabric-notebook-and-data-wrangler/" target="_blank" rel="noopener"
 &gt;Create a Table using a Notebook and Data Wrangler&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Exploring the SQL End Point&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Power BI Report&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Create a Paginated Report&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="youtube-version"&gt;YouTube Version
&lt;/h2&gt;&lt;p&gt;&lt;a class="link" href="https://youtu.be/Rafh8RRBrj8" target="_blank" rel="noopener"
 &gt;&lt;img class="gallery-image" data-flex-basis="426px" data-flex-grow="177" height="383" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-create-a-lakehouse/Fabric-Create-a-Lakehouse-Time-0_00_0000.png" width="680"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id="empty-workspace-with-a-fabric-capacity"&gt;Empty Workspace with a Fabric Capacity
&lt;/h2&gt;&lt;p&gt;We start in an empty workspace that has a capacity assigned to it. A jewel logo next to the workspace name or checking the workspace settings are indicators that it has a capacity. A premium per user capacity does not include all Fabric features.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Workspace title with a jewel logo and a screen shot of the premium workspace settings highlighting Fabric and Trial capacity options" class="gallery-image" data-flex-basis="414px" data-flex-grow="172" height="394" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-create-a-lakehouse/2023-10-23_20-42-18.jpg" width="680"&gt;&lt;/p&gt;
&lt;h2 id="create-a-lakehouse"&gt;Create a Lakehouse
&lt;/h2&gt;&lt;p&gt;There are two ways to start creating a lakehouse. First method is to click New in the top left of the workspace area, by default it shows Power BI options so click on More options. When the screen updates, on the second row is Lakehouse.&lt;/p&gt;
&lt;p&gt;&lt;img alt="showing the dropdown from the New button with More options highlighted and a screen grab of the new screen with Lakehouse button highlighted." class="gallery-image" data-flex-basis="630px" data-flex-grow="262" height="259" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-create-a-lakehouse/2023-10-23_20-55-22.jpg" width="680"&gt;&lt;/p&gt;
&lt;p&gt;The second option is switch the experience in the bottom left of the screen to show all the Experiences. When the menu pops up, select Data Engineering. Then the screen will update and show a slightly different Lakehouse button.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Screen grab showing the experience button and the menu of expereinces with Data Engineering highlighted and an arrow pointing at a screen grab of the Lakehouse button" class="gallery-image" data-flex-basis="703px" data-flex-grow="293" height="232" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-create-a-lakehouse/2023-10-23_21-01-17.jpg" width="680"&gt;&lt;/p&gt;
&lt;p&gt;The next step in the create a lakehouse process is to name the lakehouse. The name can only include letters, numbers, and underscore. It will display an error message to correct you. Enter the name and click Create. Then wait a few moments and you will get your empty lakehouse.&lt;/p&gt;
&lt;p&gt;&lt;img alt="New Lakehouse dialog to enter in the name, with a Create button and then an arrow pointing to a screengrab of the Explorer pain showing LGB_Customers tree with a Tables and Files folder" class="gallery-image" data-flex-basis="816px" data-flex-grow="340" height="200" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-create-a-lakehouse/2023-10-23_21-10-33.jpg" width="680"&gt;&lt;/p&gt;
&lt;h2 id="what-is-created"&gt;What is created?
&lt;/h2&gt;&lt;p&gt;Every lakehouse created in Fabric also creates an SQL Endpoint and a Power BI Dataset. Even though we have not added data the containers are already there to handle the data.&lt;/p&gt;
&lt;p&gt;&lt;img alt="Lineage view of the three items. On the left is the Lakehouse with an arrow to the SQL Endpoint in the middle and the dataset on the right." class="gallery-image" data-flex-basis="1754px" data-flex-grow="731" height="93" loading="lazy" sizes="(max-width: 767px) calc(100vw - 30px), (max-width: 1023px) 700px, (max-width: 1279px) 950px, 1232px" src="https://hatfullofdata.blog/fabric-create-a-lakehouse/2023-10-23_21-17-04.jpg" width="680"&gt;&lt;/p&gt;
&lt;h2 id="references"&gt;References
&lt;/h2&gt;&lt;p&gt;Microsoft’s Lakehouse Overview – &lt;a class="link" href="https://learn.microsoft.com/en-us/fabric/data-engineering/lakehouse-overview" target="_blank" rel="noopener"
 &gt;https://learn.microsoft.com/en-us/fabric/data-engineering/lakehouse-overview&lt;/a&gt;&lt;/p&gt;</description></item></channel></rss>