Hulp gevraagd bij maken requery

Status
Niet open voor verdere reacties.

remcop1989

Gebruiker
Lid geworden
29 mrt 2012
Berichten
492
Ik heb een form "klanten"
Ik heb een form "Offerte formulier"
Op "Offerte formulier" heb ik een knop die "klanten" opent. Hierin kunnen nieuwe klanten worden toegevoegd
Op "Offerte formulier" heb ik de keuzelijst met invoervak "cmbKlantID"

Ik wil nu dat zodra ik een nieuwe klant heb toegevoegd in "klanten" (door drukken op de knop die de tabel "klanten" opent), de keuzelijst met invoervak "cmbKlantID" een requery doet. Ik krijg dit zelf niet voor elkaar. Ik begin pas met Access programmeren.
 
Ik zou het simpeler (en logischer) aanpakken: middels de gebeurtenis <Bij niet in lijst> van je keuzelijst. Daarin zoek je vermoedelijk de klant op d.m.v. het intypen van de klantnaam (of een deel ervan). Wordt deze gevonden, dan zie je de klant(en) in de keuzelijst en maak je een keuze. Staat de klant er niet in, dan wordt de gebeurtenis <Bij niet in lijst> (NotInList) getriggerd, waarmee je de nieuwe klant kunt invoeren. Dat kan d.m.v. een toevoegquery, als het om weinig verplichte gegevens gaat zoals een niet-bestaande categorie, of je kunt een formulier openen. En in de procedure wordt dan automatisch je keuzelijst bijgewerkt.
 
Dat klinkt inderdaad logischer. Ik heb dit geprobeerd middels "opbouwfunctie voor expressies" van <Bij niet in lijst> en gezegd dat hij het formulier "klanten" moet openen (waar een nieuwe klant toegevoegd kan worden). Dit doet echter niets.....?
 
Ik weet niet wat je hebt gemaakt, maar hier is een opzetje dat ik zelf gebruik. Het is wat uitgebreider dan normaal, omdat er twee velden naar het subformulier gaan, die dan worden ingevuld op het formulier. Dus voor één veld kan het zonder de SPLIT functie.
Op je keuzelijst staat deze code:
Code:
Private Sub cboArtikel_NotInList(NewData As String, Response As Integer)
Dim Result
Dim Msg As String, CR As String
    CR = Chr$(13)
    If NewData = "" Then Exit Sub

    Msg = "'" & NewData & "' staat niet in de lijst." & CR & CR
    Msg = Msg & "Wil je " & NewData & " toevoegen?"
    If MsgBox(Msg, vbQuestion + vbYesNo) = vbYes Then
        iBedrijf = Me.Parent.cboBedrijf.Column(0)
        DoCmd.OpenForm "fArtikelen", , , , acAdd, acDialog,  NewData & "|" & iBedrijf
    End If

    ' Zoek het nieuwe artikelID op in de tabel Artikelen.
    Result = DLookup("[ArtikelID]", "tArtikelen", "[Artikel]='" & NewData & "'")
    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
End Sub
En het formulier dat je opent, moet de meegekregen waarde gebruiken voor het nieuwe artikel (in mijn geval).
Code:
Private Sub Form_Open(Cancel As Integer)
    If Not IsNull(Me.OpenArgs) Then
        Dim sArgs() As String
        sArgs = Split(Me.OpenArgs, "|")
        Me.txtArtikel.Value = sArgs(0)
        Me.cboBedrijfID.Value = sArgs(1)
    End If
End Sub
 
Als beginner op het gebied van VBA is dat nogal overweldigend....

Ik probeer te snappen wat hij doet....: hij controleert of de ingevoerde waarde in de lijst staat. Is dit niet het geval dan opent hij een venster waarbij de waarde die niet in de lijst wordt gevonden al wordt ingevuld. Daar kunnen dan ook nog aanvullende gegevens bij(?) en dit alles wordt opgeslagen in de tabel 'iBedrijf'. Vervolgens wordt het invoerscherm gesloten (handmatig?) en het nieuw toegevoegde artikel automatisch ingevuld.

Klopt dit of interpreteer ik dingen verkeerd? (Wat ik me heel erg goed kan voorstellen ;-)).

Het is in ieder geval belangrijk dat er meerdere gegevens dan alleen 'bedrijfsnaam' ingevuld kunnen worden.
 
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!
 
Aha. Dat klinkt al logisch :-) dank je!
Het tekstvak met het artikel op het 2e formulier kan dus vergrendeld worden zodat dit niet gewijzigd kan.

Je schrijft dat een formulier automatisch gegevens in de gekoppelde tabel opslaat. Handig. Maar wat nu als een formulier deels ingevuld word maar er dan toch word besloten dat dat niet nodig is en dat dus verwijderd kan....hoe is dat te regelen?
 
Je snapt het nog niet helemaal, al is het verhaal natuurlijk wel logisch :) Ik heb het althans niet gehad over het vergrendelen van het tekstvak op het tweede formulier. Maar je zou dat kunnen doen, mocht je die instelling nodig hebben. Wat ik bedoelde was dat het eerste formulier (en dat geldt ook voor de rest van de db) niet gebruikt kan worden zolang het tweede formulier, dat in de Dialog modus is geopend, is afgesloten. Daarmee voorkom je dat de procedure onbedoeld verder loopt. Zou je het tweede formulier niet met acDialog openen, dan gaat de code gewoon verder na het openen van het tweede formulier, en dan heb je natuurlijk nog niks ingevuld. Met als resultaat dat de operatie mislukt.

Je laatste vraag snap ik niet, vrees ik...
 
Aha, dat is duidelijk :-)

De vraag die je niet snapt:
Ik heb nu dus dat (eerste!) formulier (ik bedoel dus NIET de dialoog). Deze is gekoppeld aan de tabel. Alles wat ik op dat formulier invul word ook vrijwel meteen in de tabel opgeslagen. Als ik nu dus aan een offerte begin en hem halverwege het invullen wil/moet annuleren heb ik wel de al ingevulde gegevens in de tabel staan. Dit zorgt natuurlijk voor (uiterst ongewenste) vervuiling. Daarom dat ik hier/ergens anders vroeg naar een "knop" waarmee de gebruiker alles op het formulier pas naar de tabel overzet zodra hij dit goedkeurt.

Snappie?
 
Je hebt pas ongewenste gegevens in de tabel staan als het record op enig moment is opgeslagen. Met Undo kun je een record weer ongedaan maken, dus je kunt een check inbouwen die Undo uitvoert als je vindt dat de data niet mag worden opgeslagen.
 
Kun je me iets meer info daarover geven zodat ik ongeveer weer hoe dit te doen of waar ik hier meer over kan leren?
 
Hij slaat dus echt direct bij invoer al gegevens op, zodra ik het formulier "nieuwe offerte" open...dit wil ik dus laten uitstellen totdat de gebruiker dit goedkeurd. Hoe kan ik dat doen?
 
Blijkbaar doe je van alles automatisch in je formulier; zet de optie <Recordkiezers> op Ja, en kijk naar de vorm van het symbool op de knop. Is dat een driehoekje dan is het record (niet gewijzigd of) opgeslagen; is het een potloodje dan is het record in bewerking, en kun je het record annuleren.
 
En annuleren is dan hoe? Als ik namelijk tijdens het "potloodje" op het kruisje rechtsboven aan het scherm klik wordt hij alsnog opgeslagen....
 
Dan sluit je het formulier met behoud van gegevens. Zoals ik al zei: je zult een Undo commando moeten inbouwen. Op basis waarvan kan ik zo niet zeggen, want wanneer beschouw je een record als incompleet?
Je kunt alles natuurlijk afvangen door de ingebouwde knoppen uit te schakelen en zelf knoppen te maken voor Opslaan en Annuleren. Dan weet je precies waar je de Undo aan kunt hangen...
 
Heb je al gezien welk commando daar achter staat? :)
 
Een ingesloten macro zo te zien....maar je bedoeld vast iets sarcastisch? :P

Heb nu alleen nog dat probleem met formulier "nieuwe offerte" dat hij wel het juiste offertenummer aanmaakt (+record...lang leve access) maar zodra ik een klant selecteer in de keuzelijst met invoervak op het formulier, selecteert hij het record dat volgens hem bij die klant hoort terwijl ik juist wil dat hij de geselecteerde klant opslaat bij het nieuwe (en juiste) offertenummer....
 
Laatst bewerkt:
Nog niet eens; als het een ingesloten macro is, zou ik die gelijk vervangen door een gebeurtenis. Dat is een stuk makkelijker te onderhouden.

Code:
Private Sub cmdAnnuleren_Click()
     Me.Undo
End Sub
 
Ik krijg een naar gevoel bij je formulier; geen idee wat je aan het doen bent, maar het lijkt me een vervelend formuliertje :)
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan