Klant zoeken in formulier, bij niet gevonden (NotInList) nieuwe klant toevoegen tabel

Status
Niet open voor verdere reacties.

Lubbie87

Gebruiker
Lid geworden
16 feb 2009
Berichten
23
Hallo,

ik zit met het volgende. Ik heb een simpele database met een tabel "Klanten" en een formulier gebaseerd op deze tabel genaamd "frmZoekKlanten". Op dit formulier heb ik drie "Keuzelijsten met invoervak", waarbij gezocht kan worden op adres ("cboStraatNummer"), op Achternaam ("cboAchternaam") en op telefoonnummer ("cboTelefoonnummer"). Deze keuzelijsten werken prima en doen wat ik wil. Echter, ik wil dat als bijvoorbeeld het adres (cboStraatNummer) niet gevonden wordt, er gevraagd wordt om een nieuwe klant aan te maken. Deze nieuwe klant moet dan in de tabel "Klanten" worden toegevoegd, waar dus het huidige formulier ook op is gebaseerd. Kan dat?

Tot dusver heb ik de NotInList code als volgt:
Code:
Private Sub cboStraatNummer_NotInList(NewData As String, Response As Integer)
Dim Result
Dim Msg As String

    If NewData = "" Then Exit Sub

    Msg = "'" & NewData & "' staat niet in de lijst." & vbCrLf & vbCrLf
    Msg = Msg & "Wil je " & NewData & " toevoegen?"
    If MsgBox(Msg, vbQuestion + vbYesNo) = vbYes Then
        DoCmd.OpenForm "[COLOR="#FF0000"][B]frmZoekKlanten[/B][/COLOR]", , , , acAdd, acDialog, NewData
    End If
    Me.cboStraatNummer.Requery

    ' Zoek het nieuwe klantnr op in de tabel Klanten.
    Result = DLookup("[klantnr]", "Klanten", "[adres]='" & NewData & "'")
    If IsNull(Result) Then
        ' Als de functie 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.cboStraatNummer = Result
    End If

End Sub

Er komt wel een scherm tevoorschijn met "xxxx niet gevonden, wilt u xxxx toevoegen?" maar als ik dan op "Ja" klik krijg ik de foutmelding "Fout 2118, de actie QueryOpnieuwUitvoeren kan pas worden uitgevoerd nadat u het huidige veld hebt opgeslagen".

Foutopsporing leidt tot: Me.cboStraatNummer.Requery

Klopt de roodgemaakte tekst? Dit is immers het huidige formulier, ik weet niet of dat juist is.
Moet ik dan een nieuw formulier maken? Dat zou dan betekenen dat ik een extra tabel moet maken toch?
 
Laatst bewerkt:
Je gebruikt de eigenschap <NotInList> eigenlijk verkeerd. Keuzelijsten zou je moeten gebruiken op tabellen waarin je de feitelijke bedrijfsgegevens invult. Voorbeeldje: je hebt een vereniging, en je hebt daarin een ledenadministratie. Dan heb je een brontabel met Leden, en je hebt een tabel met de administratiegegevens, zoals Begindatum_Lidmaatschap, LidNummer, LidmaatschapType etc. Je tabel Administratie is in deze db de tabel waarin je de transacties vastlegt, zoals nieuwe leden, ledenmutaties (van aspirant naar normaal lid), betalingen etc. Je formulier Administratie bevat dus alle noodzakelijke gegevens en zal het hoofdformulier zijn.
Op dat formulier staan de keuzelijsten waarin je een Lid opzoekt. Dat opzoeken gebeurt dan in de tabel Leden. En dan komt het dus voor dat je een nieuw lid tegenkomt, omdat hij/zij niet gevonden wordt in de keuzelijst. En op dat moment gebruik je de eigenschap <Bij niet in lijst> om het formulier Leden te openen, en het nieuwe lid toe te voegen.

In jouw situatie heb je wellicht een formulier Bestellingen, waarin je met een keuzelijst cboKlanten een klant opzoekt. Dat doe je dan in de tabel Klanten. En dan kom je die situatie dus ook tegen: je vult een klantnaam in, en die wordt niet gevonden. Op dat moment gebruik je de eigenschap <Bij niet in lijst> om het formulier frmKlanten te openen, en de nieuwe klant toe te voegen.

Wat jij wilt, is eigenlijk simpel: een klant zoeken in het formulier Klanten. En die vind je, of die vind je niet. In het laatste geval wil je op hetzelfde formulier een nieuw record toevoegen. Dat kan dan zo:
Code:
Option Compare Database
Option Explicit
Dim sNieuweNaam As String

Je begint met het declareren van een variabele die in het formulier geldig is, en niet binnen een procedure (sNieuweNaam).
Code:
Private Sub cboZoekLijst_Change()
    sNieuweNaam = Me.cboZoekLijst.Text
End Sub
Die vul je tijdens het typen in de keuzelijst.
Code:
Private Sub cboZoekLijst_NotInList(NewData As String, Response As Integer)
    Me.cboZoekLijst.Undo
    Me.Dirty = False
    DoCmd.GoToRecord , , acNewRec
    Me.Naam = sNieuweNaam
End Sub
Als de naam niet gevonden wordt, maak je de keuzelijst leeg en maak je het formulier 'los' (keuzelijst leeg, en formulier vrij geven) en voeg je een nieuw record toe met de nieuwe naam ingevuld.
Code:
Private Sub cboZoekLijst_Click()
Dim rs As Object
    Set rs = Me.RecordsetClone
    rs.FindFirst "[LidNr] = " & Me.cboZoekLijst
    If Not rs.EOF Then Me.Bookmark = rs.Bookmark
End Sub
De Click procedure van de keuzelijst gebruik je om het aangeklikte record op te zoeken. Die staat dus wèl in de keuzelijst/tabel, anders kan je er niet op klikken.
 
Ik heb het op jouw manier gedaan en hij voegt het nieuwe record inderdaad ook toe. Toch ben ik bang dat dit voor verwarring gaat zorgen. Kan ik niet beter met knoppen werken om nieuwe records toe te voegen? Dus bijvoorbeeld een knop "Nieuwe klant" waarna dan het formulier ingevuld wordt, een knop "Opslaan" en een knop "Annuleren".
 
Ik zou de routine dan uitbreiden met een msgbox die vraagt of de nieuwe waarde moet worden toegevoegd of niet. Wat je eigenlijk standaard doet met NotInList.
 
Ik ben al een heel eind. Ik heb nu een zoekformulier genaamd "frmKlantenZoek", gebaseerd op de tabel "Klanten" waar medewerkers kunnen zoeken naar een klant mbv keuzelijsten. Als zij de klant niet vinden kunnen zij op een knop "Nieuwe klant" klikken die dan een formulier opent genaamd "Nieuwe klant toevoegen" waarbij ze een nieuwe klant kunnen invoeren. Op zichzelf functioneert dit formulier, op een paar details na, maar op deze manier werkt het niet omdat dit formulier op dezelfde tabel "Klanten" is gebaseerd. Ik krijg dan ook de melding: "Dit Recordset-object kan niet worden bijgewerkt". Is er een manier om, bijvoorbeeld, het zoekformulier te sluiten en het invoerformulier te openen als op de knop "Nieuwe klant" wordt geklikt? Iets van:
Code:
Private Sub Nieuwe_klant_Click()
On Error GoTo Err_Nieuwe_klant_Click

    Dim stDocName As String
    Dim stLinkCriteria As String

    [COLOR="#FF0000"][B]DoCmd.CloseForm "frmKlantenZoek"[/B][/COLOR]
    stDocName = "Nieuwe klant toevoegen"
    DoCmd.OpenForm stDocName, , , stLinkCriteria

Exit_Nieuwe_klant_Click:
    Exit Sub

Err_Nieuwe_klant_Click:
    MsgBox Err.Description
    Resume Exit_Nieuwe_klant_Click
    
End Sub

Nog een ding, bij het formulier "Nieuwe klant toevoegen" wordt het debiteurnummer nu automatisch weergegeven met een besturingselement bron " =Max([debnr])+1 ". Dit werkt ook als je aan het invullen bent. Maar als ik de gegevens invul en het op sla wordt de nieuwe klant niet met dit nummer aangemaakt maar verschijnt het simpelweg als nieuwe record in de eerste rij, een idee waar dit aan kan liggen?
 
Laatst bewerkt:
Je verwart zoekformulieren met dataformulieren. Een zoekformulier is niet gekoppeld aan een tabel, en een dataformulier wèl. Een Klantenformulier is gekoppeld aan de tabel Klanten, en kan, voor het gemak, best een zoekfunctie bevatten om klanten op te zoeken. Maar om een nieuwe klant in te voeren hoef je dan geen apart formulier in te voeren. Een niet-afhankelijk zoekformulier moet wèl een apart formulier openen dat is gekoppeld aan een tabel, anders kan je geen gegevens invoeren. Ik zou zeggen: kies één van de twee varianten (ik heb de eerste beschreven hierboven), maar probeer ze niet te combineren.
 
Oké, ik snap het. Nu heb ik een ander probleem: bij het formulier "Nieuwe klant toevoegen" wordt het debiteurnummer nu automatisch weergegeven met een besturingselement bron " =Max([debnr])+1 ". Dit werkt ook als je aan het invullen bent (je ziet het nummer verschijnen). Maar als ik de gegevens invul en het op sla wordt de nieuwe klant niet met dit nummer aangemaakt maar verschijnt het simpelweg als nieuwe record in de eerste rij, een idee waar dit aan kan liggen? Ik kom er niet uit.
 
besturingselement bron " =Max([debnr])+1 "
Dat gaat zeker niet werken; je kunt een formulierveld alleen maar opslaan als je het (tekst)veld koppelt aan een tabelveld. En dat doe je niet. Deze manier van berekenen zou ik zo ook nooit doen; ik zou een functie gebruiken die een volgnummer genereert, en die functie als Standaardwaarde op het tekstveld zetten. Het tekstveld kun je dan koppelen aan het tabelveld (middels Besturingselementbron) en je krijgt alleen maar een nieuw nummer als je een nieuw record maakt, en dat opslaat. Dit in tegenstelling tot Autonummers, die nummers niet hergebruiken als je een record niet bewaart.
 
Pff, dit gaat echt mijn pet te boven...Hoe ziet die functie er ongeveer uit? Ik heb zoiets gevonden en aangepast uit een ander topic:

Code:
Private Sub debnr_Click()
    Me.Volgnummer = debnr
End Sub

Code:
Function debnr() As String
Dim strSQL As String, iNum As Integer

'Hoogste debnr selecteren'
strSQL = "SELECT DISTINCT TOP 1 debnr FROM Kopie van Klanten " _
    & "ORDER BY debnr DESC;"
With CurrentDb.OpenRecordset(strSQL)
End With
debnr = strSQL + 1
End Function

Eigenlijk doe ik maar wat, waar kan ik meer informatie vinden over zulk soort functies? Heb al gegoogled maar kan het niet echt vinden.
 
Soms sta je bovenop de plek die je zoekt :) Kijk eens in de handleidingen sectie van HelpMij, ik heb in de Access cursus e.e.a. behandeld. Deze functie zou overigens wel eens niet kunnen werken, omdat de tabelnaam niet deugt. En je de tabel niet uitleest. Hij zou er zo uit moeten zien:
Code:
Function debnr() As Integer
Dim strSQL As String

strSQL = "SELECT TOP 1 debnr FROM [Kopie van Klanten] ORDER BY debnr DESC;"
With CurrentDb.OpenRecordset(strSQL)
     If .RecordCount > 0 Then
          debnr=!debnr + 1
     Else
          debnr=1
     End If
End With
End Function
En waarom achter een knop? Je kunt hem beter, zoals ik al voorstelde, aanroepen in het veld Standaardwaarde van het veld Volgnummer.
Daar zet je dus: =debnr() neer als formule.
 
Bedankt, jij bent wel een held. Ik heb voor nu een soort workaround gevonden maar ga morgen of volgende week hiermee aan de slag.
Bedankt voor alle moeite in ieder geval.
 
Status
Niet open voor verdere reacties.

Nieuwste berichten

Terug
Bovenaan Onderaan