Arquivo da categoria: Microsoft Office

Dicas sobre aplicativos Microsoft Office em geral

Extraindo tabelas de páginas Web com o Selenium Basic

E lá vai mais um vídeo tutorial de Selenium Basic, esse que parece ser o mais querido assunto desta comunidade de VBA, e o meu também. 🙂

Em complemento ao vídeo anterior e atendendo a alguns pedidos, aqui mostro como extrair um elemento de tabela de dentro de uma página web, algo que deve cobrir 90% do uso que se faz do Selenium.

Mais detalhes no vídeo:

E claro, o código:

Dim driver As WebDriver
 
Sub ExtrairTabelaDaPagina()
    Set driver = New ChromeDriver
    Dim destino As Range
    Set destino = Range("A1")
 
    driver.Get "https://github.com/florentbr/SeleniumBasic"
 
    Dim tabela As WebElement
 
    Set tabela = driver.FindElementByXPath("//div[@id='js-repo-pjax-container']/div[2]/div/div[6]/table")
 
    If tabela Is Nothing Then
        MsgBox "Elemento não encontrado"
    Else
        tabela.AsTable.ToExcel destino
    End If
 
    driver.Quit
End Sub

Bom proveito!

Vídeo – Migrando para o Selenium VBA

É, o Selenium fez barulho na comunidade do VBA. Pelo menos isso foi o que deu pra sentir, refletido tanto em questões no fórum, como em comentários no youtube e pedidos de serviço.

O fato é que o selenium tem crescido muito enquanto biblioteca e não só para o VBA. Tudo está muito bem explicado numa série de vídeos que gravei, de comentários a tutoriais (links no fim do artigo).

Por fim, como um auxílio para a migração do SeleniumVBA para o SeleniumBasic, explicado no vídeo “Selenium Basic Já”, gravei mais um tutorial com uma pincelada no código utilizando a nova biblioteca, que você confere abaixo:

Abaixo também segue o código utilizado para referência.

Dim driver As WebDriver
 
Sub ConsultaODolar()
    Set driver = New ChromeDriver
 
    driver.Get "http://www.dolarhoje.com"
 
    Dim nacional As WebElement
    Set nacional = driver.FindElementById("nacional")
 
    If nacional Is Nothing Then
        MsgBox "Elemento não encontrado"
    Else
        MsgBox nacional.Value
    End If
 
    driver.Quit
End Sub
 
Sub VaiProGoogle()
    Set driver = New ChromeDriver
 
    driver.Get "http://www.google.com"
    Application.Wait Now + TimeValue("00:00:01")
 
    Dim busca As WebElement, form As WebElement
    Set busca = driver.FindElementById("lst-ib")
    Set form = driver.FindElementById("tsf")
 
    If Not busca Is Nothing Then
        busca.SendKeys InputBox("Sua busca", "Google", "")
        form.Submit
    Else
        MsgBox "Elemento não encontrado"
    End If
End Sub

Bom proveito!

Usando o Selenium VBA para extrair informações da Web
https://www.youtube.com/watch?v=hk-65p2ivvQ&t=47s

Atualizando o ChromeDriver manualmente para o SeleniumBasic
https://www.youtube.com/watch?v=8fFnr-hmTW8

Selenium Basic já!
https://www.youtube.com/watch?v=WLP7QqgS8CA

Outros Links

SeleniumBasic
https://florentbr.github.io/SeleniumBasic/

ChromeDriver
https://sites.google.com/a/chromium.org/chromedriver/

Modelo de Cadastro – Dados no Excel vs Access

excelvsaccessOk, essa pergunta já passou muito tempo da minha cabeça, depois no fórum. Agora, vamos colocar isso em pratos limpos! Hehe…

O Modelo de Cadastro em Excel VBA (que você pode baixar aqui) meio que criou um quase-estigma de que é possível ter um sistema totalmente baseado em Excel, do aplicativo ao banco de dados. Essa segunda parte é a que mais me preocupa.

Tenho que confessar que quando criei o aplicativo, o objetivo foi demonstrar que era possível fazer tudo no Excel com VBA, sem outras dependências. Isso é muito poderoso se pensarmos em termos de negócios, já que o Excel está presente em quase 100% dos computadores corporativos. Isso dá ao usuário que detém esse conhecimento a liberdade de propor soluções complexas e completas sem precisar apelar para ferramentas adicionais, o que é uma realidade no mesmo mundo corporativo. Qualquer coisa “a mais” enfurece qualquer gestor, pois isso se traduz em mais gastos, mais licenças, mais falação com o departamento de infra-estrutura, etc, etc.

Até aqui, acredito que o aplicativo cumpriu seu objetivo. O problema, como dito umas frases atrás, é que a coisa toma proporções quase delirantes, ao ponto de que temos pensamentos sendo levados ao “dá pra fazer tudo no Excel!!!”. De fato, até que dá, até vírus! Alguém aí lembra dos vírus de macro? Enfim, o ponto é, não é porque você PODE que você DEVE fazer isso.

Não me levem a mal, eu acho bacana ver o povo criar versões do Mario (aqui) no Excel ou mesmo Pac-Man. Vale o mérito da conquista, mas no fim, isso é inútil para o mundo no qual o Excel faz sentido existir. Fazer por diversão, ok, mas não espere mais do que alguns “likes” por isso.

Voltando ao Modelo de Cadastro, o uso mais apropriado para ele, agora falando oficialmente (e eu posso! Fui eu que criei [=) é que ele seja um protótipo do que se pretende criar. Ele vai funcionar bem por um tempo, mas se a coisa ficar séria, é preciso dar o próximo passo. Entendo como sério o fato do mesmo começar a ser intensamente utilizado, ser utilizado por 3 ou mais usuários simultâneamente ou, no pior caso, a quantidade de registros começar a crescer generosamente. Se você chegar nesse ponto, já deve ter começado a sofrer alguns problemas de conflito de gravação ou lentidão excessiva.

Pois bem, agora que expus o objetivo máximo da minha criação, pontuei abaixo algumas vantagens e desvantagens da utilizando do modelo de cadastro, ou mesmo outros que a internet oferece, para o uso do Excel como banco de dados em comparação ao Access.

Em Excel
Vantagens

  • É mais fácil manipular os dados e sua estrutura, uma vez que está tudo no Excel

Desvantagens

  • O Excel não manipula bem acesso por múltiplos usuários ao mesmo arquivo, gerando facilmente erros quando de múltiplos acessos
  • É mais fácil corromper a estrutura, seja dos dados como tabela de dados em si, invalidando o aplicativo
  • Como o Excel não é feito para ser um banco de dados, o arquivo cresce rapidamente, prejudicando a performance ou até mesmo corrompendo os dados.
  • Validação, consistência a integridade dos dados é fraca

Em Access
Vantagens

  • Validação, consistência a integridade dos dados é nativa
  • É feito para manipular múltiplos acessos
  • Suporta melhor o crescimento dos dados e do arquivo
  • Conceitos como integridade referencial, chave primária, relacionamentos só estão presentes aqui
  • Para acesso ao banco de dados pelo VBA, não requer o Access instalado

Desvantagens

  • Manipular a estrutura é mais complexo e exige o Access
  • A manutenção do banco de dados exige um mínimo de conhecimento no Access

A lista acima não é absoluta. Ela é baseada em boa parte na experiência que tive com esse modelo. Gostaria inclusive que compartilhassem qualquer experiência que tiveram. Os comentários estão aí embaixo para isso.

Para você que já usa o modelo e quer migrar, nossa linda comunidade no fórum fez uma versão do mesmo, mas funcionando com o banco de dados em Access (aqui).

Existem outras variantes, com foto, com listview (que eu não gosto, mas isso eu explico em outro artigo), e outros que nem sei mais.

Opções não faltam. Opções de como usar, menos ainda. Vai do que sua necessidade demandar ou a do seu negócio.

Excel VBA – Unindo dados de planilhas de arquivos diferentes

Nós primórdios dos vídeos para a internet (lá pra 2006), publiquei um tutorial sobre como unir o dados de várias planilhas em uma só fazendo uma “maracutaia” com SQL para conseguir a façanha. O tutorial foi divido em 3 partes que ainda constam como os vídeos mais assistidos do meu canal no youtube:

Em todos estes anos publicado, um dos pedidos mais frequentes era como estender a proeza a vários arquivos. Por fim, eis um resultado.

Vejam a macro abaixo:

Option Explicit
 
Private Function ListaArquivos(ByVal Caminho As String) As String()
 
'Atenção: Faça referência à biblioteca Micrsoft Scripting Runtime
Dim FSO As New FileSystemObject
Dim result() As String
Dim Pasta As Folder
Dim Arquivo As File
Dim Indice As Long
 
ReDim result(0) As String
If FSO.FolderExists(Caminho) Then
    Set Pasta = FSO.GetFolder(Caminho)
 
    For Each Arquivo In Pasta.Files
      Indice = IIf(result(0) = "", 0, Indice + 1)
      ReDim Preserve result(Indice) As String
      result(Indice) = Arquivo.Name
    Next
End If
 
ListaArquivos = result
ErrHandler:
    Set FSO = Nothing
    Set Pasta = Nothing
    Set Arquivo = Nothing
End Function
 
Public Sub UnirTodos()
On Error GoTo trata_saida:
    Application.ScreenUpdating = False
    Application.DisplayAlerts = False
    
    Dim arquivos() As String
    Dim lCtr As Long, processados As Long
    arquivos = ListaArquivos(ThisWorkbook.Path)
    For lCtr = 0 To UBound(arquivos)
        If ValidaNomeArquivo(arquivos(lCtr)) Then
            'Debug.Print arquivos(lCtr)
            Call UnirAoArquivo(arquivos(lCtr))
            processados = processados + 1
        End If
    Next
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
    
    MsgBox processados & " arquivos processados"
trata_saida:
    Application.ScreenUpdating = True
    Application.DisplayAlerts = True
End Sub
 
Private Function ValidaNomeArquivo(ByVal nomeArquivo As String) As Boolean
    Dim result As Boolean
    result = InStr(1, nomeArquivo, ThisWorkbook.Name, vbTextCompare) = 0
    If result Then
        result = result Or Right(nomeArquivo, 4) = ".xls"
        result = result Or Right(nomeArquivo, 4) = "xlsx"
        result = result Or Right(nomeArquivo, 4) = "xlsm"
    End If
    ValidaNomeArquivo = result
End Function
 
Private Sub UnirAoArquivo(ByVal nomeArquivo As String)
On Error GoTo trata_erro_uniraoarquivo
    Dim wb As Workbook, ws As Worksheet, mySheet As Worksheet, rngCopy As Range
    Set wb = Workbooks.Open(ThisWorkbook.Path & "\" & nomeArquivo, ReadOnly:=True)
    Set ws = wb.Worksheets(1)
    Set mySheet = ThisWorkbook.Worksheets(1)
    
    'seleciona a regiao com conteudo
    Set rngCopy = ws.Range(ws.Cells(2, 1), ws.Cells(ws.UsedRange.Rows.Count, ws.UsedRange.Columns.Count))
    'copia
    rngCopy.Copy
    'cola no destino
    With mySheet
        Call .Paste(.Cells(.UsedRange.Rows.Count + 1, 1))
    End With
    
    wb.Close
trata_saida_uniraoarquivo:
    Set wb = Nothing
    Set ws = Nothing
    Exit Sub
trata_erro_uniraoarquivo:
    GoTo trata_saida_uniraoarquivo:
End Sub

Em resumo:

  • A macro da chama principal é a UnirTodos
  • Ela usa a Sub ListaArquivos (já mostrada aqui no blog) para obter a lista de arquivos que existem na mesma pasta do arquivo com as macros.
  • No meio do processo, a Function ValidaNomeArquivo que retorna um Boolean (Verdadeiro/Falso) confere se o arquivo possui uma extensão de Excel válida, neste caso, xls, xlsx e xlsm e também se não é o próprio arquivo.
  • Para cada arquivo válido encontrado na lista, a Sub UnirAoArquivo
  • A Sub UnirAoArquivo recebe somente o nome do arquivo como parâmetro. Com isso, ela:
    • abre o arquivo
    • seleciona a primeira planiha deste arquivo (índice 1)
    • copia a área ocupada (usando a propriedade UserRange)
    • cola o conteúdo na primeira planilha do arquivo corrente (que contém a macro) na primeira linha não ocupada.

O processo é repetido para cada arquivo válido na pasta. A velocidade de execução depende da quantidade de arquivos na pasta e claro, do poder do computador em questão.

Não há requisito para a estrutura do arquivo, ou seja, não é preciso que todas as planilihas tenham a mesma estrutura de colunas e na mesma ordem. Entretanto, esse tipo de união faz mais sentido quanto essa regra é aplicada.

Bom proveito!