Propósito

✔ Programação GLOBAL® - Quaisquer soluções e/ou desenvolvimento de aplicações pessoais, ou da empresa, que não constem neste Blog devem ser tratados como consultoria freelance. Queiram contatar-nos: brazilsalesforceeffectiveness@gmail.com | ESTE BLOG NÃO SE RESPONSABILIZA POR QUAISQUER DANOS PROVENIENTES DO USO DOS CÓDIGOS AQUI POSTADOS EM APLICAÇÕES PESSOAIS OU DE TERCEIROS.

Automação de Web Scraping em Excel: Como Extrair Dados de Tabelas HTML com VBA

Automação de Web Scraping em Excel: Como Extrair Dados de Tabelas HTML com VBA
#ProgramaçãoGlobal #VisualBasicforApplication #VBA #AutomaçãoExcel #ExtraçãoDados #HTMLParsing #IntegracaoDados #OficeAutomation #WebScraping


DOE UM CAFÉ


 Compre OS LIVROS DESTA SÉRIE 



A extração de dados de websites é necessidade cotidiana para profissionais que trabalham com análise de informações. Enquanto navegar manualmente por websites e copiar dados é solução comum, essa abordagem é extremamente demorada, propensa a erros e improdutiva quando se lida com grandes volumes de dados. A solução está em automatizar este processo através de código VBA (Visual Basic for Applications), permitindo extrair tabelas inteiras de websites diretamente para planilhas Excel de forma instantânea.

O VBA, linguagem de programação nativa do Microsoft Office, oferece capacidades robustas para interagir com conteúdo HTML de websites. Diferentemente de soluções web-scraping em Python ou JavaScript que exigem conhecimento de programação avançada, VBA permite que usuários do Excel implementem automação sofisticada sem sair do ambiente familiar da suite Office. Para profissionais que trabalham com dados em Excel — analistas de negócio, gestores de projeto, pesquisadores — aprender a extrair dados de websites representa aumento significativo de produtividade.

A técnica de web-scraping com VBA baseia-se em fazer requisições HTTP ao servidor web, receber o conteúdo HTML da página, processar a estrutura do documento HTML para localizar elementos específicos (neste caso, tabelas), extrair dados relevantes, e então preencher células da planilha Excel automaticamente. Este processo, quando bem implementado, pode processar múltiplos websites e extrair centenas ou milhares de linhas de dados em questão de minutos.

Implementação robusta de web-scraping em VBA exige atenção a diversos detalhes técnicos. Primeiro, é necessário adicionar referências apropriadas ao projeto VBA — especificamente "Microsoft HTML Object Library" e "Microsoft Internet Controls" — que fornecem objetos necessários para manipular conteúdo HTML. Segundo, tratamento de erros é essencial porque requisições de rede são operações que podem falhar por razões diversas: servidor indisponível, conexão de internet instável, timeout de requisição. Terceira, implementação deve ser flexível o suficiente para funcionar com diferentes estruturas de tabelas HTML, não apenas a estrutura específica de um website.

O código desenvolvido utiliza arquitetura modular onde cada função tem responsabilidade específica. A função principal ExtrairTabelaHTML() controla o fluxo geral: faz requisição ao website, obtém documento HTML, limpa a planilha, extrai todas as tabelas encontradas, formata as colunas para apresentação clara. A função ObterDocumentoHTML() encapsula toda a lógica de conexão HTTP, incluindo retry automático em caso de falha e timeout configurável. A função ExtrairTodasAsTabelasHTML() procura por todas as tags TABLE no documento HTML e itera sobre cada uma. A função ExtrairUmaTabela() contém lógica de parsing detalhado de uma tabela individual, iterando sobre linhas (TR) e células (TD/TH) para extrair texto.

Option Explicit

'═══════════════════════════════════════════════════════════════════════════════
' MÓDULO: Web Scraping de Tabelas HTML com VBA
'═══════════════════════════════════════════════════════════════════════════════
' DESCRIÇÃO: Extrai dados de tabelas HTML de qualquer website e popula planilha Excel
' VERSÃO: 1.0
' DATA: 14.12.2025 - 06:57:32
' AUTOR: André Luiz Bernardes
'═══════════════════════════════════════════════════════════════════════════════

'═══════════════════════════════════════════════════════════════════════════════
' REFERÊNCIAS NECESSÁRIAS (Tools > References)
' Microsoft HTML Object Library (versão 3.0 ou superior)
' Microsoft Internet Controls (versão 11.0 ou superior)
'═══════════════════════════════════════════════════════════════════════════════

Sub ExtrairTabelaHTML()
    '───────────────────────────────────────────────────────────────────────────
    ' PROCEDIMENTO PRINCIPAL: Controla o fluxo de extração de tabelas HTML
' DATA: 14.12.2025 - 06:57:32

' AUTOR: André Luiz Bernardes 

    '───────────────────────────────────────────────────────────────────────────
    
    On Error GoTo TratamentoErro
    
    Dim url As String
    Dim htmlDoc As Object
    Dim linhaAtual As Long
    
    ' Define a URL alvo contendo a tabela de estados brasileiros
    url = "https://inanyplace.blogspot.com/2017/01/lista-de-estados-brasileiros-sigla-estado-capital-e-regiao.html"
    
    ' Exibe mensagem informando início do processo
    Application.StatusBar = "Iniciando extração de dados HTML..."
    
    ' Faz download do conteúdo HTML da página
    Set htmlDoc = ObterDocumentoHTML(url)
    
    ' Verifica se documento foi carregado com sucesso
    If htmlDoc Is Nothing Then
        MsgBox "Falha ao carregar a página HTML. Verifique a URL e conexão.", vbCritical
        Exit Sub
    End If
    
    ' Limpa a planilha ativa (remove dados anteriores)
    LimparPlanilha
    
    ' Extrai todas as tabelas encontradas no documento HTML
    linhaAtual = ExtrairTodasAsTabelasHTML(htmlDoc, 1)
    
    ' Exibe mensagem de sucesso com número de linhas extraídas
    Application.StatusBar = "Extração concluída! Total de linhas: " & linhaAtual - 1
    MsgBox "Dados extraídos com sucesso! Foram importadas " & linhaAtual - 1 & " linhas.", vbInformation
    
    ' Formata as colunas automaticamente para melhor visualização
    FormatarColunas
    
    Application.StatusBar = ""
    Exit Sub
    
TratamentoErro:
    MsgBox "Erro: " & Err.Description, vbCritical
    Application.StatusBar = ""
End Sub

'═══════════════════════════════════════════════════════════════════════════════

Function ObterDocumentoHTML(urlAlvo As String) As Object
    '───────────────────────────────────────────────────────────────────────────
    ' FUNÇÃO: Faz download da página HTML e retorna o objeto Document
    ' ENTRADA: urlAlvo (String) - URL da página a ser acessada
    ' SAÍDA: Objeto HTMLDocument contendo o conteúdo da página
' DATA: 14.12.2025 - 06:57:32

' AUTOR: André Luiz Bernardes  

    '───────────────────────────────────────────────────────────────────────────
    
    On Error GoTo TratamentoErro
    
    Dim xmlhttp As Object
    Dim htmlDocument As Object
    Dim tentativas As Integer
    Dim tempoEspera As Integer
    
    ' Inicializa contador de tentativas e tempo de espera
    tentativas = 0
    tempoEspera = 2000 ' 2 segundos em milissegundos
    
    ' Tenta fazer conexão com retry automático (até 3 tentativas)
    Do While tentativas < 3
        tentativas = tentativas + 1
        
        Try
            ' Cria objeto para requisição HTTP
            Set xmlhttp = CreateObject("MSXML2.XMLHTTP.6.0")
            
            ' Configura timeout para 30 segundos
            xmlhttp.setTimeouts 30000, 30000, 30000, 30000
            
            ' Abre conexão com método GET na URL especificada
            xmlhttp.Open "GET", urlAlvo, False
            
            ' Adiciona header User-Agent para evitar bloqueios de bot
            xmlhttp.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
            
            ' Envia requisição ao servidor
            xmlhttp.Send
            
            ' Verifica se a resposta foi bem-sucedida (código 200)
            If xmlhttp.Status = 200 Then
                
                ' Cria novo documento HTML para armazenar resposta
                Set htmlDocument = CreateObject("htmlfile")
                
                ' Carrega o HTML recebido no documento
                htmlDocument.body.innerHTML = xmlhttp.responseText
                
                ' Retorna documento HTML preenchido
                Set ObterDocumentoHTML = htmlDocument
                Exit Function
                
            Else
                ' Se falhou, aguarda um pouco e tenta novamente
                Application.Wait Now + TimeValue("0:00:02")
            End If
            
        Catch
            ' Em caso de erro, aguarda e tenta novamente
            Application.Wait Now + TimeValue("0:00:02")
        End Try
    Loop
    
    ' Se chegou aqui, todas as tentativas falharam
    Set ObterDocumentoHTML = Nothing
    Exit Function
    
TratamentoErro:
    Set ObterDocumentoHTML = Nothing
End Function

'═══════════════════════════════════════════════════════════════════════════════

Function ExtrairTodasAsTabelasHTML(htmlDoc As Object, linhaInicial As Long) As Long
    '───────────────────────────────────────────────────────────────────────────
    ' FUNÇÃO: Procura e extrai TODAS as tabelas encontradas no documento HTML
    ' ENTRADA: htmlDoc (Object) - Documento HTML carregado
    '          linhaInicial (Long) - Número da linha para iniciar preenchimento
    ' SAÍDA: Long - Número total de linhas preenchidas
' DATA: 14.12.2025 - 06:57:32

' AUTOR: André Luiz Bernardes  

    '───────────────────────────────────────────────────────────────────────────
    
    On Error GoTo TratamentoErro
    
    Dim tabelas As Object
    Dim tabela As Object
    Dim indiceTabela As Integer
    Dim linhaAtual As Long
    
    ' Inicializa contador de linhas
    linhaAtual = linhaInicial
    
    ' Obtém todas as tags TABLE do documento HTML
    Set tabelas = htmlDoc.getElementsByTagName("TABLE")
    
    ' Se não encontrou tabelas, retorna linha inicial
    If tabelas.Length = 0 Then
        ExtrairTodasAsTabelasHTML = linhaAtual
        Exit Function
    End If
    
    ' Percorre cada tabela encontrada
    For indiceTabela = 0 To tabelas.Length - 1
        
        ' Obtém referência para tabela atual
        Set tabela = tabelas.Item(indiceTabela)
        
        ' Extrai dados da tabela atual e atualiza contador de linhas
        linhaAtual = ExtrairUmaTabela(tabela, linhaAtual)
        
    Next indiceTabela
    
    ' Retorna total de linhas preenchidas
    ExtrairTodasAsTabelasHTML = linhaAtual
    Exit Function
    
TratamentoErro:
    ExtrairTodasAsTabelasHTML = linhaAtual
End Function

'═══════════════════════════════════════════════════════════════════════════════

Function ExtrairUmaTabela(tabela As Object, linhaInicial As Long) As Long
    '───────────────────────────────────────────────────────────────────────────
    ' FUNÇÃO: Extrai dados de uma única tabela HTML e popula planilha
    ' ENTRADA: tabela (Object) - Elemento TABLE do HTML
    '          linhaInicial (Long) - Número da linha para iniciar preenchimento
    ' SAÍDA: Long - Número da próxima linha disponível
' DATA: 14.12.2025 - 06:57:32

' AUTOR: André Luiz Bernardes  

    '───────────────────────────────────────────────────────────────────────────
    
    On Error GoTo TratamentoErro
    
    Dim linhas As Object
    Dim linha As Object
    Dim celulas As Object
    Dim celula As Object
    Dim indiceLinhas As Integer
    Dim indiceColunas As Integer
    Dim linhaAtual As Long
    Dim colunaAtual As Integer
    Dim textoCelula As String
    
    ' Inicializa contadores
    linhaAtual = linhaInicial
    
    ' Obtém todos os elementos TR (linhas) dentro da tabela
    Set linhas = tabela.getElementsByTagName("TR")
    
    ' Se tabela vazia, retorna linha inicial
    If linhas.Length = 0 Then
        ExtrairUmaTabela = linhaAtual
        Exit Function
    End If
    
    ' Percorre cada linha da tabela
    For indiceLinhas = 0 To linhas.Length - 1
        
        ' Obtém referência para linha atual
        Set linha = linhas.Item(indiceLinhas)
        
        ' Obtém todos os elementos TD ou TH (células) da linha
        Set celulas = linha.getElementsByTagName("TD")
        
        ' Se não encontrou TD, tenta TH (header cells)
        If celulas.Length = 0 Then
            Set celulas = linha.getElementsByTagName("TH")
        End If
        
        ' Se ainda não encontrou células, pula para próxima linha
        If celulas.Length = 0 Then
            GoTo ProximaLinhaExterno
        End If
        
        ' Reinicia contador de colunas para nova linha
        colunaAtual = 1
        
        ' Percorre cada célula da linha
        For indiceColunas = 0 To celulas.Length - 1
            
            ' Obtém referência para célula atual
            Set celula = celulas.Item(indiceColunas)
            
            ' Extrai texto da célula, removendo espaços extras
            textoCelula = Trim(celula.textContent)
            
            ' Preenche célula da planilha com texto extraído
            Cells(linhaAtual, colunaAtual).Value = textoCelula
            
            ' Move para próxima coluna
            colunaAtual = colunaAtual + 1
            
        Next indiceColunas
        
        ' Move para próxima linha apenas se célula foi preenchida
        If colunaAtual > 1 Then
            linhaAtual = linhaAtual + 1
        End If
        
ProximaLinhaExterno:
    Next indiceLinhas
    
    ' Retorna número da próxima linha disponível
    ExtrairUmaTabela = linhaAtual
    Exit Function
    
TratamentoErro:
    ExtrairUmaTabela = linhaAtual
End Function

'═══════════════════════════════════════════════════════════════════════════════

Sub LimparPlanilha()
    '───────────────────────────────────────────────────────────────────────────
    ' PROCEDIMENTO: Remove todos os dados da planilha ativa
' DATA: 14.12.2025 - 06:57:32

' AUTOR: André Luiz Bernardes  

    '───────────────────────────────────────────────────────────────────────────
    
    On Error GoTo TratamentoErro
    
    ' Seleciona todas as células da planilha
    Cells.Select
    
    ' Deleta conteúdo das células selecionadas
    Selection.Delete
    
    ' Posiciona cursor na célula A1
    Range("A1").Select
    
    Exit Sub
    
TratamentoErro:
    ' Se ocorrer erro, apenas prossegue
End Sub

'═══════════════════════════════════════════════════════════════════════════════

Sub FormatarColunas()
    '───────────────────────────────────────────────────────────────────────────
    ' PROCEDIMENTO: Formata colunas para melhor visualização dos dados
' DATA: 14.12.2025 - 06:57:32

' AUTOR: André Luiz Bernardes  

    '───────────────────────────────────────────────────────────────────────────
    
    On Error GoTo TratamentoErro
    
    ' Seleciona todas as colunas com dados
    Cells.Select
    
    ' Ajusta largura das colunas automaticamente ao conteúdo
    Selection.Columns.AutoFit
    
    ' Aplica bordas simples em todas as células com dados
    Selection.Borders.LineStyle = xlContinuous
    Selection.Borders.Weight = xlThin
    
    ' Aplica formatação de negrito na primeira linha (headers)
    Range("1:1").Font.Bold = True
    Range("1:1").Interior.Color = RGB(200, 200, 200)
    
    ' Congela a primeira linha para facilitar navegação
    Rows("2:2").Select
    ActiveWindow.FreezePanes = True
    
    ' Posiciona cursor na célula A1
    Range("A1").Select
    
    Exit Sub
    
TratamentoErro:
    ' Se ocorrer erro, apenas prossegue
End Sub

Comentários de código extensivos facilitam compreensão e manutenção. Cada função possui comentário de cabeçalho explicando propósito, parâmetros de entrada e valores de retorno. Cada bloco de código crítico possui comentário explicando o que está sendo executado. Esta documentação interna é fundamental porque código VBA frequentemente é mantido por diferentes pessoas ao longo do tempo, e clareza contribui significativamente para sustentabilidade de solução.

Tratamento de erros implementado segue padrão robusto. A estrutura On Error GoTo TratamentoErro em cada função garante que exceções não façam código crashar, e em lugar disso, execução continua de forma controlada. Para operação de requisição HTTP, implementa-se retry automático — até 3 tentativas com espera entre tentativas — porque falhas temporárias de rede são comuns. Timeout é configurado em 30 segundos para evitar que código fique travado esperando resposta de servidor não responsivo indefinidamente.

Flexibilidade é característica importante do código. A função ExtrairTodasAsTabelasHTML() não presume nada sobre número de tabelas — procura por TODAS as tabelas encontradas no documento HTML. A função ExtrairUmaTabela() trata casos onde células podem ser tags TD (células de dados) ou TH (células de cabeçalho), adaptando-se a variações em estrutura HTML. A função não presume nada sobre número de colunas — itera sobre todas as células em cada linha. Esta flexibilidade permite que mesmo código seja usado para extrair dados de websites completamente diferentes, desde que contenham tabelas.

Formatação de dados é aspecto frequentemente negligenciado mas importante. O código inclui função FormatarColunas() que ajusta largura das colunas automaticamente ao conteúdo, aplica bordas às células para melhor visualização, formata primeira linha com negrito e cor de fundo para identificação clara de headers, e congela primeira linha permitindo que usuário role dados enquanto mantendo headers visíveis. Esta formatação automatizada poupa tempo que seria gasto em ajustes manuais.

Uso prático desta solução é variado. Analista de RH pode extrair automaticamente dados de websites de universidades contendo lista de programas oferecidos, comparar com banco de dados interno, e identificar lacunas em oferta de treinamento. Pesquisador de mercado pode extrair dados de preços de concorrentes de múltiplos websites diariamente, alimentar planilha Excel centralizada, e gerar relatórios de tendência de preços. Gerente de projetos pode extrair dados de status de projetos de websites de parceiros, consolidar em dashboard único, e monitorar progresso de múltiplos engajamentos simultaneamente.

Limitações práticas devem ser reconhecidas. Código funciona com websites que servem conteúdo HTML estático — se website utiliza JavaScript para renderizar conteúdo dinamicamente (single-page application), esta abordagem não funcionará porque MSXML2.XMLHTTP não executa JavaScript. Alguns websites implementam bloqueios contra bots — rate limiting, bloqueio de User-Agent, CAPTCHA — que podem impedir execução bem-sucedida. Websites que mudarem estrutura HTML de suas tabelas podem quebrar código existente e exigir ajustes.

Segurança é consideração importante ao fazer requisições HTTP. O código inclui User-Agent header que identifica requisição como navegador web, reduzindo probabilidade de bloqueio. Contudo, fazer muitas requisições em curto período pode resultar em bloqueio de IP. Para casos de uso em produção, considerar implementar delay entre requisições, implementar pool de IPs proxy, ou utilizar APIs oficiais quando disponíveis em lugar de web scraping.

Performance é outro fator relevante. Código é essencialmente single-threaded — processa uma URL por vez, aguarda resposta, extrai dados. Para scenarios envolvendo dezenas de websites simultaneamente, performance pode ser limitada. Soluções mais sofisticadas poderiam implementar async patterns ou paralelização, contudo isso aumentaria complexidade significativamente.

Manutenção contínua é necessária. Se website muda sua estrutura HTML ou URL, código requer ajustes. É recomendação boa manter documentação de versão de código, adicionar logging detalhado para debugging de problemas em produção, e implementar testes automáticos se solução é crítica para negócio. Versionamento de código em sistema como Git é prática recomendada mesmo para código VBA.

Extensões futuras são possíveis. Código poderia ser modificado para suportar login em websites protegidos, implementar parsing de conteúdo mais sofisticado (não apenas tabelas), adicionar capacidade de processar formulários e enviar dados, ou integrar com APIs de cloud services para armazenar dados em bancos de dados remotos. Comunidade de desenvolvedores VBA é ativa e documentação abundante pode ser encontrada para casos de uso específicos.

Conclusão prática: VBA oferece solução acessível e poderosa para automatizar extração de dados de websites. Código bem estruturado, comentado e tratando erros robustamente pode ser utilizado por múltiplas pessoas e mantido ao longo de anos. Para profissionais de dados que trabalham primariamente em Excel, investir tempo em aprender web scraping com VBA representa incremento substancial de valor profissional e produtividade.


Sim, nós sabemos, nós sabemos, nós sabemos…


Ver essa mensagem é irritante. Sabemos disso. (Imagine como é escrevê-la...). Mas também é extremamente importante. Um dos maiores trunfos do ✔ Brazil SFE® é seu modelo parcialmente financiado pelos leitores. 


1. O financiamento dos leitores significa que podemos cobrir o que quisermos. Não sujeitos a caprichos de um proprietário bilionário. Ninguém pode nos dizer o que não dizer ou o que não reportar.


2. O financiamento dos leitores significa que não precisamos correr atrás de cliques e tráfego. Não buscamos desesperadamente a sua atenção por si só: buscamos as histórias que nossa equipe editorial considera importantes e que merecem o seu tempo.


3. O financiamento dos leitores significa que podemos manter nosso blog aberto, permitindo que o maior número possível de pessoas leia artigos de qualidade do mundo todo.


O apoio de leitores como você torna tudo isso possível. No momento, apenas 2,4% dos nossos leitores regulares ajudam a financiar nosso trabalho. Se você quer ajudar a proteger nossa independência editorial, considere juntar-se a nós hoje mesmo.


Valorizamos qualquer quantia que possa nos dar, mas apoiar mensalmente é o que causa maior impacto, permitindo um investimento maior em nosso trabalho mais crucial e destemido, assim esperamos que considere apoiar-nos. Obrigado!

👉 Siga André Bernardes no LinkedinClique aqui e contate-me via What's App.

Comente e compartilhe este artigo!

brazilsalesforceeffectiveness@gmail.com


 

 Compre OS LIVROS DESTAS SÉRIES 

 Série Donut Project 
DONUT PROJECT: VBA - Projetos e Códigos de Visual Basic for Applications (Visual Basic For Apllication)eBook - DONUT PROJECT 2024 - Volume 03 - Funções Financeiras - André Luiz Bernardes eBook - DONUT PROJECT 2024 - Volume 02 - Conectando Banco de Dados - André Luiz Bernardes eBook - DONUT PROJECT 2024 - Volume 01 - André Luiz Bernardes


eBook - PT - Série DONUT PROJECT - Volume 07 - VBA TOP 50 Códigos Mais Importantes - Access — André Luiz BernardeseBook - PT - Série DONUT PROJECT - Volume 07 - VBA TOP 50 Códigos Mais Importantes - Excel — André Luiz Bernardes eBook - PT - Série DONUT PROJECT - Volume 07 - VBA TOP 50 Códigos Mais Importantes - Outlook — André Luiz Bernardes eBook - PT - Série DONUT PROJECT - Volume 08 - VBA TOP 50 Códigos Mais Importantes - Project — André Luiz Bernardes  eBook - PT - Série DONUT PROJECT - Volume 08 - VBA TOP 50 Códigos Mais Importantes - Project — André Luiz Bernardes  eBook - PT - Série DONUT PROJECT - Volume 08 - VBA TOP 50 Códigos Mais Importantes - Word — André Luiz Bernardes

Nenhum comentário:

Postar um comentário

diHITT - Notícias