VBA - Artigo 022 - Efetuando pesquisas com o método Find

Progredindo em VBA no Microsoft Excel

Efetuando pesquisas com o método Find

No último artigo usei o método Find para ajudar a encontrar a última linha ou última coluna de um intervalo. Como certamente despertou uma curiosidade, resolvi escrever este artigo para dar uma explicação mais detalhada.

O método de pesquisa mais popular entre usuários intermediários a avançados é o PROCV (VLOOKUP, no original em inglês, que é o utilizado no VBA). Outra alternativa comum é usar os métodos ÍNDICE e CORRESP (INDEX e MATCH, respectivamente). Entretanto, nem sempre é necessário ou mesmo possível usar esses comandos: às vezes queremos simplesmente saber se um determinado valor existe em um intervalo de células; em outros casos, precisamos pesquisar por valores não exatos, o que provavelmente demandaria uma estrutura de repetição para verificar cada célula se corresponde ao valor desejado.

Para pesquisas mais simples ou para pesquisar mais de uma ocorrência de um determinado valor, podemos usar o método FIND em um intervalo. Sua forma de uso é a seguinte:

Range(Intervalo).Find(What, After, LookIn, LookAt, SearchOrder, SearchDirection, MatchCase, MatchByte, SearchFormat)

A quantidade de parâmetros assusta à primeira vista, mas somente o primeiro parâmetro (What) é obrigatório e todos os outros são opcionais. Entretanto, como será visto logo adiante, há parâmetros que devemos colocar sempre. Vejamos a função de cada parâmetro:

- What: O valor a ser pesquisado. Pode ser um texto, um valor numérico, uma data, ou seja, quaisquer tipos de dados possíveis em uma célula;

- After: Indica a célula após a qual a pesquisa será feita, sendo útil quando encontra um valor e quer pesquisar outras ocorrências de um valor no mesmo intervalo;

- LookIn: Especifica em que tipo de informação o valor será pesquisado. O parâmetro pode assumir os valores xlValues (valores das células), xlFormulas (valores em fórmulas, mas não o resultado da fórmula) ou xlComments (comentários). O valor padrão é xlFormulas;

- LookAt: Determina se a busca será parcial ou total. Os valores possíveis são xlPart (parcial, valor padrão) e xlWhole (total);

- SearchOrder: Indica se a pesquisa será feita por linhas ou colunas. Os valores possíveis são xlByRows e xlByColumns, respectivamente. O valor padrão é xlByRows;

- SearchDirection: Indica a direção da pesquisa. Os valores possíveis são xlNext (próximo, pesquisa para a frente) e xlPrevious (anterior, pesquisa para trás). O valor padrão é xlNext;

- MatchCase: Parâmetro booleano que indica se há distinção de maiúsculas e minúsculas. O valor padrão é False;

- MatchByte: Parâmetro booleano também, deve ser usado somente quando há caracteres de idiomas que usem dois bytes por caracter. True localiza apenas quando os caracteres de dois bytes forem iguais, False localiza também caracteres equivalentes em um byte;

- SearchFormat: Outro parâmetro booleano, True especifica se a busca será por algum formato específico. Neste caso, será preciso definir o objeto Application.FindFormat com propriedades que especifiquem qual o formato das células que serão pesquisadas. Por exemplo, definindo a propriedade Application.FindFormat.Font.Color com o valor vbRed fará o Excel pesquisar somente nas células com cor de texto em vermelho.


Lembra da janela de pesquisa do Excel? Há um botão Opções, que estende a janela com mais alguns parâmetros:



Para ajudar a compreender melhor a função de cada parâmetro, vamos associá-los com os campos dessa janela. O parâmetro What é o que digitamos no campo Localizar; LookIn representa o campo Examinar (note que o valor padrão é Fórmulas); LookAt equivale à caixa Coincidir conteúdo da célula inteira; SearchOrder é o campo Pesquisar (valor padrão Por linhas), o MatchCase é a caixa Diferenciar maiúsculas de minúsculas e por fim SearchFormat equivale ao botão Formatar. O parâmetro After pode ser associado ao botão Localizar próxima, levando em conta que ele sempre pesquisa após a célula ativa. Já os parâmetros SearchDirection e MatchByte não têm equivalentes nessa janela, mas seu entendimento é simples.

É importante saber que os parâmetros LookIn, LookAt, SearchOrder e MatchByte são definidos para as pesquisas subsequentes, ou seja, se na primeira pesquisa você definir SearchOrder como xlByColumns e na pesquisa seguinte não especificar valor, a pesquisa será por colunas, mesmo que o valor padrão seja xlByRows. Como o MatchByte dificilmente será alterado (a menos que você trabalhe com caracteres do leste asiático), é interessante definir sempre os outros três parâmetros. Lembre-se que o código pode ser alterado no futuro e pode haver necessidade de acrescentar um novo Find com parâmetros diferentes e a nova pesquisa pode acabar interferindo na anterior, dependendo de como o código é executado. Desta forma, o ideal é sempre usar a seguinte forma:

Range(Intervalo).Find(What, LookIn, LookAt, SearchOrder)

Depois que uma primeira pesquisa foi realizada, pode-se realizar outras subsequentes acrescentando o valor da pesquisa anterior no parâmetro After. Assim, uma nova pesquisa será realizada a partir daquela célula.

Após uma pesquisa realizada também é possível utilizar os métodos FindNext e FindPrevious, que, como o próprio nome diz, buscam pelo valor para a frente ou para trás, respectivamente. Forma de uso:

Range(Intervalo).FindNext(After)
Range(Intervalo).FindPrevious(After)

O parâmetro After funciona de maneira similar ao parâmetro homônimo em Find. Embora seja considerado opcional, é sempre bom colocar o valor da última pesquisa realizada. Há relatos de que estes métodos não estão encontrando as próximas ocorrências se não for fornecido o parâmetro, o que confirmei em alguns testes.

Da mesma forma que na janela de Localizar e Substituir, é possível utilizar caracteres máscaras para ajudar na busca dos dados. Colocar "Pedro*" no parâmetro What (com LookAt sendo xlWhole) irá localizar todos os nomes que comecem com Pedro e não incluirá os que tenham esse nome no meio ou fim. "*Pedro*", por outro lado, incluirá nomes que tenham Pedro em qualquer parte do nome, funcionando da mesma forma que pesquisar por "Pedro" com LookAt sendo xlPart. Da mesma forma, colocar "Ant?nio" no parâmetro What irá localizar os valores Antonio, Antônio e António (comum em Portugal).

Uma forma de demonstrar o funcionamento é com um código de exemplo:

Sub TesteFind()

    Dim Intervalo As Range
    Dim Valor As String
    Dim Resultado As Range
    Dim ResultadoAnterior As Range
   
    Set Intervalo = Range("A1:A1000")
    Valor = "Pedro*"
    Set Resultado = Intervalo.Find(Valor, LookIn:=xlFormulas, LookAt:=xlWhole, _
        SearchOrder:=xlByColumns)
   
    If Resultado Is Nothing Then
        Debug.Print "Valor não encontrado"
        Exit Sub
    End If
   
    Do
        Debug.Print Resultado.Value
        Set ResultadoAnterior = Resultado
        Set Resultado = Intervalo.Find(Valor, After:=ResultadoAnterior, _
            LookIn:=xlFormulas, LookAt:=xlWhole, SearchOrder:=xlByColumns)
    Loop Until Resultado.Row < ResultadoAnterior.Row
   
End Sub

Suponha que você tenha uma lista com mil nomes diferentes no intervalo A1 a A1000 e você quer pesquisar quais nomes começam com "Pedro". Esse código irá exibir na área de Verificação Imediata todos os nomes encontrados.

Como esse código funciona? Primeiramente, criei as variáveis e depois coloquei os valores em Intervalo e em Valor. Em seguida, Resultado receberá a célula com o primeiro resultado da pesquisa. Se não for encontrado nada (Resultado Is Nothing), será exibida uma mensagem e a sub-rotina será encerrada. Se houver um valor, entrará em uma estrutura de repetição para verificar outros valores que possam haver no intervalo.

Essa estrutura de repetição verifica se a linha (Row) de Resultado é menor que a linha de ResultadoAnterior, o que significaria que a pesquisa voltou ao começo do intervalo (lembre-se que o funcionamento é similar ao da janela Localizar e Substituir). Perceba que a verificação é feita ao final do loop, assim o interior dele é executado pelo menos uma vez.

Dentro da estrutura, o conteúdo da célula é exibido e então ResultadoAnterior recebe o valor de Resultado, que por sua vez recebe o resultado da próxima pesquisa. Note que aqui há o parâmetro After com o valor de ResultadoAnterior, para que esta nova pesquisa inicie logo após essa célula. Poderia ter usado o FindNext, mas para fins didáticos mantive o Find, para acrescentar o parâmetro After.

O loop se repetirá até que a pesquisa volte ao início do intervalo e Resultado receba o primeiro valor encontrado. Execute o código passo a passo com F8 para acompanhar os valores das linhas para perceber melhor como funciona. Se não tiver uma lista grande de nomes para testar, pode testar com uma quantidade menor e alterar o intervalo da pesquisa e colocar o nome que quiser na pesquisa.

É possível fazer essa pesquisa com uma estrutura de repetição verificando cada célula individualmente? Sim, porém em listas muito grandes a pesquisa levaria muito tempo, podendo levar até vários minutos. Usando o método Find reduz o tempo de processamento absurdamente, levando apenas poucos segundos.

Espero que o artigo seja de grande valia para futuras rotinas de pesquisa. Até o próximo artigo.

Pedro Martins


Pós-graduando em Business Intelligence e Big Data pela Faculdade Impacta de Tecnologia. Formado em Tecnologia em Eletrônica Digital com Ênfase em Microprocessadores






Catálogo de aulas (NOVIDADE)

Criei um catálogo de aulas para ajudar você em seus estudos. Acesse clicando na imagem abaixo ou clique aqui.


Postagem Anterior Próxima Postagem