Gekoppelde keuzelijsten

Een regelmatig terugkerende vraag is die waarbij de vragensteller via een keuzelijst-met-invoervak een waarde wil kiezen, waarbij de gekozen waarde dan meteen een beperking is voor een volgende keuzelijst-met-invoervak.

In het voorbeeld heb ik de situatie uitgewerkt waarbij tijdens het invoeren van een bestelling eerst een leverancier gekozen moet worden. Via de tweede keuzelijst kan je het artikel kiezen. Er mogen dan alleen artikelen van de geselecteerde leverancier getoond worden.

De leveranciers staan in de tabel Leverancier. In de tabel Artikel ligt per artikel vast welke leverancier het levert. Verder is er in het voorbeeld een tabel Bestelling waar het feitelijk om draait. Daarin leggen we bestellingen voor een artikel vast. Bij het via een formulier invoeren van bestellingen willen we gebruik maken van een getrapte invoer: eerste een leverancier kiezen, dan kiezen uit de artikelen die de leverancier voert.
Merk op dat in tabel Bestelling alleen het artikel, en niet de leverancier, wordt opgeslagen. In de artikeltabel ligt al vast welke leverancier het artikel levert. Dat hoeven we in de bestelling niet nogmaals te doen. Op het formulier is de leverancier dan ook een niet-afhankelijk veld.

Om de artikelen die je in de tweede keuzelijst te zien krijgt in te perken, maken we een gebeurtenis na bijwerken (after update) op de eerste keuzelijst (leverancier). Zodra de leverancier gekozen is zorgen we ervoor dat de keuzelijst voor het artikel correct ingesteld wordt. De gebeurtenis ziet er zo uit:

Private Sub Leverancier_AfterUpdate()
Me.Artikel.RowSource = "SELECT ArtikelID, Artikel, LeverancierID FROM Artikel" & _
  " WHERE LeverancierID=" & Me.Leverancier & " ORDER BY Artikel"

Me.Artikel.SetFocus

Select Case Me.Artikel.ListCount
  Case 0
     Me.Artikel = Null
  Case 1
     Me.Artikel = Me.Artikel.ItemData(0)
  Case Else
     Me.Artikel = Null
     Me.Artikel.Dropdown
End Select

End Sub

Nadat de leverancier is gekozen, vullen we de rijbron (rowsource) van het artikelveld met waardes uit de artikeltabel waarvoor geldt dat de leverancier gelijk is aan de zojuist gekozen leverancier. Merk op dat we niet alleen de identificatie en de naam van het artikel ophalen, maar ook de identificatie van de leverancier. Verderop blijkt waarom we dat doen.
De keuzelijst is nu dus gevuld. Aan de eigenschap Listcount kunnen we zien hoeveel items (artikelen) er in de keuzelijst staan (nul, één of meer). Is dat er maar één (de leverancier levert kennelijk maar 1 artikel), dan kunnen we het artikelveld daarmee vullen. Zijn er meer artikelen, dan maken we het artikelveld leeg en klappen de keuzelijst uit zodat de gebruiker direct een keuze kan maken. Voert de leverancies geen artikelen, dan maken we het artikelveld alleen maar leeg (want er kan nog een artikel in staan dat hoorde bij een eerder gekozen (andere) leverancier).

Er is nog een bijzonderheid waar je rekening mee moet houden. Zoals ik al zei slaan we in de bestellingentabel niet de leverancier op. Toch zou je voor bestaande records wel de bij artikel behorende leverancier willen zien. Dat kunnen we oplossen door op het formulier een gebeurtenis bij aanwijzen (current) te maken, die ervoor zorgt dat het niet-afhankelijke veld leverancier gevuld wordt met de leverancier die bij het artikel van het actuele record hoort. Deze gebeurtenis ziet er zo uit:

Private Sub Form_Current()
Me.Leverancier = Me.Artikel.Column(2)
Me.Artikel.RowSource = "SELECT ArtikelID, Artikel, LeverancierID FROM Artikel" & _
  " WHERE LeverancierID=" & Me.Leverancier & " ORDER BY Artikel"
Me.Artikel.Requery
End Sub

Omdat we ervoor gezorgd hebben dat in de keuzelijst van het artikel de identificatie van de leverancier (onzichtbaar) aanwezig is in de derde kolom van die lijst, kunnen we het (niet-afhankelijke) veld Leveranciers vullen met de inhoud van die kolom (let op dat Access bij nul begint tellen en we dus verwijzen naar Column(2)). Daarna moeten we er, net als bij de vorige gebeurtenis, voor zorgen dat de keuzelijst voor het artikel alleen waardes bevat die bij de gevonden leverancier horen. Als de gebruiker zonder de leverancier te veranderen een andere artikel wil kiezen mag hij alleen artikelen van die leverancier kiezen.

Klik hier om de voorbeelddatabase te downloaden.