☕DOE UM CAFÉ
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 TratamentoErroDim url As StringDim htmlDoc As ObjectDim linhaAtual As Long' Define a URL alvo contendo a tabela de estados brasileirosurl = "https://inanyplace.blogspot.com/2017/01/lista-de-estados-brasileiros-sigla-estado-capital-e-regiao.html"' Exibe mensagem informando início do processoApplication.StatusBar = "Iniciando extração de dados HTML..."' Faz download do conteúdo HTML da páginaSet htmlDoc = ObterDocumentoHTML(url)' Verifica se documento foi carregado com sucessoIf htmlDoc Is Nothing ThenMsgBox "Falha ao carregar a página HTML. Verifique a URL e conexão.", vbCriticalExit SubEnd If' Limpa a planilha ativa (remove dados anteriores)LimparPlanilha' Extrai todas as tabelas encontradas no documento HTMLlinhaAtual = ExtrairTodasAsTabelasHTML(htmlDoc, 1)' Exibe mensagem de sucesso com número de linhas extraídasApplication.StatusBar = "Extração concluída! Total de linhas: " & linhaAtual - 1MsgBox "Dados extraídos com sucesso! Foram importadas " & linhaAtual - 1 & " linhas.", vbInformation' Formata as colunas automaticamente para melhor visualizaçãoFormatarColunasApplication.StatusBar = ""Exit SubTratamentoErro:MsgBox "Erro: " & Err.Description, vbCriticalApplication.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 TratamentoErroDim xmlhttp As ObjectDim htmlDocument As ObjectDim tentativas As IntegerDim tempoEspera As Integer' Inicializa contador de tentativas e tempo de esperatentativas = 0tempoEspera = 2000 ' 2 segundos em milissegundos' Tenta fazer conexão com retry automático (até 3 tentativas)Do While tentativas < 3tentativas = tentativas + 1Try' Cria objeto para requisição HTTPSet xmlhttp = CreateObject("MSXML2.XMLHTTP.6.0")' Configura timeout para 30 segundosxmlhttp.setTimeouts 30000, 30000, 30000, 30000' Abre conexão com método GET na URL especificadaxmlhttp.Open "GET", urlAlvo, False' Adiciona header User-Agent para evitar bloqueios de botxmlhttp.setRequestHeader "User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"' Envia requisição ao servidorxmlhttp.Send' Verifica se a resposta foi bem-sucedida (código 200)If xmlhttp.Status = 200 Then' Cria novo documento HTML para armazenar respostaSet htmlDocument = CreateObject("htmlfile")' Carrega o HTML recebido no documentohtmlDocument.body.innerHTML = xmlhttp.responseText' Retorna documento HTML preenchidoSet ObterDocumentoHTML = htmlDocumentExit FunctionElse' Se falhou, aguarda um pouco e tenta novamenteApplication.Wait Now + TimeValue("0:00:02")End IfCatch' Em caso de erro, aguarda e tenta novamenteApplication.Wait Now + TimeValue("0:00:02")End TryLoop' Se chegou aqui, todas as tentativas falharamSet ObterDocumentoHTML = NothingExit FunctionTratamentoErro:Set ObterDocumentoHTML = NothingEnd 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 TratamentoErroDim tabelas As ObjectDim tabela As ObjectDim indiceTabela As IntegerDim linhaAtual As Long' Inicializa contador de linhaslinhaAtual = linhaInicial' Obtém todas as tags TABLE do documento HTMLSet tabelas = htmlDoc.getElementsByTagName("TABLE")' Se não encontrou tabelas, retorna linha inicialIf tabelas.Length = 0 ThenExtrairTodasAsTabelasHTML = linhaAtualExit FunctionEnd If' Percorre cada tabela encontradaFor indiceTabela = 0 To tabelas.Length - 1' Obtém referência para tabela atualSet tabela = tabelas.Item(indiceTabela)' Extrai dados da tabela atual e atualiza contador de linhaslinhaAtual = ExtrairUmaTabela(tabela, linhaAtual)Next indiceTabela' Retorna total de linhas preenchidasExtrairTodasAsTabelasHTML = linhaAtualExit FunctionTratamentoErro:ExtrairTodasAsTabelasHTML = linhaAtualEnd 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 TratamentoErroDim linhas As ObjectDim linha As ObjectDim celulas As ObjectDim celula As ObjectDim indiceLinhas As IntegerDim indiceColunas As IntegerDim linhaAtual As LongDim colunaAtual As IntegerDim textoCelula As String' Inicializa contadoreslinhaAtual = linhaInicial' Obtém todos os elementos TR (linhas) dentro da tabelaSet linhas = tabela.getElementsByTagName("TR")' Se tabela vazia, retorna linha inicialIf linhas.Length = 0 ThenExtrairUmaTabela = linhaAtualExit FunctionEnd If' Percorre cada linha da tabelaFor indiceLinhas = 0 To linhas.Length - 1' Obtém referência para linha atualSet linha = linhas.Item(indiceLinhas)' Obtém todos os elementos TD ou TH (células) da linhaSet celulas = linha.getElementsByTagName("TD")' Se não encontrou TD, tenta TH (header cells)If celulas.Length = 0 ThenSet celulas = linha.getElementsByTagName("TH")End If' Se ainda não encontrou células, pula para próxima linhaIf celulas.Length = 0 ThenGoTo ProximaLinhaExternoEnd If' Reinicia contador de colunas para nova linhacolunaAtual = 1' Percorre cada célula da linhaFor indiceColunas = 0 To celulas.Length - 1' Obtém referência para célula atualSet celula = celulas.Item(indiceColunas)' Extrai texto da célula, removendo espaços extrastextoCelula = Trim(celula.textContent)' Preenche célula da planilha com texto extraídoCells(linhaAtual, colunaAtual).Value = textoCelula' Move para próxima colunacolunaAtual = colunaAtual + 1Next indiceColunas' Move para próxima linha apenas se célula foi preenchidaIf colunaAtual > 1 ThenlinhaAtual = linhaAtual + 1End IfProximaLinhaExterno:Next indiceLinhas' Retorna número da próxima linha disponívelExtrairUmaTabela = linhaAtualExit FunctionTratamentoErro:ExtrairUmaTabela = linhaAtualEnd 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 planilhaCells.Select' Deleta conteúdo das células selecionadasSelection.Delete' Posiciona cursor na célula A1Range("A1").SelectExit SubTratamentoErro:' Se ocorrer erro, apenas prossegueEnd 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 dadosCells.Select' Ajusta largura das colunas automaticamente ao conteúdoSelection.Columns.AutoFit' Aplica bordas simples em todas as células com dadosSelection.Borders.LineStyle = xlContinuousSelection.Borders.Weight = xlThin' Aplica formatação de negrito na primeira linha (headers)Range("1:1").Font.Bold = TrueRange("1:1").Interior.Color = RGB(200, 200, 200)' Congela a primeira linha para facilitar navegaçãoRows("2:2").SelectActiveWindow.FreezePanes = True' Posiciona cursor na célula A1Range("A1").SelectExit SubTratamentoErro:' Se ocorrer erro, apenas prossegueEnd Sub
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 Linkedin. Clique aqui e contate-me via What's App.











Nenhum comentário:
Postar um comentário