Ik zal proberen uit te leggen wat er gebeurt, en de uitleg baseren op één enkel veld, dat is misschien wat makkelijker.
De code wordt getriggerd doordat de waarde niet voorkomt in de rijbron van keuzelijst. In mijn geval: de naam van een artikel. Die waarde staat in de variabele NewData.
Code:
Private Sub cboArtikel_NotInList(NewData As String, Response As Integer)
Dim Result
Dat is dus een tekstwaarde (in het achterhoofd houden, want die kennis heb je straks weer nodig). Vervolgens wordt op een wat ingewikkelde manier een dialoogvenster op het scherm gezet, die vraagt of je de nieuwe waarde wilt toevoegen aan de keuzelijst. Voor hetzelfde geld heb je een typefout gemaakt, en staat de waarde er gewoon tussen, niet waar? Daarvoor is deze code voldoende:
Code:
If MsgBox("'" & NewData & "' staat niet in de lijst." VbLf & & "Wil je " & NewData & " toevoegen?", vbQuestion + vbYesNo) = vbYes Then
DoCmd.OpenForm "fArtikelen", , , , acAdd, acDialog, NewData
End If
Hiermee opent het formulier "fArtikelen" in de Dialoog modus. Da's een belangrijke, want je moet eerst een nieuw record toevoegen (en opslaan etc) voordat je verder mag gaan. Het eerste formulier gaat dus tijdelijk even 'op slot'. De waarde NewData wordt meegegeven aan de documentvariabele OpenArgs. Deze variabele wordt op het tweede formulier weer uitgelezen. We gaan dus nu verder op het formulier fArtikelen, waar we de naam van het artikel moeten invullen in het juiste tekstvak. En die naam is dus meegegeven middels de parameter OpenArgs.
Code:
Private Sub Form_Open(Cancel As Integer)
If Not Me.OpenArgs & "" = "" Then
Me.txtArtikel.Value = Me.OpenArgs
End If
End Sub
Het formulier wordt geopend, en met een IF ... END IF controleren we of de OpenArgs leeg is of niet. Je moet het formulier ook zelfstandig kunnen openen, en dan is de variabele OpenArgs leeg. Dus daarom een check.
Is de variabele niet leeg, dan wordt het tekstvak txtArtikel gevuld met de tekst.
Je ziet nu het tweede formulier fArtikelen, en de naam van het artikel is ingevuld. De prijs nog niet (want die had je uiteraard niet in de keuzelijst) en dat doe je dus nu, en wat je nog meer wilt invullen en wat misschien wel verplicht is. Al die tijd is het eerste formulier uitgeschakeld. Ben je klaar met invullen, dan sluit je het formulier. Het record wordt automatisch bewaard, want dat is nu eenmaal een eigenschap van een formulier. Of je een knop gebruikt, een sneltoets of het standaar standaardkruisje maakt dus allemaal niet uit.
Je komt nu weer terug in het eerste formulier, waar de rest van de code wordt uitgevoerd.
Code:
' Zoek het nieuwe artikelID op in de tabel Artikelen.
Result = DLookup("[ArtikelID]", "tArtikelen", "[Artikel]='" & NewData & "'")
Eerst zoek je met DLookup het nieuwe ArtikelID op; dit is immers wat je uiteindelijk op slaat in de tabel. Dat zoeken gebeurt op een tekstveld, en op basis van de variabele NewData. Zou ik in het popup formulier de naam van het artikel hebben veranderd, dan gaat de lookup dus de mist in, want dan bestaat het artikel niet onder deze naam. Je mag de naam dus niet veranderen!
If IsNull(Result) Then
' Als het artikel niet is gemaakt, Response argument op Error message zetten en herstellen.
Response = acDataErrContinue
MsgBox "Nog een keer proberen...", vbOKOnly
Else
' Als het artikel is gemaakt, het Response argument Added zetten.
Response = acDataErrAdded
Me.cboArtikel = Result
End If
In de check wordt gecontroleerd of de LOOKUP gelukt is of niet; zoals ik al zei: als je in het tweede formulier de artikelnaam ook nog verandert, ga je hem niet vinden, en is er dus geen artikel om te laten zien. Lukt de opzoekactie wel, dan heb je in de variabele Result een waarde staan. Die wordt toegewezen aan de keuzelijst, en de status van de procedure wordt op acDataErrAdded gezet: actie gelukt, patient niet overleden en de keuzelijst bijgewerkt!