Usare il Filtro Automatico con scelta libera del
campo e del criterio di ricerca.
Quando usiamo il
Filtro Automatico di Excel, sappiamo che dobbiamo selezionare la prima a
sinistra delle celle che formano le intestazioni di colonna, celle che
rappresentano i "campi" della tabella o database che dir si voglia,
dopodichè sceglieremo il "campo" che intendiamo filtrare applicando un
"criterio" di ricerca tra i valori presenti in quel campo. Non è altresì
difficile realizzare una macro che ci consenta di automatizzare tramite
codice vba le operazioni volute, semplicemente usando il "registratore
di macro".
L'esercizio che
presento si diversifica da una macro realizzata nel modo su esposto, in
quanto lasceremo al vba il compito di identificare l'area del database, di
contare il numero di colonne ( campi ) che formano il database, di chiederci
tramite una InputBox il numero di campo ( o colonna ) su cui vorremo
applicare il filtro, di trovare quanto è lungo l'elenco in modo da definire
tutte le righe in cui faremo cercare, tramite un'altra InputBox, il criterio
di ricerca sul quale applicare il filtro, e una volta accertato che il
criterio è presente, filtrare tutti i dati. Vediamo i passaggi, e alla fine
la routine completa:
-
come prima
condizione sarà quella di inserire nella sezione
Generale - Dichiarazioni del Modulo che
conterrà la nostra routine ( o macro che dir si voglia ) una semplice
istruzione che ha lo scopo di rendere indifferente l'uso di
maiuscole/minuscole nelle Inputbox che useremo per reperire le variabili.
(Diversamente la ricerca sarebbe CaseSensitive,
cioè sensibile alle maiusc/minusc. in quanto le istruzioni risiedono su un
Modulo)
Option Compare Text
-
identificare la
posizione della tabella (o database ) sul foglio di lavoro; per fare questo ci affideremo
all' UsedRange, (di cui esistono spiegazioni in
questa sezione, paragrafo "Copia/Incolla 4") e assegneremo con
l'istruzione Set, un nome alla tabella (zona)
dell'UsedRange nel foglio attivo:
Set zona = ActiveSheet.UsedRange
identificazione del numero di colonne da cui è formata la tabella. Questo ci
consentirà di usare il numero colonna per scegliere il campo su cui
applicare il filtro, anzichè il nome del campo, e di poter controllare poi
se abbiamo richiesto un numero di colonna che non esiste. Assegneremo ad una
variabile, la X, il numero di colonne ottenuto con questa istruzione:
X = zona.Columns.Count
Dim Campo
Dim Criterio
Campo = InputBox("Inserire il numero del campo di
ricerca")
-
inserimento di un
ciclio If...Then...End If per controllare
due eventi: il primo controlla che il valore restituito dalla inputbox
non sia vuoto, nel qual caso si uscirebbe dalla routine; precauzione
necessaria per evitare proteste del debugger che se si proseguisse con
l'esecuzione delle altre istruzioni si genererebbe un errore per mancanza di
dati (la variabile Campo non conterrebbe nessun
valore). Il secondo ciclo invece controlla se il valore numerico della
variabile Campo (
Val(Campo) ) è maggiore del numero di colonne che la variabile
X iniziale ha memorizzato. Se il valore sarà maggiore, verremo
avvisati con un messaggio e si uscirà dalla routine anche in questo caso.
If Campo = "" Then Exit Sub
If Val(Campo) > X Then
MsgBox "N° Campo non presente"
Exit Sub
End If
-
ora si passa ad
assegnare alla seconda variabile ( Criterio )
il valore che inseriremo nella seconda InputBox.
Anche qui eseguiremo il controllo per uscire se
Criterio sarà vuoto. Trattandosi di testo da assegnare a
Criterio, non sarà necessario dichiarare il "tipo"
di dato numerico ( Val(Criterio) ), necessario
peraltro nel caso che anche Criterio sia un valore numerico.
Criterio = InputBox("Inserire il criterio di ricerca")
If Criterio = "" Then Exit Sub
-
a questo punto
avremo bisogno, se vogliamo controllare la presenza del valore (Criterio)
da filtrare nel campo già deciso, di un ciclo di ricerca che partendo
dall'inizio della colonna identificata con Campo,
trovi quante righe sono presenti nella colonna, e in questo Range effettui
la ricerca. Per questo istruiremo un ciclo For Each....Next
, usando la procedura già vista tante volte su questo sito.
Dim CL As Object
-
dovremo far sapere
da quale riga e quale colonna iniziare,
rendendo "pippo"
uguale alla riga 1 dell'area "zona", colonna
numero Campo
Set pippo = zona.Cells(1, Val(Campo))
-
ora possiamo
inizializzare il ciclo "per ogni cella (CL)"
presente tra "pippo" e la fine di "pippo"
in basso (End(xlDown)
For Each CL In Range(pippo, pippo.End(xlDown))
-
se il valore di
una cella sarà uguale al valore memorizzato in
Criterio, allora...
If CL.Value = Criterio Then
-
in questo caso
(che il valore Criterio esista nell'elenco
della colonna scelta) avremo bisogno di interrompere il ciclo, passando alle
istruzioni di applicazione del filtro, ed useremo il vecchio
GoTo indicando a quale indice riga spostarsi
GoTo 10
-
nel caso che il
valore del Criterio non sia presente, il compilatore proseguirà cercando in
tutte le celle e alla fine concluderà la ricerca, e qui inseriremo un
messaggio che ci avviserà che il valore non è presente, uscendo dalla
routine:
End If
Next
MsgBox "Criterio Non presente"
Exit Sub
-
dopo questa
istruzione troveremo il riferimento all'indice riga a cui il compilatore
sarebbe saltato se il Criterio veniva trovato,
con a seguire l'istruzione per l'applicazione del filtro alla prima cella
della prima riga dell'area tabella ( zona ), e
l'indicazione del Campo e del
Criterio da applicare.
10:
zona.Cells(1, 1).Select
Selection.AutoFilter
Selection.AutoFilter Field:=Campo, Criteria1:=Criterio
zona.Cells(1, 1).Select
End Sub
e questa l'intera routine:
Sub RicercaeFiltra()
Set zona = ActiveSheet.UsedRange
X = zona.Columns.Count
Dim Campo
Dim Criterio
Campo = InputBox("Inserire il numero del campo di ricerca")
If Campo = "" Then Exit Sub
If Val(Campo) > X Then
MsgBox "N° Campo non presente"
Exit Sub
End If
Criterio = InputBox("Inserire il criterio di ricerca")
If Criterio = "" Then Exit Sub
Dim CL As Object
Set pippo = zona.Cells(1, Val(Campo))
For Each CL In Range(pippo, pippo.End(xlDown))
If CL.Value = Criterio Then
GoTo 10
End If
Next
MsgBox "Criterio Non presente"
Exit Sub
10:
zona.Cells(1, 1).Select
Selection.AutoFilter
Selection.AutoFilter Field:=Campo, Criteria1:=Criterio
zona.Cells(1, 1).Select
End Sub |
Nota per quanto
riguarda l'"UsedRange", faccio solo presente
che l'esempio sopra è impostato su un foglio in cui sia presente solo il
database, completo delle intestazioni dei "campi".
Se invece sul foglio, prima del database,
avessimo usato celle per scrivere altre cose, tipo "Ufficio
Statistiche", o altre amenità del genere, l'UsedRange
comprenderebbe nell'area anche queste celle, sballando completamente i
valori dell'identificazione dei riferimenti riga, colonna, ecc.ecc.
Un'altra cosa: visto che con l'applicazione di un filtro, compaiono i famosi
menù su ogni campo, sarebbe opportuno prevedere di poterli togliere e
ripristinare il database dopo la consultazione. Per fare questo, suggerisco
di usare un CommandButton delle ActiveX (Strumenti di controllo o Casella
degli strumenti) sfruttando la sua proprietà Caption, in modo da
differenziare nell'evento Click le istruzioni da seguire. Questo un
esempio(dopo aver impostato la sua proprietà Caption a "Filtro"):
Private Sub CommandButton1_Click()
If CommandButton1.Caption = "Filtro" Then
CommandButton1.Caption = "Ritorno" 'cambia la
caption "Filtro" in "Ritorno"
RicercaeFiltra 'chiama la routine sopra esposta
Else 'se invece la caption sarà diversa da
"Filtro", e quindi "Ritorno"
CommandButton1.Caption = "Filtro" 'reimposta la
caption a "Filtro"
Set zona = ActiveSheet.UsedRange 'e
toglie dalla cella 1 di "zona" il filtro
zona.Cells(1, 1).Select
Selection.AutoFilter
End If
End Sub Buon
lavoro.
prelevato sul sito http://ennius.interfree.it |