Individuare controllo su duplicati non ammessi

di il
5 risposte

Individuare controllo su duplicati non ammessi

Buona sera.
Premetto che è solo per puro esercizio di stile per trovare soluzioni alternative a problemi già risolti, magari trovando modi più snelli e performanti.

Ho più di un campo indicizzato con duplicati non ammessi e l'immissione avviene in modo manuale senza l'uso di combo box o formattazioni particolari e naturalmente non voglio usare lookup o altri artefizi.

In caso di errore nella fase di immissione dati, naturalmente access mi avverte del problema generando l'errore 3022 e che gestisco tramite la gestione errori della form.

Però naturalmente non mi dice quale campo (o campi) genera l'errore e avendone più di uno ho necissità di sapere quale contiene il duplicato.
Come faccio ad individuare il valore (o i valori) sbagliato, visto che il 3022 si genera solo al momento dell'aggiornamento del record e non è nemmeno intercettabile?

Sono 3 giorni che spulcio manuali, guida microsoft e vari forum, ma non riesco a trovare la soluzione, anche a livello logico.
SUggerimenti?
Grazie.

5 Risposte

  • Re: Individuare controllo su duplicati non ammessi

    Mi viene in mente solo un modo, anzi 2:
    1) controlli sul beforeupdate di ogni controllo
    2) controlli prima dell'aggiornamento della form tutti i campi

    non so se i contenuti dei campi siano legati tra loro ma in base alle dinamiche del tuo db forse puoi creare un'unica funzione passando come parametro il controllo... dipende

    non credo si possa fare quello che chiedi, cioè capire quale controllo ha generato il 3022 a posteriori ... forse su err.description dice qualcosa in più fai una prova
  • Re: Individuare controllo su duplicati non ammessi

    Fai una prova semplice... che solitamente è la cosa migliore.

    Genera un duplicato su un Campo, genera l'errore e nell'evento FORM_ERROR che mi pare tu gestisca e fai una cosa simile:
    
    Select case DataErr
        Case 3022
            Msgbox "Controllo : " & Screen.ActiveControl.ControlSource 'Oppure Name
            
    ...
    Se, l'errore viene generato, come spero, prima dell'Exit potresti avere la soluzione... ovviamente se poi ti sposti e fai la medesima cosa su altro campo deve restituire il controllo attivo su cui hai appena inserito il duplicato.
  • Re: Individuare controllo su duplicati non ammessi

    Ciao Alex e grazie della risposta.

    Tra le molte prove, non avevo preso in considerazione questa soluzione, perchè mi sembrava di ricordare che questa istruzione riguardasse l'ultimo controllo che aveva il focus. Ed infatti è così. E non mi sembra che ci siano metodi sfruttabili per ricavare chi ha generato l'errore.

    Il problema del 3022 è che tecnicamente non è un vero errore, ma un avviso, quindi non intercettabile con Err o per altre vie.
    In ogni esempio che ho trovato, viene sempre intercettato nella Form_Error, dove è troppo tardi per individuare il controllo che ha generato l'errore del duplicato.

    Certo, potrei controllare a monte controllando manualmente gli eventuali duplicati, controllando il campo nella tabella di destinazione, ma non è quello che voglio fare, anche perchè a quel punto sarebbe superfluo usare il Form_Error, visto che non farei generare nemmeno l'errore 3022.

    Spulciando anche in siti stranieri dalla lingua discutibile, (Coreano per la cronaca) mi viene il forte dubbio che non esista un metodo per ricavare il dato, ma può essere solo essere gestito manualmente, prima o dopo, andando a confrontare il dato inserito con quelli già inseriti nella tabella.
    Possibile che in access il controllo dei duplicati sia usa e getta e non sia possibile recuperarlo?
  • Re: Individuare controllo su duplicati non ammessi

    In effetti la mia era una speranza... ovvero che inserito il valore in textbox scatenasse il warning e di conseguenza il Form_error che avrebbe fatto coincidere il controllo attivo con quello che avrebbe girato errore...
    Peccato, però ci faccio una pensata.

    Ovviamente se segui la strada della validazione chiaramente sarebbe inutile la gestione errori su form.

    Altra opzione è mettere su Validazione un Dcount(...)<1 questo scatenerrbbe errore sempre intercettabile su Form_erorr e questo sarebbe sincrono con ActuveControl.

    Non è bellissimo ma potrebbe evitare di dover ciclare tutti i controlli ma solo quelli modificati.

    Io poi francamente sono uso costruirmi classi di controllo e validazione con Eventahandler quindi la gestirei diversamente...
  • Re: Individuare controllo su duplicati non ammessi

    La verifica fatta con il VALIDATION RULE funziona correttamente.

    Ti mostro l'esempio, ho fatto una Tabella chiamata T1 con 3 campi tutti Indicizzatri e Duplicati NON ammessi:
    [ID] Numerico Indicizzato Duplicati Non ammessi
    [Targa] Testo Indicizzato Duplicati Non ammessi
    [Nome] Testo Indicizzato Duplicati Non ammessi

    Nei 3 Controlli di maschera ho inserito:
    ID(Valido se):DCount("*";"T1";"ID=" & [ID])<1
    Targa(Valido Se):DCount("*";"T1";"Targa='" & [Targa] & "'")<1
    Nome(Valido Se):DCount("*";"T1";"Nome='" & [Nome] & "'")<1
    Gestendo Form ERROR, io ho questo codice che riciclo, viene generato errore 2107, nel mio caso ERR_DATAVALIDATION1:
    
    Option Compare Database
    Option Explicit
    
    Private Const ERR_ONETOMANYCONFLICT = 3101
    Private Const ERR_RELATEDRECORDS1 = 3200
    Private Const ERR_RELATEDRECORDS2 = 3201
    Private Const ERR_REQUIREDDATA = 3314
    Private Const ERR_DUPLICATEKEY = 3022
    Private Const ERR_NOCURRRECFOUND = 3021
    Private Const ERR_DATATYPE = 2113
    Private Const ERR_INPUTMASK = 2279
    Private Const ERR_NULLKEY = 3058
    Private Const ERR_NULLVALUE = 3162
    Private Const ERR_ZEROLENGTHSTRING = 3315
    Private Const ERR_DATAVALIDATION1 = 2107
    Private Const ERR_DATAVALIDATION2 = 3317
    Private Const ERR_ITEMNOTINLIST1 = 2237
    Private Const ERR_ITEMNOTINLIST2 = 2473
    
    
    Private Sub Form_Error(DataErr As Integer, Response As Integer)
        Const NEXT_MSG = "See next message for details."
    
        Select Case DataErr
            Case Is = ERR_ITEMNOTINLIST1, ERR_ITEMNOTINLIST2
                Response = acDataErrContinue
                MsgBox "Seleziona solo valori nella lista."
                ActiveControl.Undo
                            
            Case ERR_REQUIREDDATA
                MsgBox "Required value missing!" & vbCr & _
                       NEXT_MSG, vbInformation, "WARNING"
                Response = acDataErrDisplay
    
            Case ERR_RELATEDRECORDS1, ERR_RELATEDRECORDS2
                MsgBox "Relation conflict!" & vbCr & _
                       NEXT_MSG, vbInformation, "WARNING"
                Response = acDataErrDisplay
    
            Case ERR_NULLKEY, ERR_NULLVALUE, ERR_ZEROLENGTHSTRING
                MsgBox "Field can not be empty.", vbInformation, "WARNING"
                Response = acDataErrContinue
    
            Case ERR_DUPLICATEKEY
                MsgBox "The value is already in use to " & _
                       "create an unique record. Change the value.", vbInformation, "WARNING"
                Response = acDataErrContinue
    
            Case ERR_DATATYPE, ERR_INPUTMASK
                MsgBox "The value has an incorrect data type" & vbCr & _
                       "(f.i. text value in a numeric field).", _
                       vbInformation, "WARNING"
                Response = acDataErrContinue
                ActiveControl.Undo
    
            Case ERR_DATAVALIDATION1, ERR_DATAVALIDATION2
                'Custom validation rules: show corresponding error message
                 MsgBox "Controllo DUPLICATO: " & Screen.ActiveControl.Name, vbInformation, "WARNING"
                 Response = acDataErrContinue
    
            Case Else
                'Display the default error message
                Response = acDataErrDisplay
        End Select
    
    End Sub
    Non mi pare una bruttissima soluzione...
Devi accedere o registrarti per scrivere nel forum
5 risposte