RICERCA INTERATTIVA (AL VOLO, DURANTE LA DIGITAZIONE) DI TESTO IN TABELLA TRAMITE QUERY

interattiva

Oggi vi propongo una soluzione ad un piccolo problema che molti di voi mi hanno chiesto di affrontare: In sostanza si tratta di ricercare “al volo” un testo all’interno di uno (o più) campi di una tabella mostrando immediatamente il risultato.

Ci sono diversi modi per affrontare questo tipo, diciamo così, di “problema” ma voglio proporvene uno che probabilmente attirerà l’attenzione di molti poiché utilizza alcune tecniche poco note e certamente utilizzabili in ambiti diversi da quello dell’esempio, volutamente molto semplice.

La ricerca interattiva, come qualunque interrogazione al DB, DEVE essere effettuata tramite una query, lo strumento fondamentale di ricerca di ogni Database.

Immaginiamo dunque di avere a che fare con una tabella “Articoli” 

e immaginiamo di voler cercare nel campo “descrizione” il termine “Binzel” (o qualsivoglia altra cosa).

L’approccio che vi propongo è quello di creare una query nella quale il filtro venga determinato non dal valore diretto di un campo di testo presente sulla form ma tramite il valore assunto da una variabile VBA.

Avete capito bene: è possibile, anche direttamente nella query by example, utilizzare come criterio di filtro il valore assunto più o meno arbitrariamente da una variabile.

Il primo passo è quello di dichiarare nome e tipo della variabile e renderla “pubblica”. Quest’ultimo concetto è semplice: “il cui valore è valido in qualsiasi contesto e quindi anche al di fuori di una specifica routine”.

Dunque per prima cosa creiamo un modulo VBA (l’oggetto in cui inseriremo il nostro codice): Strumenti Database-> Visual Basic -> Inserisci -> Modulo

Quanto al nome, lasciate pure quello di default: lo si potrà cambiare, all’occorrenza, in qualunque momento.

Un modulo vuoto contiene una sola riga: “Option Compare Database

Appena sotto scriviamo il seguente codice:

Public myString As String

myString è la variabile pubblica che conterrà il testo da ricercare tramite la query.

Creiamo ora il codice necessario all’interrogazione efficace della query che utilizzeremo per filtrare i dati.

Appena al di sotto della dichiarazione precedente scriviamo:

Public Function myquery()

myquery = “*” & myString & “*”

End Function

La funzione sopraesposta, anch’essa di tipo Public, semplicemente aggiungerà al testo che digiteremo per la ricerca un paio di asterischi prima e dopo quel testo. Se digiteremo “pippo”, questa funzione metterà nella variabile myString *pippo*

L’asterisco, per chi non lo sapesse, è un “carattere jolly” di VBA che significa “un numero arbitrario di caratteri qualunque“.

Adesso occupiamoci della query vera e propria.

Dal menù cliccate su Crea -> Struttura query e trascinate la tabella “articoli” sullo stage. Selezionate tutti i campi della tabella e trascinateli (tutti insieme o uno per volta) sulla barra sottostante. Inserite dunque il criterio di filtro

La parola chiave Like impostata nel criterio del campo “descrizione” ordinerà al motore SQL di cercare la stringa indicata anche all’interno di parole più estese.

Ebbene, quello che vi ho appena mostrato fin qui è proprio quanto promesso: La query filtrerà il contenuto di una variabile VBA.

Salvate e chiudete la query. Verrà salvata con il nome di Query1, va benissimo così.

Adesso passiamo alla maschera (form) per l’interrogazione:

Dal Menu cliccate su Crea->Maschera vuota->Visualizza->Visualizzazione struttura

Dal menù progettazione inseriamo una casella di testo sul corpo della form.

Quest’oggetto assumerà il nome, con tutta probabilità, di “Testo0 (non associato)”

Fatto questo, trascinate la Query1 nel corpo della maschera. In questo modo chiediamo ad Access di creare una sottomaschera per la visualizzazione dei risultati della query. Assegnatele il nome di SMQuery1 e sistematela un po’ in larghezza e posizione. Attenzione al nome. Niente spazi. Questo nome sarà fondamentale nel codice che scriveremo fra un po’.

Salviamo la maschera senza uscire dalla modalità di progettazione, clicchiamo con il tasto destro del mouse sulla casella di testo Testo0 (non sull’etichetta!!! dovete cliccare dove compare la scritta “non associato“) e scegliamo la voce “proprietà“.

Si aprirà sulla destra una nuova colonna, un frame, con elencate le proprietà della casella di testo.

Essendo tantissime (le proprietà configurabili), questa colonna contiene alcune tab (linguette).

Quella che ci interessa è la tab “evento”. In particolare andremo a programmare l’evento “su tasto su“.

Il codice associato a questo evento viene lanciato ogni volta che un tasto, premuto, viene rilasciato.

In cambio, a livello di VBA, Access restituisce due variabili locali: KeyCode Shift.

KeyCode è una variabile locale che contiene il codice ASCII in notazione decimale del tasto appena premuto. La variabile locale Shift contiene invece i valori booleani 1 e 0 a seconda che sia stato o meno premuto il tasto “shift” ovvero il maiuscolo temporaneo.

L’utilizzo opportuno della variabile Keycode può dunque darci l’opportunità di costruire un comodissimo Keylogger locale (keylogger=un programma che intercetta quali tasti sono stati premuti e ne memorizza la sequenza) ed è esattamente ciò che faremo.

Dunque cliccate sul tab evento, cliccate su “su tasto su“, scegliete di inserire una “routine evento” ed immediatamente si aprirà la finestra VBA posizionata proprio all’interno di questo specifico evento:

A questo punto cerchiamo di elaborare il codice VBA che ci è necessario.

Dobbiamo creare un piccolo keylogger locale per intercettare il testo ogni volta che viene inserita una nuova lettera (pigiato un tasto) e avviare l’aggiornamento della query legata alla sottomaschera presente nella form, in modo da avere sempre a disposizione il risultato aggiornato.

Ricordiamoci che il testo NON verrà copiato dalla casella di testo: verranno intercettati i tasti premuti!

Ecco il codice necessario:

Lung = Len(myString) 

If KeyCode = 46 Then myString = “”: Me.Testo0.Value = “”

If KeyCode = 8 Then 

    If lung = 0 Then GoTo 100 ‘se la lunghezza è 0 non serve intervenire, il campo è vuoto

    If lung = 1 Then myString = “”: GoTo 100 ‘se la lunghezza è 1, semplicemente svuotiamo la variabile

 myString = Left$(myString, lung – 1): GoTo 100 ‘togliamo un carattere dalla stringa

End If

myString = myString & Chr$(KeyCode) ‘aggiungiamo il carattere digitato alla stringa

100 ‘fine della sub

Me.SMQuery1.Requery

Spieghiamolo:

In primo luogo calcoliamo la lunghezza di testo contenuto nella variabile myString:

 lung = Len(myString)

affidiamo questo valore alla variabile lung, per facilitarci la programmazione.

Qualora venisse intercettato il tasto 49, “Canc“, svuotiamo la variabile myString e cancelliamo l’intero contenuto di Testo0:

If KeyCode = 46 Then myString = “”: Me.Testo0.Value = “”

Il codice 8 è il “backspace” ovvero la cancellazione del testo a sinistra.

Se viene intercettata la pressione di questo tasto, vuol dire che l’utente ha voluto cancellare un carattere e dunque ci comportiamo di conseguenza tramite l’istruzione Left$ (prendi un certo numero di caratteri a sinistra del testo).

Esistono però due condizioni particolari:

1) quando il campo è vuoto (ha premuto backspace per sbaglio, lung =0) oppure

2) quando è stato digitato un solo carattere (lung=1), il che equivarrebbe a svuotare comunque la stringa mystring:

If KeyCode = 8 Then 

    If lung = 0 Then GoTo 100 ‘se la lunghezza è 0 non serve intervenire, il campo è vuoto

    If lung = 1 Then myString = “”: GoTo 100 ‘se la lunghezza è 1, semplicemente svuotiamo la variabile

 myString = Left$(myString, lung – 1): GoTo 100 ‘togliamo un carattere dalla stringa

End If

La riga che segue è il vero e proprio keylogger: intercetta il tasto digitato e lo converte in carattere aggiungendolo in coda alla stringa myString:

myString = myString & Chr$(KeyCode) 

Infine dobbiamo ricordarci di aggiornare i risultati della query. Questa operazione è svolta dalla riga:

Me.SMQuery1.Requery

Il codice esposto non è scevro da difetti:

Bisognerebbe renderlo molto più “solido” intercettando alche l’eventuale pressione accidentale di tasti e/o di movimenti “incolsulti” del mouse da parte dellutente.

Purtuttavia credo sia molto utile dal punto di vista didattico.

Infine:

Un’operazione fondamentale che manca all’appello è quella di assicurarci, avendo utilizzato una variabile public, di svuotarla ogni volta che apriamo la form d’interrogazione.

Il rischio è quello di effettuare una ricerca incongruente poiché, oltre ai tasti digitati, è possibile che venga ricordata la stringa di una ricerca precedente.

Similmente a come abbiamo fatto prima, ma stavolta NON nelle proprietà di Testo0 ma nelle proprietà generali della form (cliccate in uno spazio vuoto, in basso, al di fuori del corpo della form) clicchiamo sulla tab evento e scegliamo di inserire unaroutine evento sulla proprietà “su caricamento“:

A questo punto dovremmo esserci, è praticamente tutto.

Caricherò il file di esempio QUI (codice 11).

[mx_youtuber type="video" id="_pGZ2MvScSU"]

 

 

No thoughts on “RICERCA INTERATTIVA (AL VOLO, DURANTE LA DIGITAZIONE) DI TESTO IN TABELLA TRAMITE QUERY”