Voorkomen dubbele invoer in Access

Status
Niet open voor verdere reacties.

EdHa

Verenigingslid
Lid geworden
6 mei 2012
Berichten
57
In een eerder draadje vond ik onderstaande code, die ik in mijn database heb proberen toe te passen. Het grappige is dat de code doet wat hij moet doen als je een record in probeert te vullen dat al bestaat, maar dat er een foutmelding komt op het moment dat je een nog niet bestaand record wilt toevoegen, terwijl dat toch in de meeste gevallen dient te gebeuren. Dan volgt de melding 3001, ongeldig argument. Geen idee hoe dat komt, maar iets gaat er niet goed. Wie heeft een idee? Ik gebruik Access 2007-2010. Bijkomend is ook nog dat ik in tegenstelling tot de vraagsteller uit het eerdere draadje niet in de hele database wil zoeken naar 'dubbele' vermeldingen, maar alleen in het veld dat hier met tVeldNaam staat aangegeven. In mijn database heb ik mijn eigen veldnaam gebruikt maar dat doet aan de vraag niet af, ik heb nu maar even dat voorbeeld overgenomen. Daarvoor moet waarschijnlijk .Fields worden aangepast, maar hoe?

Code:
Private Sub tVeldNaam_AfterUpdate()
    If fZoekOp(Me!tVeldNaam) Then
        MsgBox "die waarde komt al voor"
    End If
End Sub

Function fZoekOp(s As String) As Boolean
    Dim fld As Object
    With CurrentDb.OpenRecordset("MijnTabel")
        While Not .EOF And Not fZoekOp
            For Each fld In .Fields
                If fld.Value = s Then
                    fZoekOp = True
                    Exit For
                End If
            Next
            .MoveNext
        Wend
    End With
End Function
 
En waarom gebruik je niet gewoon de ingebakken tabelvalidatie? Veel makkelijker, lijkt mij.
 
@Octafish

Allereerst omdat het om een string tekens gaat die steeds wisselend is, 6 getallen, liggend steeepje, jaaraanduiding. En ten tweede omdat het in een tweetal formulieren moet worden gecontroleerd bij invoer. Ik meen begrepen te hebben uit wat ik las dat dat niet op tabelniveau kan. Als dat anders is, hoe formuleer ik dan de regel?
 
Ik ben ook maar een prutser met Access, dus ik heb geen idee hoe je met twee formulieren tegelijkertijd één record kan maken, dus wellicht ben ik niet de juiste persoon om antwoord te geven. Mij lijkt dat namelijk volslagen onmogelijk, en in ieder geval onwenselijk.
Daarnaast gaf je in je vraag aan dat je één veld wilt controleren en daarbij is het volslagen irrelevant hoe de inhoud van dat veld er uit ziet; je wilt voorkomen dat een waarde dubbel ingevoerd kan worden, en dat doe je echt wel op tabelniveau. Simpel de index van dat veld aanpassen, en eventueel een eigen foutmelding erbij om de gebruiker wat beter te informeren dan met de standaard melding als je een waarde dubbel invoert.
Maar ja, zo zou ik het dus doen.
 
Oei, wat een cynische reactie, Octafish, dat ben ik niet van je gewend, maar misschien miste ik de olijke ondertoon. Of mijn reactie op de jouwe heeft onbedoeld iets geraakt. Ik denk dat ik niet duidelijk ben geweest in mijn vraag. Uiteraard heb ik in de tabel het 'Ja, geen duplicaten' aangezet. Maar als je dat zo laat is het effect dat de gebruiker zijn invoer genegeerd ziet en dus moeite voor niets doet. Daarom wilde ik met script een waarschuwing genereren bij het invullen van het invoerformulier (één van de twee en natuurlijk niet allebei TEGELIJK zoals jij aangeeft) zodat de gebruiker kan stoppen of een verkeerde invoer kan herstellen. Als er iemand voor de kwalificatie prutser in aanmerking komt ben ik dat. Dat weet jij ook wel en realiseer ik mij maar al te goed. Daarom schrok ik van je reactie, alsof ik
je niet serieus nam. Verre van dat, maar ik begreep niet waarom je mij niet begreep. Wat ik wil is die waarschuwing bij dubbele invoer, maar ik krijg nu tevens een foutmelding bij juiste invoer. En dat moet ik toch in het formulier afvangen en niet in de tabel? Hoor graag. En excuus als ik iets in mijn reactie had dat verkeerd schoot bij je.
 
Te cynisch? Excuus, dat was inderdaad niet de bedoeling :). Kwam door dit zinnetje:
... omdat het in een tweetal formulieren moet worden gecontroleerd bij invoer.
Je zal dat ongetwijfeld anders bedoelen dan dat je het schrijft. Overigens snap ik dus niet waarom je bij het invoeren van één record twee formulieren nodig hebt; ik kan geen enkele situatie verzinnen waarbij dat nodig zou zijn. Ik open wel eens een tweede formulier tijdens het invoeren van een record, maar dat is dan om bijvoorbeeld een nieuwe plaatsnaam weg te schrijven voor een keuzelijst die de nieuwe plaats niet bevat. Dan moet je, tijdens het invoeren, even een plaats invoeren via het formulier fPlaatsnaam. Maar daarna ga je weer gewoon verder in het eerste formulier, en is er nog steeds geen sprake van dat één (nieuw) record in twee formulieren open staat.

Ik heb wel eens vragen gezien van mensen die dat doen omdat ze teveel velden hebben voor het formulier, en er dan maar een tweede formulier tegenaan gooien. Maar dat hoeft dus ook al niet, want dan werk je beter met tabbladen. Kortom: leg eens uit wat je nu aan het doen bent met die twee formulieren, en waarom je überhaupt in de problemen komt met die dubbele waarden, want ook dát probleem heb ik dus eigenlijk nooit. Op het moment dat ik dat tegen zou komen, werk ik met keuzelijsten zodat er geen verkeerde keuze kan worden gemaakt (=dubbel ingevoerd) of met automatisch gegenereerde waarden. Want als een waarde uniek moet zijn, is er vaak een systeem te bedenken dat die waarden genereert.
 
Die twee formulieren zijn in wezen inderdaad niet nodig, maar dat is gekomen omdat er twee verschillende groepen gebruikers zijn die nieuwe records moeten kunnen aanmaken, waarvan de ene groep een aantal gegevens vastlegt waarmee de ander zo nodig verder kan, terwijl de andere groep ook zelfstandig records moet kunnen aanmaken waarbij ze alle gegevens zelf invullen. Op verzoek van de gebruikers hebt ik het ene formulier dat ik had vervangen door twee formulieren, zodat of de ene groep kan invoeren, of de andere. En om nu te voorkomen dat de ene groep (of iemand uit de groep) een record gaat aanmaken dat al bestaat is die controle nodig. De primaire sleutel is gewoon de ID, en dit veld dat geen dubbelen mag bevatten is het veld waarin het nummer van de zaak staat. Dat nummer is een gegeven dat uit een ander systeem komt en dus niet binnen access aangemaakt wordt maar alleen overgenomen. Het bestaat uit 6 cijfers, een steeepje en de twee cijfers van het jaar. Dat is uniek voor die zaak en moet dus ook zo blijven. Alles wat daarvan in deze database wordt bewaard mag er maar één keer in voorkomen. Begrijp je mijn probleem? De zaak wordt aangemaakt door groep 1 met formulier A of door groep 2 met formulier B, en nooit met allebei. Maar elk van beide formulieren bestaan en bieden de mogelijkheid van invoer. Dat ze verschillend zijns om het voor elk van beide groepen overzichtelijk te houden wat ze moeten vastleggen, want dat verschilt, op het unieke zaaksnummer na.
 
Ik zou, puur op basis van onderhoud, toch voor één formulier gaan en dat zodanig inrichten dat de ene groep de voor hun relevante informatie ziet, en de andere groep ook. Zo maak ik zelf mijn databases, en dat werkt prima. Als alle gebruikers een eigen FE hebben naar de BE, lost dat overigens niks op, want dan kan nog steeds elke gebruiker een nieuw record in dezelfde database proberen aan te maken. Dus daar ligt het probleem niet. Je moet dus, voordat je überhaupt een record aanmaakt, al gecontroleerd hebben of het zaaknummer al bestaat in de db, en niet tijdens het invoeren. Dan is je probleem volgens mij opgelost.
 
Eerst controleren is zeker een goed idee, maar heb ik daar niet een zelfde script voor nodig? Of heb je daar een (ander) voorbeeld van?
 
Ik zou de interne knop op het formulier waarmee je een record kan toevoegen sowieso uitschakelen (formuliereigenschappen <Toevoegingen toestaan>=Nee) en een knop op het formulier zetten waarmee je een record kan toevoegen. Die knop zet AllowAdditions uiteraard eerst op True, anders kun je nog steeds niet toevoegen. Met de DLookup functie zoek je dan het nieuwe zaaknummer op in je tabel; dat zaaknummer zal vermoedelijk ingetypt worden door de gebruiker, want dat komt dus uit dat DMS systeem.
Je begint, kortom, met een Inputbox waarin je het zaaknummer vraagt. Ik zou de opgevraagde waarde gelijk in een variabele zetten, zodat je, als hij niet gevonden wordt, gebruikt kan worden in de toevoeging. Krijg je zoiets:

Code:
Private Sub cmdNieuwRecord_Click()
Dim sZaakNr As String, sInput As String
    With Me.cmdNieuwRecord
        If .Caption = "Nieuw record" Then
            sInput = InputBox("Typ het zaaknummer.", "Zoek zaaknummer", "123456-" & Year(Date))
            sZaakNr = Nz(DLookup("[ZaakNr]", "tDossiers", "[Zaaknr] = """ & sInput & """"), "Geen Zaaknr")
            If sZaakNr = "Geen Zaaknr" Then
                Me.AllowAdditions = True
                DoCmd.GoToRecord , , acNewRec
                Me.Zaaknr.Value = sInput
                .Caption = "Record opslaan"
                .FontBold = True
                'etc
            Else
                MsgBox "Zaaknummer bestaat al", vbCritical + vbOKOnly
                Exit Sub
            End If
        ElseIf .Caption = "Record opslaan" Then
            .Caption = "Nieuw record"
            .FontBold = False
            If Me.Dirty Then Me.Dirty = False
            On Error Resume Next
            DoCmd.RunCommand acCmdSaveRecord
            Me.AllowAdditions = False
        End If
    End With
End Sub
Niet getest uiteraard; d.w.z. de verschillende onderdelen wel op een eigen db, maar niet in deze hoedanigheid.
 
Laatst bewerkt:
Dank je. Ik ga het uitproberen. En laat het je weten of het gelukt is of niet. Kan even duren ivm andere bezigheden, maar je hoort zeker.
 
Het werkt!

Op een kleinigheidje na, dat ik heb aangepast, lijkt dit script te doen wat het moet doen. Moet nog even kijken hoe ik het inpas in het formulier, maar dat komt wel. Dank in elk geval voor het meedenken.

PS: de aanpassing betrof de vermelding
Code:
           If sZaakNr = "Geen Zaaknr" Then
                Me.AllowAdditions = True
                DoCmd.GoToRecord , , acNewRec
                Me.Zaaknr.Value = sZaakNr
                .Caption = "Record opslaan"
                .FontBold = True
                'etc
Dat moet volgens mij niet zijn: Me.Zaaknr.Value = sZaakNr, maar Me.Zaaknr.Value = sInput. Want anders komt in het veld zaaknr te staan "sZaakNr" terwijl je juist het door de gebruiker ingevoerde nummer wilt terugzien en daarmee verder wilt werken. Maar voor het overige niets dan lof.
 
Je hebt nog gelijk ook. Dat krijg je er van als je code uit het hoofd moet schrijven zonder het te kunnen testen :). Ik heb het ook in het voorbeeld maar aangepast.
 
Status
Niet open voor verdere reacties.
Steun Ons

Nieuwste berichten

Terug
Bovenaan Onderaan