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
Parabéns Pedro Martins!!!
ResponderExcluirMais um artigo excepcional!!!
Obrigado :)
ExcluirBoa tarde Pedro.
ExcluirExiste alguma forma de eu procurar uma linha onde preciso encontrar na mesma mais de uma variavel?
Ou seja, preciso exatamente encontrar o "nome" a "característica" e a "idade" de uma pessoa em outra planilha.
Olá, alguém pode me ajudar?
ExcluirTenho um cadastro que é realizado pelo CPF e armazena CPF, Nome, RG, data nascimento e serviço.
Dependendo do serviço, o cliente pode ser cadastrado mais de uma vez no banco de dados, por exemplo:
CPF 012.345.678.99 cliente José serviço 01
CPF 012.345.678.99 cliente José serviço 02
CPF 012.345.678.99 cliente José serviço 04
Ocorre que quando vou fazer a pesquisa e digito o cpf de José, só aparece o primeiro serviço e quando clico de novo no botão “pesquisar” ela não faz a busca pelos outros serviços de Jose
Como faço para quando eu clicar no botão “pesquisar” novamente, ir aparecendo os outros serviços de jose? Ou seja, como faço para quando eu apertar o botão “pesquisar” apareça a informação de outra linha que tenha o número do CPF de josé?
Private Sub cmdPequisar_Click()
'Verificar se foi digitado um nome na primeira caixa de texto
If txtCPF.Text = "" Then
MsgBox "Digite o CPF de um cliente"
txtCPF.SetFocus
GoTo Linha1
End If
With Worksheets("Dados Clientes").Range("A:A")
Set c = .Find(txtCPF.Value, LookIn:=xlValues, lookat:=xlPart)
If Not c Is Nothing Then
c.Activate
TxtRg.Value = c.Offset(0, 1).Value
txtNome.Value = c.Offset(0, 2).Value
txtNascimento.Value = c.Offset(0, 3).Value
txtServiço.Value = c.Offset(0, 5).Value
'Carregando o botão de opção
If c.Offset(0, 4) = "Masculino" Then
OptionButton1.Value = True
Else
OptionButton2.Value = True
End If
Else
MsgBox "Cliente não encontrado!"
End If
End With
Linha1:
End Sub
òtimo , clareou meu entendimento , mas e seu quero pesquisar dois critérios? no meu projeto tenho o cod do funcionario e a loja onde está lotado. o codigo do funcionario pode se repetir, como buscar por exemplo o camarada cujo codigo é 200 e trabalha na loja x?
ResponderExcluirsabendo que a loja está na 1ª coluna e o codigo na 3ª coluna? é possíve retornar essa busca?
Olá,
ResponderExcluirMe ajuda, tenho um codigo ja em funcionamento em que estou pesquisando o que eu preciso, mais queria que a pesquisa pulasse a primeira linha, não pesquisasse nela, ja tentei muitas modificações porem não funciona:
Codigo:
Set intervalo = Range("A2:A65000")
Set plan = Sheets("Protocolo")
'Set x = plan.Rows.Find(what:=Pesquisa)
Set x = plan.intervalo.Find(what:=Pesquisa)
Desde já agradeço!
Coloque aí pra nois um exemplo de pesquisa usando esse método, mais pesquisar por cor um determinado valor, exemplo o número pode ter repetido"34" na cor vermelha e na cor azul, porém eu só quero bucar a q está de cor vermelha, tem como postar um código de como fazer isso?
ResponderExcluirEste comentário foi removido pelo autor.
ResponderExcluirMuito obrigado pelo tempo despendido para disponibilizar esse conhecimento!
ResponderExcluirEstou com problemas para fazer ele para no último nome correspondente da lista. Se aplico um loop, ele entra em loop eterno. Se não ele só pesquisa o primeiro nome correspondente como o do exemplo acima.
ResponderExcluir