<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>A #dataOp ramblings</title><link>https://fpvmorais.com/</link><description>Recent content on A #dataOp ramblings</description><generator>Hugo</generator><language>en</language><lastBuildDate>Wed, 07 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://fpvmorais.com/index.xml" rel="self" type="application/rss+xml"/><item><title>Fabric Semantic Model Refresh: One Table at a Time</title><link>https://fpvmorais.com/post/fabric_semantic_model_refresh_enhanced/</link><pubDate>Wed, 07 Oct 2026 00:00:00 +0000</pubDate><guid>https://fpvmorais.com/post/fabric_semantic_model_refresh_enhanced/</guid><description>&lt;p&gt;In a &lt;a href="https://fpvmorais.com/post/fabri_power_bi_refresh_with_notebooks.md"&gt;previous post&lt;/a&gt; I
showed how to trigger a semantic model refresh from a Fabric notebook
using &lt;code&gt;sempy.fabric&lt;/code&gt;. That approach works great for small models, but
in production you&amp;rsquo;ll quickly run into problems when the model has many
tables or large fact tables.&lt;/p&gt;
&lt;h2 id="the-problem-out-of-memory"&gt;The problem: out of memory&lt;/h2&gt;
&lt;p&gt;The &lt;code&gt;sempy&lt;/code&gt; default for &lt;code&gt;max_parallelism&lt;/code&gt; is &lt;strong&gt;10&lt;/strong&gt;. For a model with
27 tables including several large fact tables (tens of millions of
rows), processing 10 tables concurrently can easily exhaust the
available memory on the capacity and the refresh fails with a generic
&amp;ldquo;out of memory&amp;rdquo; error — or worse, it succeeds but takes an
unreasonably long time because of internal retries.&lt;/p&gt;</description></item><item><title>Microsoft Fabric External Data Sharing Hidden Limitation</title><link>https://fpvmorais.com/post/fabric_external_sharing_hidden_limitation/</link><pubDate>Thu, 09 Apr 2026 19:36:00 +0100</pubDate><guid>https://fpvmorais.com/post/fabric_external_sharing_hidden_limitation/</guid><description>&lt;p&gt;Microsoft Fabric &lt;strong&gt;&lt;strong&gt;external data sharing&lt;/strong&gt;&lt;/strong&gt; is a powerful feature that
allows us to share data with external users. This is particularly
&lt;strong&gt;&lt;strong&gt;interesting&lt;/strong&gt;&lt;/strong&gt; because it enables data to be shared &lt;strong&gt;in-place&lt;/strong&gt; from
the sharer&amp;rsquo;s tenant without any data copy. We simply create shortcuts.&lt;/p&gt;
&lt;p&gt;The use case for the customer in question involves data from
&lt;strong&gt;&lt;strong&gt;Microsoft Dynamics 365 (D365)&lt;/strong&gt;&lt;/strong&gt; residing on two different Azure
tenants. I needed a solution to share data from one tenant to the
other.&lt;/p&gt;</description></item><item><title>Refreshing Power BI Datasets with Notebooks</title><link>https://fpvmorais.com/post/fabri_power_bi_refresh_with_notebooks/</link><pubDate>Wed, 12 Nov 2025 00:00:00 +0000</pubDate><guid>https://fpvmorais.com/post/fabri_power_bi_refresh_with_notebooks/</guid><description>&lt;p&gt;The &lt;code&gt;sempy&lt;/code&gt; Python library in Fabric is quite powerful and offers a
range of capabilities that make working with Fabric environments more
efficient and flexible. One of the most useful features I&amp;rsquo;ve
implemented in my projects is the ability to trigger semantic model
refreshes directly from a Spark notebook.&lt;/p&gt;
&lt;p&gt;This approach allows to trigger the refresh right after the data load
is finished.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;sempy.fabric&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nn"&gt;fabric&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;time&lt;/span&gt;
&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;&lt;span class="n"&gt;workspace&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fabric&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;resolve_workspace_name&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;dataset&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;My_Amazing_Semantic_Model&amp;#34;&lt;/span&gt;
&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;&lt;span class="n"&gt;refresh_request_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fabric&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;refresh_dataset&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;refresh_type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;full&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&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;&lt;span class="c1"&gt;# refresh api is async, so we need to poll until it completes&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="kc"&gt;True&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&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; &lt;span class="n"&gt;res&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;fabric&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_refresh_execution_details&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;dataset&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;workspace&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;refresh_request_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;refresh_request_id&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&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; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Unknown&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;break&lt;/span&gt;
&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;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Completed&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Refresh Dataset completed with success &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;extended_status&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;errors&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;res&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;messages&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Message&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;cat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sep&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;raise&lt;/span&gt; &lt;span class="ne"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Refresh Dataset failed: &lt;/span&gt;&lt;span class="se"&gt;\n\n&lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This script starts by resolving the current workspace and identifying
the target dataset. It then initiates a full refresh of that dataset
and waits for the process to complete, checking periodically for
updates.&lt;/p&gt;</description></item><item><title>Terraform/OpenTofu Notes</title><link>https://fpvmorais.com/post/terraform_opentofu_notes/</link><pubDate>Wed, 05 Nov 2025 00:00:00 +0000</pubDate><guid>https://fpvmorais.com/post/terraform_opentofu_notes/</guid><description>&lt;h2 id="using-workspaces-for-environment-separation"&gt;Using Workspaces for Environment Separation&lt;/h2&gt;
&lt;p&gt;Terraform workspaces are a powerful feature that allows you to manage
multiple environments (such as dev, staging, and prod) within the same
configuration. For example, to switch to the production workspace:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tofu workspace &lt;span class="k"&gt;select&lt;/span&gt; prod
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="applying-configuration-changes"&gt;Applying Configuration Changes&lt;/h2&gt;
&lt;p&gt;When applying changes to your Terraform configuration, you can specify
a variable file for different environments and approve the changes
automatically:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sh" data-lang="sh"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tofu apply -var-file ./dev.tfvars -auto-approve
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="importing-existing-resources"&gt;Importing Existing Resources&lt;/h2&gt;
&lt;p&gt;To import an existing resource into Terraform&amp;rsquo;s state, use the import
command with the appropriate variable file:&lt;/p&gt;</description></item><item><title>The credentials provided for the UsageMetricsDataConnector source are invalid.</title><link>https://fpvmorais.com/post/usagemetricsdataconnector_invalid_credentials/</link><pubDate>Mon, 14 Jul 2025 00:00:00 +0100</pubDate><guid>https://fpvmorais.com/post/usagemetricsdataconnector_invalid_credentials/</guid><description>&lt;p&gt;Last weeks I had several meetings with Microsoft support to try
this wrong credentials issue. The problem was that after right
clicking to &amp;ldquo;View Usage Metrics Report&amp;rdquo; the report would come up
empty and after 24h you would get an email with the following message:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&amp;lt;ccon&amp;gt;The credentials provided for the UsageMetricsDataConnector
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;source are invalid. (Source at UsageMetricsDataConnector.)&amp;lt;/ccon&amp;gt;. The
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;exception was raised by the IDbCommand interface
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;We tried several approaches until we found this piece of documentation:
&lt;a href="https://learn.microsoft.com/en-us/power-bi/collaborate-share/service-modern-usage-metrics#considerations-and-limitations"&gt;https://learn.microsoft.com/en-us/power-bi/collaborate-share/service-modern-usage-metrics#considerations-and-limitations&lt;/a&gt;&lt;/p&gt;</description></item><item><title>About me</title><link>https://fpvmorais.com/about/</link><pubDate>Wed, 09 Jul 2025 00:00:00 +0000</pubDate><guid>https://fpvmorais.com/about/</guid><description>&lt;p&gt;I&amp;rsquo;m a Portuguese Solution Data Architect based in Braga, with more than 15
years of experience building Business Intelligence and data solutions — always
aiming to help teams find meaning in their data.&lt;/p&gt;
&lt;p&gt;My path has taken me from software development through BI consulting and a
spell leading the BI practice at Salsa — where I worked with QlikView and
Qlik Sense — to a period at DevScope on projects involving Snowflake, to where
I am today: working freelance as a Solution Data Architect with
&lt;a href="https://www.nosedat.com/en/"&gt;NoseDat&lt;/a&gt;, a German BI company. My focus is now
the modern Azure stack — Microsoft Fabric, Databricks, Power BI and DAX —
alongside infrastructure-as-code with Terraform. I&amp;rsquo;m currently a Microsoft
Certified: Fabric Data Engineer Associate.&lt;/p&gt;</description></item><item><title>Issues with v4l2loopback and OBS</title><link>https://fpvmorais.com/post/issues_with_v4l2loopback/</link><pubDate>Wed, 09 Jul 2025 00:00:00 +0100</pubDate><guid>https://fpvmorais.com/post/issues_with_v4l2loopback/</guid><description>&lt;p&gt;I started my Linux journey a long time ago with Red Hat in the middle
of the nineties and moved after to Slackware. Still to this day one of
my favourite distros. I tried Ubuntu for a shortwhile but found a new
home on Arch. It was my main distro for the better part of the 2010&amp;rsquo;s
but then tried Void Linux and it&amp;rsquo;s now my home since at least 3 years.&lt;/p&gt;</description></item><item><title>Tabular Editor Scripts: Simplifying Your Power BI Modeling Experience</title><link>https://fpvmorais.com/post/tabular_editor/</link><pubDate>Sun, 27 Apr 2025 10:23:00 +0100</pubDate><guid>https://fpvmorais.com/post/tabular_editor/</guid><description>&lt;p&gt;As a data enthusiast, I&amp;rsquo;m always on the lookout for ways to streamline
my workflow and make my life easier. In this post, I&amp;rsquo;ll be sharing two
Tabular Editor scripts that have saved me countless hours of manual
formatting in my Power BI projects.&lt;/p&gt;
&lt;p&gt;There are two versions of this software. To use the scripts below you only need version two.
This version is free and open source: &lt;a href="https://tabulareditor.github.io/TabularEditor/"&gt;https://tabulareditor.github.io/TabularEditor/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you have the money for the license you can support the author (Daniel Otykier) by buying the license for version 3:
&lt;a href="https://tabulareditor.com"&gt;https://tabulareditor.com&lt;/a&gt;&lt;/p&gt;</description></item><item><title>Extracting tables from SQL queries by using Sqlfluff</title><link>https://fpvmorais.com/post/table_extraction_sqlfluff/</link><pubDate>Sun, 03 Sep 2023 22:16:00 +0100</pubDate><guid>https://fpvmorais.com/post/table_extraction_sqlfluff/</guid><description>&lt;p&gt;I got an assignment the other day to produce documentation to send to
a customer. The extraction of the table names required to execute a
certain Databricks notebook was part of the task. The plan was to
build an object dependency tree.&lt;/p&gt;
&lt;p&gt;The query spanned 279 lines. How can you extract only the table names
from a file without having to manually look for them? Can we make use
of this technique again in the future?&lt;/p&gt;</description></item><item><title>Azure Active Directory extraction with Databricks</title><link>https://fpvmorais.com/post/aad_extraction_databricks/</link><pubDate>Mon, 08 May 2023 16:51:00 +0100</pubDate><guid>https://fpvmorais.com/post/aad_extraction_databricks/</guid><description>&lt;p&gt;During data engineering projects I tend to try and minimize the tools
being used. I think it&amp;rsquo;s a good practice. Having too many tools causes
sometimes for errors going unnoticed by the teams members.&lt;/p&gt;
&lt;p&gt;One of the advantages of having a tool like Databricks is that it
allows us to use all the power of &lt;code&gt;python&lt;/code&gt; and avoid, like I did in
the past, to have something like &lt;code&gt;Azure Functions&lt;/code&gt; to compensate for
the limitations of some platform.&lt;/p&gt;</description></item><item><title>List of errors from Databricks API</title><link>https://fpvmorais.com/post/error_log_databricks/</link><pubDate>Fri, 17 Feb 2023 11:01:00 +0000</pubDate><guid>https://fpvmorais.com/post/error_log_databricks/</guid><description>&lt;p&gt;I&amp;rsquo;m currently working on a project where I&amp;rsquo;m adapting a code base of
Databricks notebooks for a new client. There are a few errors to hunt
but the Web UI is not really friendly for this purpose.&lt;/p&gt;
&lt;p&gt;Just wanted a quick and easy way to not have to click around to find
the issues.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a quick script to just do that:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-python" data-lang="python"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;os&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;json&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="nn"&gt;configparser&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;databricks_cli.sdk.api_client&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ApiClient&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="nn"&gt;databricks_cli.runs.api&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;RunsApi&lt;/span&gt;
&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;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;print_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nb_path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nb_params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nb_run_url&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;nb_error&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;Unknown&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;nb_error&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;partition&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;)[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;params&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;loads&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;nb_params&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;nb_params&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="sa"&gt;f&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;Path: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;nb_path&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;Params: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;dumps&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;params&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="n"&gt;indent&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;RunUrl: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;nb_run_url&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;Error: &lt;/span&gt;&lt;span class="si"&gt;{&lt;/span&gt;&lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="si"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;&amp;#34;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&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;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;databricks_cfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;~/.databrickscfg&amp;#34;&lt;/span&gt;
&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;&lt;span class="n"&gt;conf&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configparser&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConfigParser&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;expanduser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;databricks_cfg&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&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;&lt;span class="n"&gt;api_client&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ApiClient&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;host&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;DEFAULT&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;host&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;token&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;conf&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;DEFAULT&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;password&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&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;&lt;span class="n"&gt;runs_api&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RunsApi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;api_client&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&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;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="nb"&gt;range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;101&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runs_api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;list_runs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;job_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;active_only&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;completed_only&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="kc"&gt;None&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;offset&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;25&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;2.1&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;runs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;runs&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;state&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;result_state&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;FAILED&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;z&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;runs_api&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;get_run_output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;run_id&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;run_id&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&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; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;error&amp;#34;&lt;/span&gt; &lt;span class="ow"&gt;in&lt;/span&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;print_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;task&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;notebook_task&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;notebook_path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;task&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;notebook_task&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;base_parameters&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Param1Value&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;run_page_url&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;error&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;else&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;print_error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;task&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;notebook_task&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;notebook_path&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;task&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;notebook_task&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;base_parameters&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="s2"&gt;&amp;#34;Param1Value&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="n"&gt;z&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;metadata&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;run_page_url&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Follow this &lt;a href="https://docs.databricks.com/dev-tools/cli/index.html"&gt;documentation&lt;/a&gt; to install the requirements. There&amp;rsquo;s
a lot more you can do with &lt;code&gt;databricks-cli&lt;/code&gt; to make your life easier.
It&amp;rsquo;s a great tool to add to your toolbox.&lt;/p&gt;</description></item><item><title>Calculating workdays in Databricks</title><link>https://fpvmorais.com/post/databricks_workdays/</link><pubDate>Thu, 05 Jan 2023 10:23:00 +0000</pubDate><guid>https://fpvmorais.com/post/databricks_workdays/</guid><description>&lt;p&gt;There&amp;rsquo;s not an official function to calculate workdays in Databricks.
Here are some solutions.&lt;/p&gt;
&lt;h2 id="having-a-dimcalendar-with-holidays-and-at-least-databricks-runtime-12"&gt;Having a DimCalendar with holidays and at least Databricks Runtime 12&lt;/h2&gt;
&lt;p&gt;If you have a DimCalendar in the system you can now do &lt;code&gt;LEFT LATERAL
JOIN&lt;/code&gt; without the correlated subquery errors when using non-equality
predicates. Check &lt;a href="https://issues.apache.org/jira/browse/SPARK-36114"&gt;SPARK-36114&lt;/a&gt; for more details.&lt;/p&gt;
&lt;p&gt;Calculating working days is then as simple as run a query like:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-sql" data-lang="sql"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EndDate&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Workdays&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;myTable&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mt&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LEFT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;JOIN&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;LATERAL&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;SELECT&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DateKey&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Workdays&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dimCalendar&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dc&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;WHERE&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StartDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;lt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DateKey&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;mt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;EndDate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;&amp;gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Datekey&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDayWeekDay&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;TRUE&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AND&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;dc&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IsDayHoliday&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;FALSE&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;If this query is slow, please check if the data types for the dates
columns match. All are &lt;code&gt;DATE&lt;/code&gt; or all are &lt;code&gt;TIMESTAMP&lt;/code&gt;. If the sluginess
remains check if any of the fields are not part of the statistics of
the table.&lt;/p&gt;</description></item><item><title>Mass changing power query connection strings in Excel using PowerShell</title><link>https://fpvmorais.com/post/mass_changing_power_query_connection_strings/</link><pubDate>Wed, 07 Dec 2022 10:33:00 +0000</pubDate><guid>https://fpvmorais.com/post/mass_changing_power_query_connection_strings/</guid><description>&lt;p&gt;A while ago I&amp;rsquo;ve received an email from &lt;a href="https://www.linkedin.com/in/jason-roy-alvarez-5b239789/"&gt;Jason Alvarez&lt;/a&gt; asking me if I
knew a way to change &lt;code&gt;Power Query&lt;/code&gt; connections inside an Excel file.
The problem is similar to my previous post on &lt;a href="https://fpvmorais.com/post/excel_powershell/"&gt;Mass changing pivot table
connection strings in Excel using PowerShell&lt;/a&gt;. Turns out you can and he was able to find this solution:&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;span class="lnt"&gt;16
&lt;/span&gt;&lt;span class="lnt"&gt;17
&lt;/span&gt;&lt;span class="lnt"&gt;18
&lt;/span&gt;&lt;span class="lnt"&gt;19
&lt;/span&gt;&lt;span class="lnt"&gt;20
&lt;/span&gt;&lt;span class="lnt"&gt;21
&lt;/span&gt;&lt;span class="lnt"&gt;22
&lt;/span&gt;&lt;span class="lnt"&gt;23
&lt;/span&gt;&lt;span class="lnt"&gt;24
&lt;/span&gt;&lt;span class="lnt"&gt;25
&lt;/span&gt;&lt;span class="lnt"&gt;26
&lt;/span&gt;&lt;span class="lnt"&gt;27
&lt;/span&gt;&lt;span class="lnt"&gt;28
&lt;/span&gt;&lt;span class="lnt"&gt;29
&lt;/span&gt;&lt;span class="lnt"&gt;30
&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-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#root path to the collection of excel docs:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$rootPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;C:\Temp\PowerQueryDemo\&amp;#34;&lt;/span&gt;
&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;&lt;span class="c"&gt;#Current query file path:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$currentPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;C:\Temp\PowerQueryDemo\&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;#Updated query file path:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$newPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;C:\Temp\PowerQueryDemo\PowerQueryNewSource&amp;#34;&lt;/span&gt;
&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;&lt;span class="nb"&gt;Get-ChildItem&lt;/span&gt; &lt;span class="n"&gt;-Path&lt;/span&gt; &lt;span class="nv"&gt;$rootPath&lt;/span&gt; &lt;span class="n"&gt;-Recurse&lt;/span&gt; &lt;span class="n"&gt;-Include&lt;/span&gt; &lt;span class="p"&gt;*.&lt;/span&gt;&lt;span class="n"&gt;xlsx&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;ForEach-Object&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;$docPath&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;FullName&lt;/span&gt;
&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; &lt;span class="c"&gt;## Create an instance of excel:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;$ExcelAppInstance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;New-Object&lt;/span&gt; &lt;span class="n"&gt;-ComObject&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Excel.Application&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;$ExcelAppInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Visible&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="vm"&gt;$false&lt;/span&gt;
&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; &lt;span class="c"&gt;## Open the workbook object within our Excel instance:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;$workbook&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$ExcelAppInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;workbooks&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$docPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&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; &lt;span class="c"&gt;##iterate the list of queries embedded in the workbook,&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="c"&gt;##updating the file path to our new one:&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;$workbook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Queries&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;ForEach-Object&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Write-Output&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Formula&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Write-output&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Formula&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$xPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$tPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Formula&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Formula&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$xPath&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="nv"&gt;$tPath&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&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; &lt;span class="nv"&gt;$workbook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Save&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;$workbook&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nv"&gt;$ExcelAppInstance&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&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 key here is the &lt;code&gt;Queries&lt;/code&gt; property inside the &lt;code&gt;Workbook&lt;/code&gt; object.&lt;/p&gt;</description></item><item><title>PBIPT #41 - Solving Wordle with Power BI</title><link>https://fpvmorais.com/post/solving_wordle_with_power_bi/</link><pubDate>Wed, 29 Jun 2022 09:32:00 +0100</pubDate><guid>https://fpvmorais.com/post/solving_wordle_with_power_bi/</guid><description>&lt;p&gt;Yesterday I had the pleasure to be back to in-person to give a
small fun presentation about bending Power BI to help us solve
Wordle puzzles.&lt;/p&gt;
&lt;p&gt;The content is in Portuguese but I will upload an English version
during this week.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s the link on GitHub where you can download the file:&lt;/p&gt;
&lt;p&gt;&lt;a href="https://github.com/fpvmorais/presentations"&gt;https://github.com/fpvmorais/presentations&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you have any questions please reach me.&lt;/p&gt;
&lt;p&gt;Have fun!&lt;/p&gt;</description></item><item><title>JavaException: Must have Java 8 or newer installed.</title><link>https://fpvmorais.com/post/must_have_java_8_or_newer/</link><pubDate>Sun, 24 Apr 2022 19:47:00 +0100</pubDate><guid>https://fpvmorais.com/post/must_have_java_8_or_newer/</guid><description>&lt;p&gt;While creating a new machine to be the Integration Runtime for
Purview and after I have installed the mandatory JRE that allows
the connection to Snowflake I kept getting this error:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;Error: (3913) JavaException: Must have Java 8 or newer installed.
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;This puzzled me because I had installed &lt;a href="https://adoptium.net/"&gt;version 17&lt;/a&gt;. Started
troubleshooting and followed this &lt;a href="https://docs.microsoft.com/en-us/troubleshoot/azure/general/error-run-copy-activity-azure#resolution"&gt;guide&lt;/a&gt; to check if the
installation was correct. Everything seemed alright but the error
was still there.&lt;/p&gt;</description></item><item><title>Python Azure Functions Tips</title><link>https://fpvmorais.com/post/python_azure_functions_tips/</link><pubDate>Sat, 16 Apr 2022 11:03:00 +0100</pubDate><guid>https://fpvmorais.com/post/python_azure_functions_tips/</guid><description>&lt;p&gt;Here are some tips of the things I&amp;rsquo;ve learned while creating them.&lt;/p&gt;
&lt;h2 id="app-plan"&gt;App Plan&lt;/h2&gt;
&lt;p&gt;If you already have an Windows &amp;lsquo;App Service Plan&amp;rsquo; you&amp;rsquo;ll need a
different &lt;a href="https://docs.microsoft.com/en-us/azure/azure-functions/create-first-function-cli-python?tabs=azure-cli%2Cbash%2Cbrowser"&gt;one for running Python&lt;/a&gt;.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;You can&amp;rsquo;t host Linux and Windows apps in the same resource group. If
you have an existing resource group named AzureFunctionsQuickstart-rg
with a Windows function app or web app, you must use a different
resource group.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="python-version"&gt;Python version&lt;/h2&gt;
&lt;p&gt;If you need to use &amp;lsquo;&lt;a href="https://pypi.org/project/azure-identity/"&gt;azure-identity&lt;/a&gt;&amp;rsquo; you&amp;rsquo;ll need to use python 3.8 instead of the 3.9 otherwise you&amp;rsquo;ll get:&lt;/p&gt;</description></item><item><title>Accessing local settings while unit testing Azure Functions</title><link>https://fpvmorais.com/post/azure_functions_unit_testing/</link><pubDate>Sat, 09 Apr 2022 16:45:00 +0100</pubDate><guid>https://fpvmorais.com/post/azure_functions_unit_testing/</guid><description>&lt;p&gt;There&amp;rsquo;s a lot to chew while unit testing Azure Functions. I going to
be quite liberal with the terminology because technically some of
this will be in fact integration testing and not unit testing per se.&lt;/p&gt;
&lt;p&gt;Either way, Azure Functions load the &lt;code&gt;local.settings.json&lt;/code&gt; on
startup, creating several environment variables that then we can use
in our code. In &lt;code&gt;C#&lt;/code&gt; we would access them like so:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-csharp" data-lang="csharp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;tenantId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configRoot&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;TenantId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="n"&gt;appId&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;configRoot&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;#34;AppId&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;or in &lt;code&gt;Python&lt;/code&gt;:&lt;/p&gt;</description></item><item><title>Add multiple scans using the Purview API</title><link>https://fpvmorais.com/post/addmultiplescanswithpurviewapi/</link><pubDate>Sun, 06 Feb 2022 19:02:00 +0000</pubDate><guid>https://fpvmorais.com/post/addmultiplescanswithpurviewapi/</guid><description>&lt;p&gt;As I explained in a &lt;a href="https://fpvmorais.com/post/snowflake-connector-at-purview/"&gt;previous post&lt;/a&gt; about Purview with the official
Snowflake connector you need to create a scan per database/schema
pair. In the customer where I was working there are a few hundred
databases plus their schemas.&lt;/p&gt;
&lt;p&gt;Doing this by using the UI would mean that we will be wasting a lot
of time clicking away and be prone to forget some database/schema
pair.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve explored the documentation about the &lt;a href="https://docs.microsoft.com/en-us/rest/api/purview/scanningdataplane/scans"&gt;Scans - REST API&lt;/a&gt; and the
rest of this post is just some &lt;code&gt;PowerShell&lt;/code&gt; code to automate the
creation of scans and their schedules in Purview.&lt;/p&gt;</description></item><item><title>Add user(s) to multiple Power BI workspaces quickly</title><link>https://fpvmorais.com/post/addusertomultipleworkspaces/</link><pubDate>Fri, 14 Jan 2022 17:28:00 +0000</pubDate><guid>https://fpvmorais.com/post/addusertomultipleworkspaces/</guid><description>&lt;p&gt;A few days ago I had to add a new team member to more that 50
workspaces. I started dying inside just thinking of going to each
workspace and add it using the portal ui.&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a little snippet that saved me a few hundred clicks:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Login-PowerBI&lt;/span&gt;
&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;&lt;span class="nv"&gt;$workspaces&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Get-PowerBIWorkSpace&lt;/span&gt;
&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;&lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;mySpecial.User@MyDomain.com&amp;#34;&lt;/span&gt;
&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;&lt;span class="k"&gt;foreach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$workspace&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="nv"&gt;$workspaces&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Write-Host&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Adding User to : &amp;#34;&lt;/span&gt; &lt;span class="nv"&gt;$workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Name&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;try&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Add-PowerBIWorkspaceUser&lt;/span&gt; &lt;span class="n"&gt;-Id&lt;/span&gt; &lt;span class="nv"&gt;$workspace&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Id&lt;/span&gt; &lt;span class="n"&gt;-UserPrincipalName&lt;/span&gt; &lt;span class="nv"&gt;$user&lt;/span&gt; &lt;span class="n"&gt;-AccessRight&lt;/span&gt; &lt;span class="n"&gt;Member&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;catch&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Write-Host&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;Message: [&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;&lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Exception&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Message&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="n"&gt;-ForegroundColor&lt;/span&gt; &lt;span class="n"&gt;Red&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Adapt it to your needs.&lt;/p&gt;</description></item><item><title>Snowflake Connector for Purview</title><link>https://fpvmorais.com/post/snowflake-connector-at-purview/</link><pubDate>Mon, 29 Nov 2021 09:58:13 +0000</pubDate><guid>https://fpvmorais.com/post/snowflake-connector-at-purview/</guid><description>&lt;p&gt;In the last few weeks I&amp;rsquo;ve been working with Purview doing some code
to integrate Snowflake entities because there wasn&amp;rsquo;t an official
connector. You can imagine my surprise when I&amp;rsquo;ve noticed last friday
that there&amp;rsquo;s a new unannounced preview connector that does the work
for us.&lt;/p&gt;
&lt;h2 id="pyapacheatlas"&gt;PyApacheAtlas&lt;/h2&gt;
&lt;p&gt;If you already read or watched something about the recommended way to
create custom entities on Purview you have heard something about this
library.&lt;/p&gt;</description></item><item><title>Deprecating Google Spreadsheets Custom Connector</title><link>https://fpvmorais.com/post/deprecating-google-sheets-custom-connector/</link><pubDate>Mon, 22 Nov 2021 11:30:31 +0000</pubDate><guid>https://fpvmorais.com/post/deprecating-google-sheets-custom-connector/</guid><description>&lt;h1 id="theres-now-an-official-connector-to-google-spreadsheets-on-power-bi"&gt;There&amp;rsquo;s now an official connector to Google Spreadsheets on Power BI&lt;/h1&gt;
&lt;p&gt;With the November 2021 Power BI release, came the official connector
support for Google Spreadsheets from Microsoft. As such there&amp;rsquo;s no
more need for my custom connector. The repository on
&lt;a href="https://github.com/fpvmorais/PQGoogleSpreadsheet"&gt;GitHub&lt;/a&gt; is now archived.&lt;/p&gt;
&lt;h3 id="no-more-relationship-tag-contains-incorrect-attribute-line-2-position-86"&gt;No more &lt;code&gt;Relationship tag contains incorrect attribute. Line 2, position 86&lt;/code&gt;&lt;/h3&gt;
&lt;p&gt;During the last week I&amp;rsquo;ve tested it so see if it had the same
limitations as mine had and I&amp;rsquo;m happy to report the XML errors when
trying to import data from a Google Sheet with a pivot table don&amp;rsquo;t
occur in the new one. No more having to create a proxy file and use
the
&lt;a href="https://support.google.com/docs/answer/3093340?hl=en"&gt;&lt;code&gt;IMPORTRANGE&lt;/code&gt;&lt;/a&gt;
function.&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 16</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day16/</link><pubDate>Sat, 17 Apr 2021 17:25:00 +0100</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day16/</guid><description>&lt;p&gt;Today&amp;rsquo;s puzzle is called &lt;a href="https://adventofcode.com/2020/day/16"&gt;&amp;lsquo;Ticket Translation&amp;rsquo;&lt;/a&gt;. We have a bunch of
fields in a language we do not understand and we need to figure out
which is which.&lt;/p&gt;
&lt;p&gt;There&amp;rsquo;s a set of rules we collected in several ways to a document that
will serve as the puzzle input.&lt;/p&gt;
&lt;p&gt;If you want to follow along please download &lt;a href="https://fpvmorais.com/AdventOfCode2020/AdventOfCode2020.pbit"&gt;AdventOfCode2020.pbit&lt;/a&gt; and
check &lt;a href="https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day1/#conclusion"&gt;Day 1 post&lt;/a&gt; for instructions.&lt;/p&gt;
&lt;h2 id="part-1"&gt;Part 1&lt;/h2&gt;
&lt;p&gt;Our input file is divided into three sections separated by a blank line:&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 15</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day15/</link><pubDate>Fri, 02 Apr 2021 19:07:00 +0100</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day15/</guid><description>&lt;p&gt;Rambunctious Recitation is number game that follows the rules of the
&lt;a href="https://ibmathsresources.com/2019/06/12/the-van-eck-sequence/"&gt;Van Eck&lt;/a&gt; sequence. Here&amp;rsquo;s a great &lt;a href="https://youtu.be/etMJxB-igrc"&gt;video&lt;/a&gt; from the Numberphile channel on
YouTube about it. And here start our troubles because it seems no one
has yet found an efficient algorithm for generating this sequence. We
will really need to brute force it.&lt;/p&gt;
&lt;p&gt;How can we resolve this predicament with the tools available to us?&lt;/p&gt;
&lt;p&gt;If you want to follow along please download &lt;a href="https://fpvmorais.com/AdventOfCode2020/AdventOfCode2020.pbit"&gt;AdventOfCode2020.pbit&lt;/a&gt; and
check &lt;a href="https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day1/#conclusion"&gt;Day 1 post&lt;/a&gt; for instructions.&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 14</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day14/</link><pubDate>Sun, 21 Mar 2021 22:09:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day14/</guid><description>&lt;p&gt;The troubles are far from over, this time it&amp;rsquo;s the docking program on
the ferry that&amp;rsquo;s not compatible with the port computer system. We need
to emulate the port&amp;rsquo;s software by using a bitmasking system to figure
out the correct instructions. Let&amp;rsquo;s see if we are able to implement
this logic with Power BI.&lt;/p&gt;
&lt;p&gt;If you want to follow along please download &lt;a href="https://fpvmorais.com/AdventOfCode2020/AdventOfCode2020.pbit"&gt;AdventOfCode2020.pbit&lt;/a&gt; and
check &lt;a href="https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day1/#conclusion"&gt;Day 1 post&lt;/a&gt; for instructions.&lt;/p&gt;
&lt;h2 id="part-1"&gt;Part 1&lt;/h2&gt;
&lt;p&gt;As usual there&amp;rsquo;s a file with a set of instructions. Some lines refer
to memory addresses and others to bitmasks. We need to apply the mask
to the values stored in the memory addresses beneath it until we reach
the next mask repeating the process to the end of the file.&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 13</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day13/</link><pubDate>Sun, 28 Feb 2021 18:00:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day13/</guid><description>&lt;p&gt;We arrived to the island after the ferry trip and we see ourselves in
need of transportation to the nearest airport. Fortunately there&amp;rsquo;s a
shuttle bus service between the sea port and the airport that could
take us there.&lt;/p&gt;
&lt;p&gt;Day 13 is a wonderful mathematical puzzle, following the theme of
modular arithmetic of the previous one. Let&amp;rsquo;s dive into it as there
some surprises with the numeric limits on Power BI.&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 12</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day12/</link><pubDate>Sun, 21 Feb 2021 18:22:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day12/</guid><description>&lt;p&gt;After the waiting room we are at a ferry navigating to the island.
There seems to be a problem with the navigation system, and we
volunteered to help. We have a set of instructions and we need to make
some sense of them to help the captain circumvent the storm.&lt;/p&gt;
&lt;p&gt;The solution to the problem will be given by calculating the &lt;a href="https://en.wikipedia.org/wiki/Manhattan%5Fdistance"&gt;Manhattan
distance&lt;/a&gt; (sum of the absolute values of its east/west position and its
north/south position).&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 11</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day11/</link><pubDate>Sat, 20 Feb 2021 17:28:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day11/</guid><description>&lt;p&gt;Today&amp;rsquo;s puzzle title is &lt;a href="https://adventofcode.com/2020/day/11"&gt;&amp;ldquo;Seating System&amp;rdquo;&lt;/a&gt; but it&amp;rsquo;s actually a variation
of a well known zero-player game called &lt;a href="https://en.wikipedia.org/wiki/Conway%27s%5FGame%5Fof%5FLife"&gt;Conway&amp;rsquo;s Game of Life&lt;/a&gt;. Many of
us may recall this game as a popular choice for work assignments in
computer science courses.&lt;/p&gt;
&lt;p&gt;Dr. John Conway, the English mathematician who created this game was
last year a victim of COVID-19. If you want to know a little more
about him you can read this &lt;a href="https://www.nytimes.com/2020/12/28/science/math-conway-game-of-life.html"&gt;article&lt;/a&gt; that was featured this week on
&lt;a href="https://news.ycombinator.com/news"&gt;Hacker News&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 10</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day10/</link><pubDate>Sun, 14 Feb 2021 18:20:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day10/</guid><description>&lt;p&gt;Day 10 puzzle brings us an array of adapters. In the first part we
will need to find the number of differences of 1 and 3 jolts. Part two
asks us to find the total number of distinct ways in which we can arranje
the adapters to connect the device to the charging outlet.&lt;/p&gt;
&lt;p&gt;If you want to follow along please download &lt;a href="https://fpvmorais.com/AdventOfCode2020/AdventOfCode2020.pbit"&gt;AdventOfCode2020.pbit&lt;/a&gt; and
check &lt;a href="https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day1/#conclusion"&gt;Day 1 post&lt;/a&gt; for instructions.&lt;/p&gt;
&lt;h2 id="part-1"&gt;Part 1&lt;/h2&gt;
&lt;p&gt;After reading that long text, we can see in the example given that all
we have to do is:&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 9</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day9/</link><pubDate>Sun, 07 Feb 2021 18:52:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day9/</guid><description>&lt;p&gt;This puzzle looks a lot like &lt;a href="https://adventofcode.com/2020/day/1"&gt;day 1&lt;/a&gt;. We have a list of numbers and need
to do some operations that will return some big numbers.&lt;/p&gt;
&lt;p&gt;Let&amp;rsquo;s try to &lt;code&gt;DAX&lt;/code&gt; out them.&lt;/p&gt;
&lt;p&gt;If you want to follow along please download &lt;a href="https://fpvmorais.com/AdventOfCode2020/AdventOfCode2020.pbit"&gt;AdventOfCode2020.pbit&lt;/a&gt; and
check &lt;a href="https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day1/#conclusion"&gt;Day 1 post&lt;/a&gt; for instructions.&lt;/p&gt;
&lt;h2 id="part-1"&gt;Part 1&lt;/h2&gt;
&lt;p&gt;We have a list of numbers of each the first 25 are a preamble. After
this, any number can be calculated as a sum of any pair of numbers in
that interval.&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 8</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day8/</link><pubDate>Sun, 07 Feb 2021 12:29:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day8/</guid><description>&lt;p&gt;In day 8 we find a some weird infinite loop on a handheld device. To
fix this problem we are asked to create a program that goes trough a
stack of instructions.&lt;/p&gt;
&lt;style&gt;.codeaa { display: inline-block; width: 126px; text-align: center; }&lt;/style&gt;
&lt;div class="codeaa"&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;nop +0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;acc +1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;jmp +4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;acc +3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;jmp -3
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;acc -99
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;acc +1
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;jmp -4
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;acc +6
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;And after we find where the infinite loop is located we replace the
bad command with the correct instruction.&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 7</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day7/</link><pubDate>Sun, 31 Jan 2021 12:47:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day7/</guid><description>&lt;p&gt;&lt;a href="https://adventofcode.com/2020/day/7"&gt;Day 7: Handy Haversacks&lt;/a&gt; is the hardest puzzle to solve using only
Power BI until now. It took me a lot of time to find a viable and fast
solution.&lt;/p&gt;
&lt;p&gt;I have first tried to solve this using &lt;code&gt;DAX&lt;/code&gt; &lt;a href="https://dax.guide/path/"&gt;&lt;code&gt;PATH&lt;/code&gt;&lt;/a&gt; but had issues
with the different levels of recursion. It was possible in the real
data input for the same bag to be child of different bags in different
levels. Only after a deep dive on using the &lt;a href="https://www.powerquery.io/list/list.generate"&gt;&lt;code&gt;List.Generate&lt;/code&gt;&lt;/a&gt; a light
began to appear on the end of the tunnel.&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 6</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day6/</link><pubDate>Sun, 24 Jan 2021 15:46:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day6/</guid><description>&lt;p&gt;Time to check for some custom declarations forms. In the first part
we will check the distinct number of questions anyone on each group
answered &amp;ldquo;yes&amp;rdquo;, and on the second part the questions where everyone
gave a positive response.&lt;/p&gt;
&lt;p&gt;If you want to follow along please download &lt;a href="https://fpvmorais.com/AdventOfCode2020/AdventOfCode2020.pbit"&gt;AdventOfCode2020.pbit&lt;/a&gt; and
check &lt;a href="https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day1/#conclusion"&gt;Day 1 post&lt;/a&gt; for instructions.&lt;/p&gt;
&lt;h2 id="part-1"&gt;Part 1&lt;/h2&gt;
&lt;p&gt;The input for this problem is very similar to the &lt;a href="https://fpvmorais.com/post/advent%5Fof%5Fcode%5Fwith%5Fpower%5Fbi%5F2020%5Fday4/"&gt;passports&lt;/a&gt; we have seen on day 4.
We have several lines that represent the answers of the persons in a group and the groups
are separated by a blank line.&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 5</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day5/</link><pubDate>Sat, 23 Jan 2021 15:59:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day5/</guid><description>&lt;p&gt;This &lt;a href="https://adventofcode.com/2020/day/5"&gt;problem&lt;/a&gt; seems a lot of work at first but in reality it&amp;rsquo;s just binary number conversion to decimal.&lt;/p&gt;
&lt;p&gt;Picking up the provided example:&lt;/p&gt;
&lt;style&gt;.codeaa { display: inline-block; width: 106px; text-align: center; }&lt;/style&gt;
&lt;div class="codeaa"&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;FBFBBFF RLR
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;If we replace the lower half &lt;code&gt;[F, L]&lt;/code&gt; by 0, and the upper half &lt;code&gt;[B, R]&lt;/code&gt; by 1 we get:&lt;/p&gt;
&lt;style&gt;.codeaa { display: inline-block; width: 20%; text-align: center; }&lt;/style&gt;
&lt;div class="codeaa"&gt;
&lt;div&gt;&lt;/div&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-text" data-lang="text"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;0101100 101
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;Doing the conversions:&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 4</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day4/</link><pubDate>Fri, 22 Jan 2021 18:58:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day4/</guid><description>&lt;p&gt;Day 4 is about passport fields validation. In part 1 we need to check
if all the fields exist and in part 2 check if they are valid.&lt;/p&gt;
&lt;p&gt;This seems like a job where the heavy lifting should be made by &lt;code&gt;Power Query&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://adventofcode.com/2020/day/4"&gt;https://adventofcode.com/2020/day/4&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you want to follow along please download &lt;a href="https://fpvmorais.com/AdventOfCode2020/AdventOfCode2020.pbit"&gt;AdventOfCode2020.pbit&lt;/a&gt; and
check &lt;a href="https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day1/#conclusion"&gt;Day 1 post&lt;/a&gt; for instructions.&lt;/p&gt;
&lt;h2 id="part-1"&gt;Part 1&lt;/h2&gt;
&lt;p&gt;&lt;a id="orgdb0c3ea"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Following this strategy we load the data to our file and we find our
first challenge. &amp;ldquo;Each passport is represented as a sequence of
key:value pairs separated by spaces or newlines. Passports are
separated by blank lines.&amp;rdquo;&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 3</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day3/</link><pubDate>Wed, 20 Jan 2021 20:31:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day3/</guid><description>&lt;p&gt;Now we need to check for trees in paths. The interesting bit is that
the path can grow &lt;em&gt;ad infinitum&lt;/em&gt; to the right.&lt;/p&gt;
&lt;p&gt;Check the details at &lt;a href="https://adventofcode.com/2020/day/3"&gt;https://adventofcode.com/2020/day/3&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;If you want to follow along please download &lt;a href="https://fpvmorais.com/AdventOfCode2020/AdventOfCode2020.pbit"&gt;AdventOfCode2020.pbit&lt;/a&gt; and
check &lt;a href="https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day1/#conclusion"&gt;Day 1 post&lt;/a&gt; for instructions.&lt;/p&gt;
&lt;h2 id="part-1"&gt;Part 1&lt;/h2&gt;
&lt;p&gt;How do we avoid repeating the pattern? Looking at the provided sample we have:&lt;/p&gt;
&lt;link href='http://fonts.googleapis.com/css?family=Source+Code+Pro:300&amp;subset=latin,latin-ext' rel='stylesheet' type='text/css'/&gt;
&lt;style&gt;
codeaa {
position: relative;
display: inline-block;
margin: 0;
background: #10101a;
padding: 0;
font-weight: bold;
color: #ffffff;
font-size: x-large;
font-family: "Source Code Pro", monospace;
}
&lt;/style&gt;
&lt;div&gt;
&lt;codeaa&gt;
..##.......&lt;br&gt;
#...#...#..&lt;br&gt;
.#....#..#.&lt;br&gt;
..#.#...#.#&lt;br&gt;
.#...##..#.&lt;br&gt;
..#.##.....&lt;br&gt;
.#.#.#....#&lt;br&gt;
.#........#&lt;br&gt;
#.##...#...&lt;br&gt;
#...##....#&lt;br&gt;
.#..#...#.#&lt;br&gt;
&lt;/codeaa&gt;
&lt;/div&gt;
&lt;p&gt;The interesting part begins after line 3, where we are going to need
to get positions that are over the length of the row. The value that
we wish for row 4 is 1, which is the value of the remainder of
dividing 12 by the lenth of the track which is 11. Adding a new column
with the remainder we can crosscheck with our data and everything
seems to work:&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 2</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day2/</link><pubDate>Sun, 17 Jan 2021 21:34:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day2/</guid><description>&lt;p&gt;We are at an toboggan rental shop and we need to help the shopkeeper
to validate a bunch of corrupted passwords.&lt;/p&gt;
&lt;p&gt;(If you want to follow along please download &lt;a href="https://fpvmorais.com/AdventOfCode2020/AdventOfCode2020.pbit"&gt;AdventOfCode2020.pbit&lt;/a&gt; and
check &lt;a href="https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day1/#conclusion"&gt;Day 1 post&lt;/a&gt; for instructions)&lt;/p&gt;
&lt;h2 id="part-1"&gt;Part 1&lt;/h2&gt;
&lt;p&gt;In part one we need to check if a given character occurs between a
certain lower and upper bound.&lt;/p&gt;
&lt;p&gt;This kind of operation seems to be more suited to be done in &lt;code&gt;Power
Query&lt;/code&gt; as we are going row by row checking for the validity of the
rule. My idea here is to create a column with value of 1 if the
password is valid and 0 otherwise.&lt;/p&gt;</description></item><item><title>Advent of Code 2020 - Day 1</title><link>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day1/</link><pubDate>Sat, 16 Jan 2021 17:35:00 +0000</pubDate><guid>https://fpvmorais.com/post/advent_of_code_with_power_bi_2020_day1/</guid><description>&lt;p&gt;This will be the first post of a series where I hope to be able to
solve the problems from the &lt;a href="https://adventofcode.com/"&gt;Advent of Code&lt;/a&gt; using only Power BI.&lt;/p&gt;
&lt;p&gt;This event, sadly, only came to my attention this year. It started in
2015 and it&amp;rsquo;s a lot of fun. In these posts I will talk about my
thinking and strategy to try and solve these problems.&lt;/p&gt;
&lt;p&gt;Without further ado let&amp;rsquo;s get started:&lt;/p&gt;</description></item><item><title>Google Spreadsheets Custom Connector</title><link>https://fpvmorais.com/post/google-spreadsheets-custom-connector/</link><pubDate>Wed, 26 Feb 2020 09:36:30 +0000</pubDate><guid>https://fpvmorais.com/post/google-spreadsheets-custom-connector/</guid><description>&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;⚠ WARNING: The content of this post has been made deprecated due to the availability of the official Google Sheets connector and you should use that feature to import the data. ⚠&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Check the official announcement on the link below:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;a href="https://powerbi.microsoft.com/en-us/blog/power-bi-november-2021-feature-summary/#post-17912-_Toc87473946"&gt;https://powerbi.microsoft.com/en-us/blog/power-bi-november-2021-feature-summary/#post-17912-_Toc87473946&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;This post is just for future reference&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;h1 id="in-the-beggining"&gt;In the beggining&lt;/h1&gt;
&lt;p&gt;I&amp;rsquo;ve been tasked to find a way of exporting data from Google
Spreadsheets for a client. I&amp;rsquo;ve started researching for an already
working solution and got to the following links:&lt;/p&gt;</description></item><item><title>Import data from another Power BI dataset</title><link>https://fpvmorais.com/post/import_data_from_another_powerbi_dataset/</link><pubDate>Mon, 24 Feb 2020 09:14:52 +0000</pubDate><guid>https://fpvmorais.com/post/import_data_from_another_powerbi_dataset/</guid><description>&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;hr&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th style="text-align: center"&gt;⚠ WARNING: The content of this post has been made deprecated due to the availability of composite models and you should use that awesome feature to import the data. ⚠&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;Check the official announcement on the link below:&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;&lt;a href="https://powerbi.microsoft.com/en-us/blog/directquery-for-power-bi-datasets-and-azure-analysis-services-preview/"&gt;https://powerbi.microsoft.com/en-us/blog/directquery-for-power-bi-datasets-and-azure-analysis-services-preview/&lt;/a&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td style="text-align: center"&gt;This post is just for future reference&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;p&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;&lt;/p&gt;
&lt;p&gt;While I was working with a client they were trying to import data from another Power BI dataset to their file and they got this error:&lt;/p&gt;</description></item><item><title>Emacs Major Modes for Power BI</title><link>https://fpvmorais.com/post/emacs-major-modes-for-power-bi/</link><pubDate>Wed, 22 Jan 2020 13:53:10 +0000</pubDate><guid>https://fpvmorais.com/post/emacs-major-modes-for-power-bi/</guid><description>&lt;h1 id="emacs-major-modes-for-power-bi"&gt;Emacs Major Modes for Power BI&lt;/h1&gt;
&lt;p&gt;After many years of using Vim I finally understood the Emacs way. What
I was trying to do all along was trying to make Vim behave exactly
like Emacs.&lt;/p&gt;
&lt;p&gt;To celebrate this I made some &lt;strong&gt;bad&lt;/strong&gt; Elisp code and shared it on
GitHub. I based my code on the &lt;a href="http://ergoemacs.org/emacs/elisp_syntax_coloring.html"&gt;Simple Emacs Major Mode for Syntax
Coloring&lt;/a&gt; by
&lt;a href="https://twitter.com/ErgoEmacs"&gt;Xah Lee&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="power-query-mode"&gt;Power Query Mode&lt;/h2&gt;
&lt;p&gt;This mode gives you syntax coloring and code completion inside Emacs.
It has all the functions listed by &lt;code&gt;'#shared'&lt;/code&gt; and color codes them.
For more details on listing all Power Query functions you can check the
&lt;a href="https://radacad.com/how-to-get-list-of-all-functions-and-invoke-them-in-power-query"&gt;post&lt;/a&gt;
from &lt;a href="https://twitter.com/RADACAD_COM"&gt;RADACAD&lt;/a&gt;.&lt;/p&gt;</description></item><item><title>Diffing Power BI files</title><link>https://fpvmorais.com/post/powerbi_diff/</link><pubDate>Sun, 02 Jun 2019 14:39:06 +0100</pubDate><guid>https://fpvmorais.com/post/powerbi_diff/</guid><description>&lt;h1 id="do-you-really-can-diff-power-bi-files"&gt;Do you really can diff Power BI files?&lt;/h1&gt;
&lt;p&gt;While working with some customers a few times this question came up: &lt;strong&gt;&amp;ldquo;How
can I diff my current file with a older one? I really want to compare
my files, to know what changed from one to another.&amp;rdquo;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Many many people working with Power BI end up with a directory full
of files looking like: &lt;em&gt;&amp;ldquo;myPowerBIFileV1.pbix&amp;rdquo;,
&amp;ldquo;myPowerbifilev2.pbix&amp;rdquo;&amp;hellip; &amp;ldquo;myPowerbifilevN.pbix&amp;rdquo;&lt;/em&gt;. The scenario wull
get worse if we have two or more people working in the same file, and
until recently my answer was always the same: &amp;ldquo;You can&amp;rsquo;t&amp;rdquo;.&lt;/p&gt;</description></item><item><title>EzApi - Define flat file columns from connection string</title><link>https://fpvmorais.com/post/ezapi_define_columns_flat_file/</link><pubDate>Thu, 25 Apr 2019 16:08:33 +0100</pubDate><guid>https://fpvmorais.com/post/ezapi_define_columns_flat_file/</guid><description>&lt;h1 id="so-whats-new"&gt;So what&amp;rsquo;s new?&lt;/h1&gt;
&lt;p&gt;Thanks to the contribution via GitHub from &lt;a href="https://github.com/HadiFadl"&gt;Hadi
Fadl&lt;/a&gt; there&amp;rsquo;s a new method available for
the flat file connection manager that adds the existing columns in the
source file. This is very handy because in the past you would have to
define each and every column that existed in the flat file.&lt;/p&gt;
&lt;p&gt;I&amp;rsquo;ve updated the &lt;a href="https://www.nuget.org/packages/EzAPI/"&gt;nuget&lt;/a&gt; to version 0.8.93.&lt;/p&gt;
&lt;p&gt;Please give me your feedback of anything you might think should be improved.&lt;/p&gt;</description></item><item><title>EzApi - Adding Event Handlers</title><link>https://fpvmorais.com/post/ezapieventhandler/</link><pubDate>Tue, 19 Jun 2018 09:16:56 +0100</pubDate><guid>https://fpvmorais.com/post/ezapieventhandler/</guid><description>&lt;h2 id="how-to-add-event-handlers-to-generated-packages"&gt;How to add event handlers to generated packages&lt;/h2&gt;
&lt;p&gt;I had a request to give an example of adding event handlers to a generated SSIS package. The code is quite convoluted. There&amp;rsquo;s no method to initialize a &lt;code&gt;DtsEventHandler&lt;/code&gt;, you need to cast it after adding to the package with a &lt;code&gt;String&lt;/code&gt; describing the type of event. Here&amp;rsquo;s a list of the available events:&lt;/p&gt;
&lt;p&gt;&lt;img alt="List of event types" loading="lazy" src="https://fpvmorais.com/eventHandlerOptions.png"&gt;&lt;/p&gt;
&lt;p&gt;Here&amp;rsquo;s a sample of how to do insert a &lt;code&gt;ExecuteSQLTask&lt;/code&gt; to a event handler using a small console application:&lt;/p&gt;</description></item><item><title>Openssh Windows 10 Issues</title><link>https://fpvmorais.com/post/openssh_windows/</link><pubDate>Mon, 07 May 2018 12:57:12 +0100</pubDate><guid>https://fpvmorais.com/post/openssh_windows/</guid><description>&lt;h2 id="warning-unprotected-private-key-file"&gt;Warning: Unprotected Private Key File&lt;/h2&gt;
&lt;p&gt;As an avid user of OpenSSH on Windows after last update I&amp;rsquo;ve started seen this on my PowerShell:&lt;/p&gt;
&lt;pre style="white-space:pre-wrap;" class="language-powershell line-numbers"&gt;&lt;code&gt;
Windows PowerShell
Copyright (C) Microsoft Corporation. All rights reserved.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: UNPROTECTED PRIVATE KEY FILE! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Permissions for 'C:\\Users\\My User/.ssh/id_rsa' are too open.
&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id="file-system-security-powershell-module"&gt;File System Security PowerShell Module&lt;/h2&gt;
&lt;p&gt;Because file and folder permissions are not easy with PowerShell I&amp;rsquo;m using the &lt;a href="https://gallery.technet.microsoft.com/scriptcenter/1abd77a5-9c0b-4a2b-acef-90dbb2b84e85"&gt;File System Security PowerShell Module&lt;/a&gt;. You can install from the gallery using the command:&lt;/p&gt;</description></item><item><title>EzApi 0.8.92</title><link>https://fpvmorais.com/post/ezapi_0_8_92/</link><pubDate>Fri, 04 May 2018 12:57:41 +0100</pubDate><guid>https://fpvmorais.com/post/ezapi_0_8_92/</guid><description>&lt;h2 id="new-release-0982"&gt;New Release 0.9.82&lt;/h2&gt;
&lt;p&gt;My small contribution for the BI world has been this SSIS generation framework resurrection. Amazingly it has almost 1500 downloads &lt;a href="https://www.nuget.org/packages/EzApi/0.8.92"&gt;@NuGet&lt;/a&gt;.
We are using this &lt;a href="http://www.devscope.net"&gt;@DevScope&lt;/a&gt; for creating our SSIS packages based on metadata and it&amp;rsquo;s on production on some of our clients.&lt;/p&gt;
&lt;p&gt;We can see the rest of the details at the project &lt;a href="https://github.com/fpvmorais/EzApi2016"&gt;repository&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id="the-future"&gt;The Future&lt;/h2&gt;
&lt;p&gt;I finally managed to move to a new house and I will have (hopefully) more time to write on the blog and to continue to work on this side project.&lt;/p&gt;</description></item><item><title>Mass changing pivot table connection strings in Excel using PowerShell</title><link>https://fpvmorais.com/post/excel_powershell/</link><pubDate>Sat, 20 Jan 2018 18:22:21 +0000</pubDate><guid>https://fpvmorais.com/post/excel_powershell/</guid><description>&lt;h2 id="the-problem"&gt;The Problem&lt;/h2&gt;
&lt;p&gt;As Business Intelligence consultants after a migration to a brand new server inevitably we get asked by the users: &amp;ldquo;Do why have to redo all my pivot tables in Excel again? All my workbooks stopped working&amp;hellip;&amp;rdquo;&lt;/p&gt;
&lt;p&gt;Well, they can but they don&amp;rsquo;t need to. Where&amp;rsquo;s a simple code to replace the part that matters. This will iterate all the Excel files in the folder where the Powershell Script is located and and apply the substitution to all the OLEDBConnections that exist in each file:&lt;/p&gt;</description></item><item><title>Using Powershell to read and modify SSIS packages</title><link>https://fpvmorais.com/post/ssis_powershell/</link><pubDate>Tue, 28 Nov 2017 20:10:47 +0000</pubDate><guid>https://fpvmorais.com/post/ssis_powershell/</guid><description>&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;In these days developing in SSIS, you should be using a generation framework (&lt;a href="http://bimlscript.com/"&gt;BIML&lt;/a&gt; or &lt;a href="https://www.nuget.org/packages/EzApi"&gt;EzApi&lt;/a&gt;. The benefits era a bit obvious:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Your packages will have consistent layout and logic&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s easy and fast to apply the same change to all packages&lt;/li&gt;
&lt;li&gt;No more mouse programming (almost :))&lt;/li&gt;
&lt;li&gt;It&amp;rsquo;s the right way to do metadata driven ETL&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="the-problem"&gt;The problem&lt;/h2&gt;
&lt;p&gt;In a client I had a project with 97 packages. Each one of them started as copy of the first one. The request was to change the value of a single variable on all of them.&lt;/p&gt;</description></item><item><title>How to access SFTP with SSIS using SSH.NET</title><link>https://fpvmorais.com/post/ssis_sftp/</link><pubDate>Wed, 06 Sep 2017 16:34:25 +0100</pubDate><guid>https://fpvmorais.com/post/ssis_sftp/</guid><description>Tutorial to download from SFTP in Integration Services</description></item><item><title>Hello World</title><link>https://fpvmorais.com/post/hello_world/</link><pubDate>Mon, 04 Sep 2017 15:58:01 +0100</pubDate><guid>https://fpvmorais.com/post/hello_world/</guid><description>&lt;p&gt;Inspired by this &lt;a href="http://sqlblog.com/blogs/andy_leonard/archive/2017/03/22/please-blog.aspx/"&gt;post&lt;/a&gt; I&amp;rsquo;ve decided to start this blog.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Thank you&lt;/strong&gt; &lt;a href="http://andyleonard.blog/"&gt;Andy&lt;/a&gt; for all the times you&amp;rsquo;ve helped me without even knowing it :)&lt;/p&gt;</description></item><item><title>Contact</title><link>https://fpvmorais.com/contact/</link><pubDate>Fri, 01 Sep 2017 00:00:00 +0000</pubDate><guid>https://fpvmorais.com/contact/</guid><description>How to contact me</description></item></channel></rss>