Speak guys!
In one of the last posts of 2018, I would like to share with you a Power BI dashboard with the information of all MVP's in Brazil, which are available on the portal Find an MVP.
What is MVP?
For those unfamiliar with the Microsoft Most Valuable Professional (MVP) program, he recognizes community leaders who have already demonstrated an exemplary commitment in helping others make the most of 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 project source codes
- Personally speaking (lectures and events)
- Helping others in 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 it is located (and why not, to the whole world, through the content created). by him on the Internet).
If you want to help create and organize more IT events in your area and start participating and contributing more to the tech tech community, a good way is to look for one of these professionals to help you achieve this, so that 2 help each other in this endeavor.
Getting back to focus: Power BI
Getting back to the focus of Power BI after watching the video POWER BI - Web connector. How to capture sites with more than one page. Rafael MendonçaI had the idea of using the Power BI Web connector to Webscrape the information available on the MVP Portal and create a dashboard.
At this stage, I had difficulty capturing the profile photo link and profile URL, as this information is the attribute of the tags. A e img and the Power BI interface couldn't support it, just editing the M code, which was like this, very modest:
1 2 3 4 5 6 |
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 he had an easier way to capture it without having to edit the M code manually. That's when he bought this idea and made a much more complete panel than I was thinking, bringing even the latest 10 contributions from each MVP, which looked like this:
Really, the guy is TOO Beast in Power BI .. If you were curious to know how the M code he used to build this report, follow:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 |
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 Rafael Mendonça's Youtube, demonstrating with him how this report was built step by step.
UPDATE: As promised here, below is the live video we made explaining about the Microsoft MVP program and how the report was developed step by step.
A hug and see you in the next article!