Hey guys!
In one of the last posts of 2018, I would like to share with you a Power BI dashboard with information on all MVP's in Brazil, which are available on the portal Find an MVP.

What is MVP?

For those unfamiliar with the Microsoft MVP (Most Valuable Professional) program, it recognizes community leaders who have demonstrated exemplary commitment to helping others get the most from their experience with Microsoft technologies. They share their exceptional passion, real-world knowledge, and technical expertise with the community and with Microsoft.

These contributions can be through:
– Submitting source codes for projects
– Personally speaking (lectures and events)
– Helping others on forums, (and why not Telegram/Whatsapp groups)
– Creating content (articles, blog posts, recorded videos, webcasts, lives)
– Providing feedback for Microsoft products

I had already commented about the program in my article Congratulations 2018-2019 Microsoft MVP!, which I wrote when I received confirmation that I had joined the program, that one of the missions of these professionals is to bring technology, innovation and knowledge to the communities where they are located (and why not, to the whole world, through the content they create on the Internet).

If you want to help create and organize more IT events in your region and start participating and contributing more to the technical technology community, a good way is to look for one of these professionals to help you achieve this goal, so that both of you can help each other in this endeavor.

Returning to focus: Power BI

Returning to the focus of Power BI, after watching the video POWER BI – Web Connector. How to capture websites with more than one page, from Rafael Mendonça, I had the idea of ​​using the Power BI Web connector to Webscrape the information available on the MVPs Portal and create a panel.

At this stage, I had difficulties capturing the profile photo link and the profile URL, as this information remains as tag attributes THE and img and the Power BI interface did not support doing this, just editing the M code, which looked like this, very modest:

let
    Source = Web.BrowserContents("https://mvp.microsoft.com/en-us/MvpSearch?lo=Brazil&kw=&ps=200&pn=1"),
    #"Extracted Table From Html" = Html.Table(Source, {{"Nome", ".profileListItemFullName"}, {"Categoria", ".profileListItemCompetency > .subItemContent"}, {"Pais", ".profileListItemLocation > .subItemContent"}}, [RowSelector=".profileListItem"]),
    #"Changed Type" = Table.TransformColumnTypes(#"Extracted Table From Html",{{"Nome", type text}, {"Categoria", type text}, {"Pais", type text}})
in
    #"Changed Type"

I called Rafael on Whatsapp to see if there was an easier way to capture this, without having to edit the M code manually. That's when he bought into this idea and created a much more complete panel than I was imagining, including the last 10 contributions of each MVP, which looked like this:

Really, the guy is TOO great at Power BI... If you're curious to know what the M code he used to build this report looked like, follow below:

let
    Fonte = Web.BrowserContents("https://mvp.microsoft.com/en-us/MvpSearch?lo=Brazil&sc=e&pn=1"),
    //Extração da informação da quantidade de Registros Encontrados na consulta da página específica de MVPs do Brazil
    #"Tabela extraída de HTML" = Html.Table(Fonte, {{"Coluna 1", ".resultcount"}}),
    #"Tipo Alterado" = Table.TransformColumnTypes(#"Tabela extraída de HTML",{{"Coluna 1", Currency.Type}}),
    /////////////////////////////////////////////////////////////////////
    //Visto que cada página possui no máximo 18 perfis, dividimos a quantidade de perfis por 18 e arredondamos para cima, para encontrar a quantidade de páginas possíveis
    #"Coluna dividida" = Table.TransformColumns(#"Tipo Alterado", {{"Coluna 1", each _ / -18, Currency.Type}}),
    #"Arredondado para Cima" = Table.TransformColumns(#"Coluna dividida",{{"Coluna 1", Number.RoundUp, Currency.Type}}),
    ////////////////////////////////////////////////////////////////////
    #"Personalização Adicionada" = Table.AddColumn(#"Arredondado para Cima", "Personalizar", each {1..[Coluna 1]}),
    #"Colunas Removidas" = Table.RemoveColumns(#"Personalização Adicionada",{"Coluna 1"}),
    #"Personalizar Expandido" = Table.ExpandListColumn(#"Colunas Removidas", "Personalizar"),
    #"Tipo Alterado1" = Table.TransformColumnTypes(#"Personalizar Expandido",{{"Personalizar", type text}}),
    //Adicionado Prefixo à lista criada para montar o Link de cada uma das páginas a serem capturadas.
    #"Prefixo Adicionado" = Table.TransformColumns(#"Tipo Alterado1", {{"Personalizar", each "https://mvp.microsoft.com/en-us/MvpSearch?lo=Brazil&sc=e&pn=" & _, type text}}),
    
    //Função criada Internamente dentro da própria Consulta. Existem 3 Funções internas nessa query par capturar, pagina inicial, ultimas contribuições e dados complementares.
    Funcao = (url as text) =>
    let
        Fonte = Web.BrowserContents(url),
        #"Tabela extraída de HTML" = Html.Table(Fonte, 
        {
            {"Nome", ".profileListItemFullName"}, 
            {"Categoria Premiação", ".profileListItemCompetency > .subItemContent"}, 
            {"País/Região", ".profileListItemLocation > .subItemContent"}, 
            {"Perfil", "#kwmain > div > div > div > div > div.rightRail > div > div:nth-child(2) > div > div.thumb > a", each [Attributes][href]}, 
            {"Imagem", "#kwmain > div > div > div > div > div.rightRail > div > div:nth-child(2) > div > div.thumb > a > img", each [Attributes][src]}
        }, [RowSelector=".profileListItem"]),
        #"Prefixo Adicionado" = Table.TransformColumns(#"Tabela extraída de HTML", {{"Imagem", each "https://mvp.microsoft.com" & _, type text}}),
        #"Prefixo Adicionado1" = Table.TransformColumns(#"Prefixo Adicionado", {{"Perfil", each "https://mvp.microsoft.com" & _, type text}})
    in
        #"Prefixo Adicionado1",
    //Fim da Função
    Convoca = Table.AddColumn(#"Prefixo Adicionado", "FuncaoChamada", each Funcao([Personalizar])),
    #"FuncaoChamada Expandido" = Table.ExpandTableColumn(Convoca, "FuncaoChamada", {"Nome", "Categoria Premiação", "País/Região", "Perfil", "Imagem"}, {"Nome", "Categoria Premiação", "País/Região", "Perfil", "Imagem"}),
    #"Colunas Removidas1" = Table.RemoveColumns(#"FuncaoChamada Expandido",{"Personalizar"}),
    #"Dividir Coluna por Delimitador" = Table.ExpandListColumn(Table.TransformColumns(#"Colunas Removidas1", {{"Categoria Premiação", Splitter.SplitTextByDelimiter(", ", QuoteStyle.Csv), let itemType = (type nullable text) meta [Serialized.Text = true] in type {itemType}}}), "Categoria Premiação"),
    #"Tipo Alterado2" = Table.TransformColumnTypes(#"Dividir Coluna por Delimitador",{{"Categoria Premiação", type text}, {"Nome", type text}, {"País/Região", type text}, {"Perfil", type text}, {"Imagem", type text}}),
    Funcao2 = (urlbio as text) =>
    let
        Fonte = Web.BrowserContents(urlbio),
        #"Tabela extraída de HTML" = Html.Table(Fonte, 
        {
            {"Data", "TABLE[id='recentActivities'] > TBODY > TR > :nth-child(2)"}, 
            {"Atividade", "TABLE[id='recentActivities'] > TBODY > TR > :nth-child(3)"}, 
            {"Tipo", "TABLE[id='recentActivities'] > TBODY > TR > :nth-child(4)"}, 
            {"Área Principal de Contribuição", "TABLE[id='recentActivities'] > TBODY > TR > :nth-child(5)"}, 
            {"Link Contribuição", "#recentActivities > tbody > tr > td > a", each [Attributes][href]}
        }, [RowSelector="TABLE[id='recentActivities'] > TBODY > TR"]),
        #"Tipo Alterado" = Table.TransformColumnTypes(#"Tabela extraída de HTML",{{"Data", type text}, {"Atividade", type text}, {"Tipo", type text}, {"Área Principal de Contribuição", type text}})
    
    in
        #"Tipo Alterado",
    ConsultaCotribuicoes = Table.AddColumn(#"Tipo Alterado2", "Contribuições", each Funcao2([Perfil])),
    Funcao3 = (urlbio as text) =>
    let
        Fonte = Web.BrowserContents(urlbio),
        #"Tabela extraída de HTML" = Html.Table(Fonte, 
        {
            {"Localidade", ".state"}, 
            {"Primeiro Ano de Prêmio", ".infoRow:nth-child(2) > .infoContent"}, 
            {"Numeros de Prêmios", ".infoRow:nth-child(3) > .infoContent"}
        }, [RowSelector=".infoRow:nth-child(2) > .infoContent"]),
        #"Tipo Alterado" = Table.TransformColumnTypes(#"Tabela extraída de HTML",{{"Localidade", type text}, {"Primeiro Ano de Prêmio", Int64.Type}, {"Numeros de Prêmios", Int64.Type}})
    in
        #"Tipo Alterado",
    ConsultaDemaisInfos = Table.AddColumn(ConsultaCotribuicoes, "Infos", each Funcao3([Perfil])),
    #"Contribuições Expandido" = Table.ExpandTableColumn(ConsultaDemaisInfos, "Contribuições", {"Data", "Atividade", "Tipo", "Área Principal de Contribuição", "Link Contribuição"}, {"Data", "Atividade", "Tipo", "Área Principal de Contribuição", "Link Contribuição"}),
    #"Infos Expandido" = Table.ExpandTableColumn(#"Contribuições Expandido", "Infos", {"Localidade", "Primeiro Ano de Prêmio", "Numeros de Prêmios"}, {"Localidade", "Primeiro Ano de Prêmio", "Numeros de Prêmios"}),
    #"Tipo Alterado com Localidade" = Table.TransformColumnTypes(#"Infos Expandido", {{"Data", type date}}, "en-US"),
    #"Tipo Alterado3" = Table.TransformColumnTypes(#"Tipo Alterado com Localidade",{{"Área Principal de Contribuição", type text}, {"Link Contribuição", type text}, {"Localidade", type text}, {"Primeiro Ano de Prêmio", Int64.Type}, {"Numeros de Prêmios", Int64.Type}}),
    #"Dividir Coluna por Delimitador1" = Table.SplitColumn(#"Tipo Alterado3", "Localidade", Splitter.SplitTextByDelimiter(", ", QuoteStyle.Csv), {"Localidade.1", "Localidade.2"}),
    #"Tipo Alterado4" = Table.TransformColumnTypes(#"Dividir Coluna por Delimitador1",{{"Localidade.1", type text}, {"Localidade.2", type text}}),
    #"Personalização Adicionada1" = Table.AddColumn(#"Tipo Alterado4", "Personalizar", each if [Localidade.2] = null then [Localidade.1] else [Localidade.2]),
    #"Colunas Renomeadas" = Table.RenameColumns(#"Personalização Adicionada1",{{"Personalizar", "Estado"}}),
    #"Colunas Removidas2" = Table.RemoveColumns(#"Colunas Renomeadas",{"Localidade.2"}),
    #"Colunas Renomeadas1" = Table.RenameColumns(#"Colunas Removidas2",{{"Localidade.1", "Município"}}),
    #"Colunas Reordenadas" = Table.ReorderColumns(#"Colunas Renomeadas1",{"Nome", "Categoria Premiação", "País/Região", "Perfil", "Imagem", "Data", "Atividade", "Tipo", "Área Principal de Contribuição", "Link Contribuição", "Primeiro Ano de Prêmio", "Numeros de Prêmios", "Município", "Estado"}),
    #"Tipo Alterado5" = Table.TransformColumnTypes(#"Colunas Reordenadas",{{"Estado", type text}}),
    #"Valor Substituído" = Table.ReplaceValue(#"Tipo Alterado5","Santa Catarina","SC",Replacer.ReplaceText,{"Estado"}),
    #"Valor Substituído1" = Table.ReplaceValue(#"Valor Substituído","Ceara","CE",Replacer.ReplaceText,{"Estado"}),
    #"Valor Substituído2" = Table.ReplaceValue(#"Valor Substituído1","Sao Paulo","SP",Replacer.ReplaceText,{"Estado"}),
    #"Valor Substituído3" = Table.ReplaceValue(#"Valor Substituído2","Espírito Santo","ES",Replacer.ReplaceText,{"Estado"}),
    #"Valor Substituído4" = Table.ReplaceValue(#"Valor Substituído3","Rio de Janeiro","RJ",Replacer.ReplaceText,{"Estado"}),
    #"Valor Substituído5" = Table.ReplaceValue(#"Valor Substituído4","Parana","PR",Replacer.ReplaceText,{"Estado"}),
    #"Valor Substituído6" = Table.ReplaceValue(#"Valor Substituído5","Pernambuco","PE",Replacer.ReplaceText,{"Estado"}),
    #"Valor Substituído7" = Table.ReplaceValue(#"Valor Substituído6","São Paulo","SP",Replacer.ReplaceText,{"Estado"}),
    #"Valor Substituído8" = Table.ReplaceValue(#"Valor Substituído7","Minas Gerais","MG",Replacer.ReplaceText,{"Estado"}),
    #"Linhas Filtradas" = Table.SelectRows(#"Valor Substituído8", each true)
in
    #"Linhas Filtradas"

In January, I will make a special appearance on the channel Rafael Mendonça's Youtube, demonstrating together with him how this report was constructed step by step.

UPDATE: As promised here, below is the live video we performed explaining the Microsoft MVP program and how the report was developed step by step.

A hug and see you in the next article!