Reading Notes #220

Logic-AppSuggestion of the week


Cloud


Programming


Data

Book

  • Software Development Book Giveaway! - Cool! A great opportunity, 3 free books are given: Building Microservices, Working Effectively with Legacy Code, and Javascript: The Good Parts.

Miscellaneous



Reading Notes #219

AzureSDK2-8-2Suggestion of the week


Cloud


Programming


Books



Reading Notes #218

GuyAndErikSuggestion of the week


Cloud


Programming


Data



Reading Notes #217

yoman_asciiSuggestion of the week


Cloud


Programming


Miscellaneous



Reading Notes #216

2016-01-10_2136Cloud


Programming


Data


Podcast

  • .NET Rocks! vNext - Really interesting podcast episode. I think it's the clearer and more comprehensible explanation of Git I have ever eared.

Miscellaneous





Reading Notes #215

Reading on the roadCloud


Programming


Data


Miscellaneous



Reading Notes #214

Suggestion of the week

  • Express - This is the perfect post to get started with node.js with Azure. This post starts with you step by step from a vanilla computer running OS X or Linux to your first App.

Cloud


Programming


Data


Miscellaneous



Reading Notes #213

Cloud


Programming


Databases



Reading Notes #212

2015-12-07_0722Cloud


Programming



Simple as Azure Marketplace

It happens to all of us, we need to have something done, and we needed for yesterday. In these times, we struggle, we don’t know where to start or worse, what to do. My grand-mother use to say: “When I don’t know what to cook, I always start by a sauté of onions. It’s smell so good it helps me to get started." In this post, I will show you my “sauté of onions” tips to get an environment up and running quickly.

Everybody knows that when you are looking for something for your mobile device you just need to go the  “App Store”. But did you know Microsoft Azure has his own store? It’s called the Azure Marketplace .

Your online store for thousands of certified, open source, and
community software applications, developer services, and
data—pre-configured for Microsoft Azure. Download, deploy, and get
more done.
It's not containing two or three hundred of items but more than three thousand five hundred. Yes, that right, more than 3500! Whether you need a virtual machine, a web application, or a web API, great chance it will be available in the Marketplace. And it’s still continued to grow day after day.

It’s easy to think that we can “pop” and WordPress website in less then 5 minutes. It’s also true that creating a brand-new virtual machine, with a vanilla Windows server or Linux, is only few clicks. Moreover, many much more complex solutions could be created in the same way.

1, 2, 3, CommVault Simpana

Recently, I needed to find a fast and easy way to create a solution to provide data management that is easily accessible regardless of location. A quick search in the Azure Marketplace shows me all the different options I had. I know that  Simpana is a great product so let’s use this one.

AzureMarketSearch

When an item is selected from the search list in the Azure Marketplace, the detail view is presented. This page contains all the information: prices, sizes, documentation and references.
Let’s start! Press the big green “Create Virtual Machine” button on the top of the screen. That will open the Microsoft Azure Portal with the blade ready to create your Simpana. An active Azure subscription is required, if you don’t have one get started it one-month Free here. At the bottom of the page, you will need to select the deployment mode. I strongly suggested to select the Resource Manager, because it provides more flexibility to manage the resource once you have it created. When you are ready click the Create button.

Step_1-3_create

The first and second step, ask about the basics information: name, subscription, resource group, location and the size. The third step should be already populated base on the information you entered, but feel free to change it if you wish. The two next steps are just to be sure you understand the billing, and a summarize de new deployment.

commvault-_RG

When all the steps are completed, the portal will start the deployment of our solution. After few minutes, it should be done, and if you open the resource group, we can see all the deployed and configured items.

Simpana_and_Console_Applications

By selecting the Virtual Machine in the resource group, it will provide a Connect option. Click on it  to download a Remote Desktop connection. Once connected, click the Start Menu, and you will find Simpana ready to serve.

The Azure Marketplace is a really important and powerful tool. It will help to create simple or complex solution easily and in only few minutes. A good way to improve our productivity.
References

Reading Notes #211

switch-949109_640Cloud


Programming


Miscellaneous



PowerBI and Microsoft Azure Consumption

Recently, I needed to check and compare Azure consumption for a client. What a repetitive task: download the csv files from the Azure billing portal, open it in Excel to clean/merge/customize it… Would it be great if it could be easily done? Well, it is! Power BI is the perfect tool to do that (and a lot more).  In this post, I will explain how I created my Power Query and solved different problem I encountered in my journey.

The Goal


I want PowerBI to read (dynamically) all csv files in a folder and updates all my charts and graph, so I can share them easily why my clients.

The Tools


To create Power Queries, you can use the new Power BI Desktop available online for free or Excel. With Excel 2016, the Power query editor tools is included, for the previous version you need to install the Microsoft Power Query for Excel add-in. In both cases, many tutorials explain how to get started with these tools (see the references at the end of this post).

The Problem


Creating our query should be pretty straight forward, since we can create a Power Query by selecting a folder as a source.
Import_auto_csv
The problem is that our file contains three types of records: Provisioning Status, Statement, and Daily Usage. These “tables” are very different and don’t have the same number of columns. This is why when we try to merge them; we got some Error.

Expend_all_fail
Error_Auto_import

The Solution


The way to solve this problem is to create a function that will parse one file to extract one recordset, and call that function for all the file in the folder.

Note:
The simplest way to get started is to work with one file, then convert it to a function. The way to that is to replace the path of the csv file by a variable that will be passed as a parameter: (filePath) =>.
To keep the code as simple as possible, I kept the function and the looping query separated, but they can be merged in only query.

Extract “Daily Usage”


Here are the queries to extract the Daily Usage (third recordSet) from the csv file and some code description.
 // -- fcnCleanOneCSV_v2 ----------------------------------------

(filePath) =>
let
   fnRawFileContents = (fullpath as text) as table =>
let
   Value = Table.FromList(Lines.FromBinary(File.Contents(fullpath)),Splitter.SplitByNothing())
in Value,

   Source = fnRawFileContents(filePath),
   #"Daily Usage Row" = Table.SelectRows(Source, each Text.Contains([Column1], "Daily Usage")),
   #"DailyPosition" = Table.PositionOf(Source, #"Daily Usage Row" {0}),
   #"TopRemoved" = Table.Skip(Source, (DailyPosition + 1)),
   #"Result" = Table.PromoteHeaders(TopRemoved)
in 
   Result
The first part is to load the content of the file as a one column table. Then DailyPosition is used to store the position where Daily Usage data starts. This value is used in Table.Skip(Source, (DailyPosition + 1)) to keep only the rows after, since Daily usage is the last recordSet it works perfectly.
 //== Process Folder CSV_v2 for Daily Usage==============================

let
   Source = Folder.Files("C:\Azure_Consumption_demo\CSV_v2\"),
   MergedColumns = Table.CombineColumns(Source,{"Folder Path", "Name"},Combiner.CombineTextByDelimiter("", QuoteStyle.None),"Merged"),
   RemovedOtherColumns = Table.SelectColumns(MergedColumns,{"Merged"}),
   #"Results" = Table.AddColumn(RemovedOtherColumns , "GetCsvs", each fcnCleanOneCSV_v2([Merged])),
   #"Removed Columns" = Table.RemoveColumns(Results,{"Merged"}),
   #"Expanded GetCsvs" = Table.ExpandTableColumn(#"Removed Columns", "GetCsvs", {"Usage Date,Meter Category,Meter Id,Meter Sub-category,Meter Name,Meter Region,Unit,Consumed Quantity,Resource Location,Consumed Service,Resource Group,Instance Id,Tags,Additional Info,Service Info 1,Service Info 2"}, {"Usage Date,Meter Category,Meter Id,Meter Sub-category,Meter Name,Meter Region,Unit,Consumed Quantity,Resource Location,Consumed Service,Resource Group,Instance Id,Tags,Additional Info,Service Info 1,Service Info 2"}),


   #"Demoted Headers" = Table.DemoteHeaders(#"Expanded GetCsvs"),
   #"Split Column by Delimiter" = Table.SplitColumn(#"Demoted Headers","Column1",Splitter.SplitTextByDelimiter(","),{"Column1.1", "Column1.2", "Column1.3", "Column1.4", "Column1.5", "Column1.6", "Column1.7", "Column1.8", "Column1.9", "Column1.10", "Column1.11", "Column1.12", "Column1.13", "Column1.14", "Column1.15", "Column1.16"}),
   #"Changed Type" = Table.TransformColumnTypes(#"Split Column by Delimiter",{{"Column1.1", type text}, {"Column1.2", type text}, {"Column1.3", type text}, {"Column1.4", type text}, {"Column1.5", type text}, {"Column1.6", type text}, {"Column1.7", type text}, {"Column1.8", type text}, {"Column1.9", type text}, {"Column1.10", type text}, {"Column1.11", type text}, {"Column1.12", type text}, {"Column1.13", type text}, {"Column1.14", type text}, {"Column1.15", type text}, {"Column1.16", type text}}),
   #"Promoted Headers" = Table.PromoteHeaders(#"Changed Type"),
   #"Changed Type1" = Table.TransformColumnTypes(#"Promoted Headers",{{"Usage Date", type date}, {"Meter Region", type text}}),
   #"Replaced Value" = Table.ReplaceValue(#"Changed Type1","""","",Replacer.ReplaceText,{"Meter Category", "Meter Id", "Meter Sub-category", "Meter Name", "Meter Region", "Unit", "Resource Location", "Consumed Service", "Instance Id", "Tags", "Additional Info", "Service Info 1", "Service Info 2"}),
   #"Changed Type2" = Table.TransformColumnTypes(#"Replaced Value",{{"Consumed Quantity", type number}})
in
  #"Changed Type2"
From row 1 to 6, we get all the file in the folder then combine columns to get a full path for each file. We then pass that to our function previously defined. With the command Table.SplitColumn, on line 11, we re-built the result as a table with multiple columns.
The rest of the query is to clean-up the result by changing the column’s type or removing undesired character.


Extract “Statement”


To get the Statement recordSet, it’s the same thing except that we will Table.Range, since the rows that we are looking for are between Provisioning Status and Daily Usage.
//== fcnGetStatement ========================================== 

(filePath) =>
let
   fnRawFileContents = (fullpath as text) as table =>
let
   Value = Table.FromList(Lines.FromBinary(File.Contents(fullpath)),Splitter.SplitByNothing())
in Value,

    Source = fnRawFileContents(filePath),
    #"Daily Usage Row" = Table.SelectRows(Source, each Text.Contains([Column1], "Daily Usage")),
    #"DailyPosition" = Table.PositionOf(Source, #"Daily Usage Row" {0}),
    #"Statement Row" = Table.SelectRows(Source, each Text.Contains([Column1], "Statement")),
    #"StatementPosition" = Table.PositionOf(Source, #"Statement Row" {0}),
    #"SelectedRows" = Table.Range(Source,(StatementPosition+1),(DailyPosition - StatementPosition )-2),
    #"Result" = Table.PromoteHeaders(SelectedRows)
in
    Result
And once again we loop through every file and do some clean-up.
//== Query Statements ========================================

let
    Source = Folder.Files("C:\Azure_Consumption_demo\CSV_v2\"),
    MergedColumns = Table.CombineColumns(Source,{"Folder Path", "Name"},Combiner.CombineTextByDelimiter("", QuoteStyle.None),"Merged"),
    RemovedOtherColumns = Table.SelectColumns(MergedColumns,{"Merged"}),
    #"Results" = Table.AddColumn(RemovedOtherColumns , "GetCsvs", each fcnGetStatement([Merged])),
    #"Removed Columns" = Table.RemoveColumns(Results,{"Merged"}),
    #"Expanded GetCsvs" = Table.ExpandTableColumn(#"Removed Columns", "GetCsvs", {"Billing Period,Meter Category,Meter Sub-category,Meter Name,Meter Region,SKU,Unit,Consumed Quantity,Included Quantity,Within Commitment,Overage Quantity,Currency,Overage,Commitment Rate,Rate,Value"}, {"Billing Period,Meter Category,Meter Sub-category,Meter Name,Meter Region,SKU,Unit,Consumed Quantity,Included Quantity,Within Commitment,Overage Quantity,Currency,Overage,Commitment Rate,Rate,Value"}),


    #"Demoted Headers" = Table.DemoteHeaders(#"Expanded GetCsvs"),
    #"Split Column by Delimiter" = Table.SplitColumn(#"Demoted Headers","Column1",Splitter.SplitTextByDelimiter(",", QuoteStyle.Csv),{"Column1.1", "Column1.2", "Column1.3", "Column1.4", "Column1.5", "Column1.6", "Column1.7", "Column1.8", "Column1.9", "Column1.10", "Column1.11", "Column1.12", "Column1.13", "Column1.14", "Column1.15", "Column1.16"}),
    #"Promoted Headers" = Table.PromoteHeaders(#"Split Column by Delimiter"),
    #"Replaced Value" = Table.ReplaceValue(#"Promoted Headers","""","",Replacer.ReplaceText,{"Meter Category", "Meter Sub-category", "Meter Name", "Meter Region", "SKU", "Unit"})
in
    #"Replaced Value"

Once all that is done… Now the fun can begin!




References




Reading Notes #210

2015-11-22_2132Suggestion of the week


Cloud


Databases


    Reading Notes #209

    Image result for redhat

    Cloud


    Databases


    Programming




    Reading Notes #208

    CanMVP

    Suggestion of the week


    Cloud


    Programming


    Miscellaneous




    Reading Notes #207

    msdnmagSuggestion of the week

    • A Beginner’s Mind - A very inspiring article, especially for the younger, but also for the more experienced, that want to keep their interior flame.

    Cloud


    Databases


    Programming


    Miscellaneous



    Reading Notes #206

    2015-10-18_2050Cloud


    Programming

    • Learn You Node with VS Code (G. Andrew) - This post is really an excellent starting point to learn Node.js. It gives good references, tools, and tips.

    Miscellaneous

    • MVP Award Update - Oct 2015 - This post explains the changes done to the MVP program to improve it. A must to all current and future MVP candidates.


    What you shouldn't have missed in the last few weeks


    2015-10-15_0836In September, Microsoft did so many announcements it’s difficult to keep tracks of all. This short post he just to list the most important and to give you the opportunity to watch them again or the first time.

    AzureCon 2015

    The AzureCon was a virtual event on September 29 that was focusing on Microsoft Azure. Many View Party around the global was watching this even rich in announcements. You can watch here the AzureCon keynotes online.
    But AzureCon was not only keynotes, it was more than 50 technical sessions covering every Azure’s feature. Get the the full list on Channel9 here.

    Windows 10 Devices

    2015-10-15_0837At the beginning of October the Windows 10 Devices was a really amazing event. Microsoft was showing us all is new devices, and they were a lot! Don’t trust me, go see by yourself on this blog post by Terry Myerson.

     

    What’s new

    Get Started and deploy your first cloud solution in under 5 minutes. Find tons of short videos online that teach you how to quicky enjoy the power of Azure.



    ~Frank


    Reading Notes #205

    background_clickCloud


    Programming


    Miscellaneous


    ~Frank



    Reading Notes #204

    AzureConLabsSuggestion of the week


    Cloud


    Programming


    Databastes


    Miscellaneous

    • Going Back to One (Alexandre Brisebois) - Organize our work to become a performer, could be easily done in Windows 10.
    • Static Site or CMS? - (Brian Rinaldi) - Nice post that gives insights to answer one of the most frequent questions when people start a blog/website.


    Reading Notes #203


    AzureConScott

     

     

    Suggestion of the week


    Cloud


    Programming


    Databastes


    Miscellaneous

    • Going Back to One (Alexandre Brisebois) - Organize our work to become a performer, could be easily done in Windows. 10.

    ~Frank