Caselle combinate a cascata con scelta (Tutto)

Ho creato alcuni video sul mio canale youtube in cui spiego come creare caselle combinate a cascata in Microsoft Access e come aggiungere la scelta (Tutto) a una casella combinata. Con poche istruzioni VBA (Visual Basic for Applications) possiamo mettere insieme le cose e fornire un’interfaccia efficace all’utente del nostro database.

Che cosa mi serve:

1) un database con le tabelle Fornitori, Prodotti e Categorie in relazione tra loro. Queste tabelle provengono dal solito database di esempio Northwind che trovate nel vostro PC (altrimenti leggete il mio post per fare il download del database)

Relazioni Northwind

2) una query, selFornitoriCategorie, che useremo come origine record per la casella combinata che elenca le categorie sulla nostra maschera

Query Fornitori Categorie

3) una query, selProdottiFiltrati, che useremo come origine record della maschera di ricerca

Query Prodotti Filtrati

4) una maschera che avrà come origine record la query selProdottiFiltrati

Maschera RicercaIn rosso i nomi da assegnare ai diversi controlli. Saranno utilizzati nel codice VBA.

Ora che abbiamo tutti gli oggetti necessari, dobbiamo impostare innanzitutto l’origine riga delle due caselle combinate.

a) Fornitore: l’origine riga è uguale a una istruzione SQL che usa UNION (vedi post e video):

SELECT IDFornitore, NomeSocietà 
FROM Fornitori 
UNION 
SELECT 0, "(Tutto)" 
FROM tblFinta 
ORDER BY NomeSocietà

Con la seconda SELECT creo un record con 0 (è uno zero) in prima colonna e (Tutto) nella seconda. Dal momento che i miei fornitori avranno un IDFornitore certamente diverso da 0, sono sicuro che non avrò doppioni. Con il codice, poi, controlleremo il valore della casella combinata Fornitore e se uguale a 0, dovremo rimuovere il filtro. Chiaro, no? :-). Per non “sprecare risorse”, ho creato una tabella tblFinta che contiene un solo campo (si chiama ID) e un solo record. Potete scrivere qualunque cosa. Mi serve soltanto perché quando creo la UNION ho bisogno di una tabella da cui leggere.

b) Categoria: l’origine riga è uguale a una istruzione SQL che usa UNION (vedi post e video):

SELECT IDCategoria, NomeCategoria 
FROM selFornitoriCategorie 
WHERE IDFornitore=[Maschere]![CercaProdotti]![cboFornitore]
UNION SELECT 0, "(Tutto)" 
FROM tblFinta

Come vedete, e l’abbiamo imparato in un altro video, il filtro è legato al valore impostato nella casella combinata del Fornitore.

Ora dobbiamo scrivere qualche istruzione di codice VBA.
Selezioniamo la casella del Fornitore e poi nelle proprietà degli eventi scegliamo l’evento Dopo aggiornamento.

Evento dopo aggiornamento

Cliccando sui 3 puntini si apre una finestra in cui scegliere Generatore di codice.

Generatore codice

Ora siamo nella finestra VBA (a cui si arriva anche premendo ALT+F11). Qui ci troviamo nell’evento After Update (ossia Dopo aggiornamento). Dopo la linea che inizia con Private e prima della linea che inizia con End scriviamo:

If Me.cboFornitore > 0 Then
    Me.Filter = "IDFornitore=" & Me.cboFornitore
    Me.FilterOn = True
    Me.cboCategoria.Requery
Else
    Me.cboCategoria.Requery
    Me.cboCategoria = ""
    Me.Filter = ""
    Me.FilterOn = False
End If

Abbiamo una IF:

If <condizione> Then <codice se la condizione è verificata> Else <codice se la condizione non è verificata> End If.

Se la casella del fornitore ha un valore > 0:
a) imposto il filtro sulla maschera
b) attivo il filtro
c) eseguo una requery, cioè ricarico i valori della casella combinata della categoria, così visualizzo solo le categorie legate al fornitore scelto

Se la casella del fornitore è uguale a 0, significa che l’utente ha scelto (Tutto), perciò:
a) eseguo una requery, cioè ricarico i valori della casella combinata della categoria, così visualizzo solo le categorie legate al fornitore 0. In tal modo svuoto l’elenco delle categorie.
b) cancello il valore eventualmente presente nella casella della categoria
c) cancello il filtro
d) disattivo il filtro dalla maschera.

Eseguiamo gli stessi passaggi per gestire l’evento Dopo aggiornamento della casella combinata della Categoria e scriviamo il seguente codice:

If Me.cboCategoria > 0 Then
    If Me.cboFornitore >0 Then
        Me.Filter = "IDFornitore = " & Me.cboFornitore & " AND IDCategoria =" & Me.cboCategoria
        Me.FilterOn = True
    End If
Else
    If Me.cboFornitore > 0 Then
        Me.Filter = "IDFornitore = " & Me.cboFornitore
        Me.FilterOn = True
    End If
End If

Se è stata scelta una categoria (quindi il valore è > 0), controllo se è stato anche scelto un fornitore. Se è stato scelto un fornitore, imposto il filtro sulla maschera al valore del fornitore e al valore della categoria; infine attivo il filtro.
Se non è stata scelta una categoria o è stato scelto (Tutto) e il Fornitore è stato scelto, imposto il filtro in base al valore del Fornitore e attivo il filtro.

Ultimo codice da scrivere per l’apertura del report. Questa volta l’evento da utilizzare è Su clic.

Il codice è il seguente:

Dim strFiltro As String
If cboFornitore > 0 Then
    strFiltro = "IDFornitore=" & Me.cboFornitore
End If
If cboCategoria > 0 Then
    strFiltro = strFiltro & " AND IDCategoria= " & Me.cboCategoria
End If
DoCmd.OpenReport "selProdottiFiltrati", acViewPreview, , strFiltro

Se è stato scelto il fornitore, memorizzo il filtro in una variabile stringa strFiltro, che ho dichiarato all’inizio con Dim. Poi controllo se è stata scelta la categoria. In caso positivo, aggiungo il filtro della categoria.

Infine apro il report. La costante acViewPreview fa sì che il report sia aperto in anteprima.

Se abbiamo seguito correttamente tutti i passi, dovremmo arrivare al risultato che vedete qui nel video.