Hey guys!
Em um dos últimos posts de 2018, gostaria de compartilhar com vocês um dashboard do Power BI com as informações de todos os MVP’s do Brasil, que estão disponíveis no portal Encontre um MVP.
O que é MVP?
Para quem não conhece o programa Microsoft MVP (Most Valuable Professional), ele reconhece líderes comunitários que já demonstraram um compromisso exemplar ao ajudar os outros a obter o máximo de sua experiência com as tecnologias Microsoft. Eles compartilham sua paixão excepcional, o conhecimento do mundo real, e conhecimentos técnicos com a comunidade e com a Microsoft.
Essas contribuições podem ser através de:
– Submetendo códigos-fonte para projetos
– Pessoalmente falando (palestras e eventos)
– Ajudando os outros em fóruns, (e porquê não grupos de Telegram/Whatsapp)
– Criando conteúdo (artigos, blog posts, vídeos gravados, webcasts, lives)
– Fornecendo feedback para os produtos Microsoft
Eu já havia comentado sobre o programa no meu artigo Congratulations 2018-2019 Microsoft MVP!, que escrevi quando recebi a confirmação que eu havia entrado para o programa, que uma das missões desses profissionais, é levar tecnologia, inovação e conhecimento para as comunidades onde ele se encontra (e porque não, para o mundo todo, através dos conteúdos criados por ele na Internet).
Se você quer ajudar a criar e organizar mais eventos de TI na sua região e começar a participar e contribuir mais para a comunidade técnica de tecnologia, um bom caminho é procurar um desses profissionais para te ajudar a alcançar esse objetivo, de modo que os 2 se ajudem nessa empreitada.
Voltando ao foco: Power BI
Voltando ao foco do Power BI, após assistir ao vídeo POWER BI – Conector Web. Como capturar sites com mais de uma página, do Rafael Mendonça, tive a ideia de utilizar o conector Web do Power BI pra fazer um Webscraping das informações disponível no Portal dos MVPs e criar um painel.
Nessa etapa, tive dificuldades na parte de capturar o link da foto do perfil e a URL do perfil, pois essas informações ficam como atributos das tags A e img e a interface do Power BI não suportava fazer isso, apenas editando o código M, que estava assim, bem modesto:
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" |
Chamei no Rafael no Whatsapp pra ver com ele se não tinha uma forma mais fácil de capturar isso, sem ter que editar o código M manualmente. Foi aí que ele comprou essa ideia e fez um painel bem mais completo do que eu estava idealizando, trazendo até as últimas 10 contribuições de cada MVP, que ficou assim:
Realmente, o cara é fera DEMAIS no Power BI.. Se você ficou curioso de saber como ficou o código M que ele utilizou para construir esse relatório, segue abaixo:
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 of Registros Encontrados na consulta da página específica of 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 of perfis por 18 e arredondamos para cima, para encontrar a quantidade of 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 of 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" |
Em Janeiro, vou fazer uma participação especial no canal do Youtube do Rafael Mendonça, demonstrando junto com ele, como esse relatório foi construído passo a passo.
UPDATE: Conforme prometido aqui, segue abaixo o vídeo da live que realizamos explicando sobre o programa Microsoft MVP e como o relatório foi desenvolvido passo a passo.
Um abraço e até o próximo artigo!