Ricerca di dati in un elenco di un foglio di lavoro

Usare il metodo Find

Per dimostrare che sfruttando gli esempi contenuti nella guida in linea dell'Editor di Visual Basic, è possibile, con piccole modifiche, adattare gli esempi alle nostre necessità, presento alcune soluzioni possibili sfruttando l'esempio collegato al metodo Find. Questo sotto è quanto riportato nella "Guida il linea", ottenibile anche premendo il tasto F1, quando ci si trova nell'editor di visual basic:

(N.B. la seguente routine, presa dalla guida contiene un piccolo bug. Vedi la segnalazione a pagina 5 de "le vs domande", paragrafo "Errori sulla Guida")

 

Esempio dalla guida in linea (cito:)
Questo esempio trova tutte le celle nell'intervallo A1:A500 sul foglio di lavoro 1 contenenti il valore 2 e modifica il valore in 5.

With Worksheets(1).Range("a1:a500")
Set c = .Find(2, lookin:=xlValues)
If Not c Is Nothing Then
firstAddress = c.Address
Do
c.Value = 5
Set c = .FindNext(c)
Loop While Not c Is Nothing And c.Address <> firstAddress
End If
End With

 

E queste sono alcune possibili varianti, la prima ipotizza l'utilizzo di una cella per l'introduzione del dato da cercare (vettore). La cella d'esempio ( Cells(1, 2).Value ) identifica la cella B1, e avremmo potuto usare indifferentemente la notazione Range("B1").Value, sarebbe stato lo stesso, forse più semplice da usare e da riconoscere per colui che compìla l'istruzione. A questa cella viene associata la variabile stringa X in modo che, qualunque testo si scriva in B1, venga identificato con la X. Se il valore da cercare, anzichè testo, fosse un numero, sarebbe necessario definire la X non come String ma come Variant  (Variant accetta sia testo che numero, solo occupa un pò più di spazio in memoria). Sempre per fare l'esempio, diremo che i dati si trovano sul Foglio1, nel Range A2:H100. Ovviamente ognuno metterà i riferimenti alla zona dove vorrà eseguire la ricerca, che potrà essere più ampia, o anche una sola colonna da una determinata riga ad un altra. Una particolarità legata al tipo di ricerca, è questa: con la seguente istruzione, verranno cercati valori esatti al valore da cercare : Set c = .Find(X, LookIn:=xlValues, LookAt:=xlWhole), con la seguente istruzione verranno invece trovati valori che sono una parte del valore cercato: Set c = .Find(X, LookIn:=xlValues), se, per esempio, in B1 digitiamo. "pape", verranno trovati anche "papero", op. "paperino", ecc.ecc. La seguente routine cerca quindi il valore dato, e se lo trova, seleziona la cella, altrimenti avvisa con un messaggio "Nome non Trovato".

Sub Cerca1()

With Worksheets(1).Range("A2:H100")
Dim X As String
X = Cells(1, 2).Value
Set c = .Find(X, LookIn:=xlValues, LookAt:=xlWhole)

If Not c Is Nothing Then
firstAddress = c.Address
Do
c.Cells.Select
Set c = .FindNext(c)
Loop While Not c Is Nothing And c.Address <> firstAddress

Else
MsgBox "Nome non Trovato"
End If
End With
End Sub


Questo che segue è un'altro esempio, in cui l'introduzione del dato da cercare passa attraverso una InputBox, e quindi viene usata la imputbox come vettore per la ricerca:

Sub Cerca2()

With Worksheets(1).Range("A2:H100")
Dim Message, Title, MyValue

Message = "Inserisci il nominativo da cercare :"
Title = "Ricerca Dati"
' Imposta il titolo.

' Visualizza il messaggio, il titolo
MyValue = InputBox(Message, Title)

Dim X As String
X = MyValue 
'viene assegnato alla X il contenuto della Inputbox
Set c = .Find(X, LookIn:=xlValues, LookAt:=xlWhole)

If Not c Is Nothing Then
firstAddress = c.Address
Do
c.Cells.Select
Set c = .FindNext(c)
Loop While Not c Is Nothing And c.Address <> firstAddress

Else
MsgBox "Nome non Trovato"
End If
End With
End Sub

Un altro modo per eseguire una ricerca, e senza il metodo Find, è la seguente, però senza messaggio di avviso, visto che se trova il dato lo seleziona, se non lo trova vuol dire che il dato non è presente

Sub Cerca3()

For Each c In Worksheets("Foglio1").Range("A2:H100")
If c.Value = Range("B1").Value Then
c.Select
Exit For
End If
Next c

End Sub

Volendo, anche per quest'ultima routine, è possibile sfruttare l'assegnazione del vettore ad una variabile, oppure usare una InputBox; sarà sufficiente sostituire If c.Value = Range("B1").Value Then con If c.Value = X Then...  oppure If c.Value = MyValue Then...

 

NUOVO:

Un problema di tutti i cicli di ricerca (ovviamente dipende dalla procedura scelta), è che quando in un elenco ci sono più dati uguali, il ciclo, o trova il primo (come negli esempi sopra), e li si ferma, e se lo fai ripartire inizia da capo e si riferma al primo, o li trova tutti ma si ferma all'ultimo. Questo secondo caso avviene perchè nel ciclo in genere si usa l'istruzione "se lo trovi, selezionalo", ed il ciclo lo fa, ma dopo averlo selezionato prosegue e se trova altri valori uguali, li seleziona fintantochè non trova l'ultimo valore e si ferma. Allora ho pensato di inserire un'istruzione che blocchi il ciclo se trova il valore cercato, ma che lo possa riavviare dal punto in cui si è fermato; la soluzione più semplice e quella che riporto sotto, dove nel caso venga trovato il valore, faccio apparire una msgbox Si/No, che interrompe il ciclo, con una domanda: " Ti vuoi fermare?" Se premi Si, esci dal ciclo, se premi No, prosegue nel ciclo dal punto in cui si era fermato, e per ogni valore uguale si riferma e ripone la domanda. Semplice no?

Sub cerca()
Dim CL As Object
For Each CL In Range("A1:A2000")
'colonna in cui esegue la ricerca
Dim X
X = Range("D1").Value
'cella che porta il valore da cercare
If CL = X Then
'se la cella (CL) è ugule a X
CL.Select
'faccio selezionare (fermo il ciclo) questa cella
Y = Mid(CL.Address, 2, 1) + Mid(CL.Address, 4, 5)
'con Y prendo il 'riferimento alla cella che poi uso nella domanda
Dim irisposta As Integer
'Imposto la msgbox e relativa domanda
irisposta = MsgBox("Trovato in " & Y & " Vuoi fermarti ?", vbYesNo)
If irisposta = vbYes Then
'se rispondo Si allora
Exit For
  'esco dal ciclo
End If
End If
Next CL
'altrimenti proseguo al successivo
End Sub
 

Come per le altre routine, anche in questa la variabile X può venir assegnata attraverso una InputBox.

Buon lavoro.