Ho due tabelle collegate uno a molti fatturevendite e dettaglivendite senza
integrità referenziale. una maschera Fatturevendite e sottomaschera
dettaglivendite per l'inserimento dei dati.
Come potrei impedire l'inserimento di prodotti uguali nella sottomaschera?
Grazie anticipatamente a chi volesse darmi un aiuto.
Saluti Daniele
Per impedire duplicazioni ci sono sempre almeno 2 strade:
1 - impostare il/i campo/i da non duplicare come chiave univoca sulla
tabella, e in maschera intercettare l'errore che ti da' quando tenti una
duplicaz.
2 - Prima di ogni effettivo inserimento in tabella
(BeforeInsert,BeforeUpdate) , fare eseguire una parte di codice che
verifica che non ci sia gia' e in quel caso inserire effettivamente il
record.
Ciao
Ux
Impostando correttamente le Chiavi primarie con Duplicati non ammessi.....!
Ma......!
In realtà per no avere spiacevoli messaggi di avviso ti consiglio di
effettuare
una corretta gestione degli errori nell'evento OnError di Maschera, non
ricordo
se la duplicazione PrimaryKey corrisponde a 3021, in questo caso lo dovresti
gestire in modo che l'utente venga indirizzato, in quanto a lui che venga
duplicata
la PrimaryKey non dice nulla, se non di insultare il programmatore e magari
telefonargli
perchè non va nulla............!!!!
;-)
@Alex.
Cerco di spiegare meglio quello che cerco di fare.
Dovrei poter gestire lo scarico dei prodotti, senza fare fattura, cioè con
scontrino, da una maschera di scarico, basata sulla tblDettaglivendite.
oltre che con maschera e sottomaschera fattura, per regolare fattura. Per
fare questo non ho applicato l'integrità referenziale tra le tbl
fatturevendite e dettaglivendite. Al momento l'unico problema, che ho
rilevato io, era appunto la possibile duplicazione dei prodotti nella
sottomaschera dei dettagli di vendita. Come si dovrebbe impostare IDProdotto
nella tbl dettaglivendite?
saluti Daniele
Non ti sei spiegato male, solo non hai capito il Ns suggerimento.
Il fatto che ti sia possibile inserire Duplicati č la base del tuo problema.
Questo lo risolvi impostando diversamente le PrimaryKey della Tabella.
Ma a questo punto la Mascherina(SubForm) ti restituirŕ errori se
cerchi di inserire doppioni, perchč hai impostato a NO Duplicati Ammessi.
E' quě che devi gestire gli
errori.........................................................
@Alex.
> Non ti sei spiegato male, solo non hai capito il Ns suggerimento.
> Il fatto che ti sia possibile inserire Duplicati è la base del tuo
problema.
> Questo lo risolvi impostando diversamente le PrimaryKey della Tabella.
> Ma a questo punto la Mascherina(SubForm) ti restituirà errori se
> cerchi di inserire doppioni, perchè hai impostato a NO Duplicati Ammessi.
> E' quì che devi gestire gli
> errori.........................................................
..ed è qui che continuo a non capire. :-))
Scusami Alex, sono un pò duro, ma non riesco ad individuare questi errori
della SubForm. Continuo a dirti che, con le impostazioni attuali, non ho
nessun errore in nessuna maschera. Solo nella sottomaschera della fattura si
può inserire, per errore, lo stesso prodotto, cosa che vorrei evitare.
Nella tbldettaglivendite ho:
IDDettaglivendite PK; IDFatturavendite: duplicati ammessi; IDProdotto:
duplicati ammessi.
Quando inserisco un record dalla maschera Scarico IDFatturavendite è uno
zero.
Non so se questo può portarmi ad eventuali anomalie nel funzionamento del db
per eventuali ricerche e statistiche.
saluti Daniele
I casi sono veramente 2:
1)Non hai letto bene i POST(nel caso rileggi)
2)La prima che hai detto........... ;-)
Non ho detto che hai errori, ti ho detto che devi modificare il formato dati
nella tabella, dove dici Duplicati Ammessi devi invece inserire Duplicati
NON Ammessi.
Quando avrai fatto questa modifica, allora si che vedrai gli
ERRORI.............!!!
A questo punto per evitare di incasinare l'utente devi gestirli questi
errori, e come si
gestiscono....??? Intercettandoli, cioè inserendo un controllo nell'EVENTO
ONERROR
della SubForm, in quanto gli ERRORI vengono generati solo dopo il tentativo
di UPDATE, ma allora è già tardi, quindi o controlli tutti gli
inserimenti(troppi) oppure
più genericamente su evento ONERROR gestisci l'errore relativo, che come ti
dicevo
dovrebbe essere 3021.
Ci siamo.....................................
@Alex.
P.S. non ti offendere sto scherzando, se non sono stato chiaro lo ripeto
volentieri un Copia/Incolla
non mi scoccia.........!!!
Ma figurati... per così poco...ti conosco ... sono due anni che seguo questo
NG :-))
Se avevi capito il mio problema potevi anche dirmi come risolvere la
gestione degli errori.
detto questo ho messo: a Duplicati non ammessi idprodotto nella tabella
Dettaglivendite. inserisco un nuovo record e mi viene fuori il solito
messaggio di avviso di valori duplicati. Nessun numero di errore.
Speriamo che la notte mi porti consiglio...:-)))
saluti Daniele
Event Error(DataErr As Integer, Response As Integer)
Membro di Access.Form
--
Ciao :-)
Maurizio
--------
?SPQR(C)
X
--------
Ciao Maurizio, ti ringrazio per la risposta, ma non ho la necessaria
preparazione per poter capire come dovrei fare.
Ti sarei molto grato se potessi darmi maggiori delucidazioni.
saluti Daniele
---
Da qualche parte bisogna pur cominciare... ;-)
> Ti sarei molto grato se potessi darmi maggiori delucidazioni.
Volentieri, ma dopo che avrai consultato la guida a proposito di cio'
che ho scritto, in modo che tu possa spiegarci, riferendoti a quella, cosa
in particolare non ti e' chiaro. Diversamente, per darti maggiori
delucidazioni, dovrei fare un copia/incolla della guida e capisci bene che
non ha senso.
> Da qualche parte bisogna pur cominciare... ;-)
> > Ti sarei molto grato se potessi darmi maggiori delucidazioni.
>
> Volentieri, ma dopo che avrai consultato la guida a proposito di cio'
> che ho scritto, in modo che tu possa spiegarci, riferendoti a quella, cosa
> in particolare non ti e' chiaro.
Tutto!....la prima cosa che ho fatto, dopo il tuo precedente post, è stata
quella di cercare nella guida di access, 2000-sp1, EventError.
Chiedevo spiegazioni perchè non vedo cosa c'entra la modifica del messaggio
di errore, almeno è quello che ho capito, con il mio problema che
riepilogo.
Maschera e sottomaschera fatture; maschera scarico entrambe devono scrivere
record nella tabelle dettaglivendite, tabella fatture e dettagli non hanno
l'integrità referenziale, ci sono riuscito, dopo un'infinità di prove,
mettendo idprodotto a duplicati ammessi, non conosco altre soluzioni. :-)))
Ovviamente nella sottomaschera fattura si possono inserire gli stessi
prodotti ed era quello che volevo evitare.
saluti Daniele
---
Vabbe', come battuta e' buona ma autorizzerebbe a dirti di ripassare
piu' tardi, dopo che avrai digerito le nozioni basilari, oppure ad invitarti
a collaborare un po' di piu'... C'e' pero' anche la remotissima possibilita'
che io non abbia afferrato il senso del 3d. :-)))) Percio' rileggo tutti i
post e vediamo...
> la prima cosa che ho fatto, dopo il tuo precedente post, è stata
> quella di cercare nella guida di access, 2000-sp1, EventError.
> Chiedevo spiegazioni perchè non vedo cosa c'entra la modifica del
> messaggio
> di errore, almeno è quello che ho capito, con il mio problema che
> riepilogo.
> Maschera e sottomaschera fatture; maschera scarico entrambe devono
> scrivere
> record nella tabelle dettaglivendite, tabella fatture e dettagli non hanno
> l'integrità referenziale, ci sono riuscito, dopo un'infinità di prove,
> mettendo idprodotto a duplicati ammessi, non conosco altre soluzioni.
> :-)))
> Ovviamente nella sottomaschera fattura si possono inserire gli stessi
> prodotti ed era quello che volevo evitare.
Per ottenere cio' che richiedi dovrai avere una struttura del tipo:
Tabella: FattureVendita
Campi:
idFatturaVendita: Numerico, Intero lungo, Richiesto.
Indici:
pk: idFatturaVendita, Primario, Univoco.
Tabella: ProdottiVendita
Campi:
idProdottoVendita: Numerico, Intero lungo, Richiesto.
Indici:
pk: idProdottoVendita, Primario, Univoco.
Tabella: DettagliVendita
Campi:
idFatturaVendita: Numerico, Intero lungo, Richiesto;
idProdottoVendita: Numerico, Intero lungo, Richiesto;
idDettaglioVendita: Numerico, Intero lungo, Richiesto.
Indici:
pk: idDettaglioVendita, Primario, Univoco;
ukFattProd: idFatturaVendita, idProdottoVendita, Univoco;
kFatt: idFatturaVendita;
kProd: idProdotto.
In questo modo, grazie alla chiave univoca ukFattProd, non ti sara'
possibile avere prodotti duplicati nella stessa fattura.
Cosa succede in fase di immissione se invece si immette un prodotto gia'
presente nella fattura? Quando si tenta di passare ad un nuovo record di
dettaglio, compare il messaggio:
L'apporto modifiche non e' riuscito perche' si e' cercato di
duplicare i valori nell'indice, nella chiave primaria o nella
relazione. Modificare i dati nel campo o nei campi che
contengono dati duplicati, rimuovere l'indice per consentire
l'inserimento di voci duplicate, quindi ritentare l'operazione.
[ Ok ] [ ? ]
Chiaramente non va bene spaventare gli utenti della nostra applicazione
con questa pappardella, meglio un messaggio conciso ma chiaro, che indichi
anche come l'utente deve comportarsi per rimediare. Questo lo si ottiene
appunto intercettando l'errore nella procedura evento di cui ti ho parlato.
E' stato bello assistere........!
No Maurizio hai afferrato benissimo il senso, purtroppo facciamo fatica
a capirci a vicenda, per colpa di entrambi, mi spiego....!
Quello che vuole fare Cidi, e che sono sicuro tu abbia capito, è una cosa
abbastanza ovvia, ma richiede un minimo di conoscenza di base sia
della Terminologia, che dei contenuti dei Database.
Mi pare, senza che Cidi si ritenga offeso, che debba fare ancora qualche
passettino
per completare queste cose...........!
Di contro da parte nostra, io per primo, diamo per scontato che lui sappia
ciò di cui staimo
parlando, e visto che chiede aiuto, mi pare ovvio non sia così.
Detto questo.........:
La segnalazione che ricevi dopo aver fatto le modifiche di cui sopra si può
evitare, come..?
Inserendo una condizione nell'evento OnError di Maschera.
Per tua conoscenza, sull'evento in questione inserisci MsgBox Err.Number &
"-->" & Err.Description
Ora puoi vedere qual'è l'errore al quale mi riferivo.....!
Quì adesso devi solo dirottarlo, con una condizione sempre nell'evento
Errore:
If err.Number=NumeroDiPrima then MsgBox"Stai inserendo Valori
Doppi.....!!!":Exit Sub
Ciao.
@Alex.
:-)
> Ora puoi vedere qual'è l'errore al quale mi riferivo.....!
> Quì adesso devi solo dirottarlo, con una condizione sempre nell'evento
> Errore:
> If err.Number=NumeroDiPrima then MsgBox"Stai inserendo Valori
> Doppi.....!!!":Exit Sub
Sicuro? Ora non posso verificare ma, dato che stiamo parlando di:
Event Error(DataErr As Integer, Response As Integer)
Membro di Access.Form
mi sembra non si possa gestire l'errore come se fosse un errore di run-time
di Visual Basic dato che dovrebbe essere un errore di run-time di Access.
Ecco, mi pareva. Questo e' l'esempio della guida:
Private Sub Form_Error(DataErr As Integer, Response As Integer)
Const conChiaveDuplicata = 3022
Dim strMsg As String
If DataErr = conChiaveDuplicata Then
Response = acDataErrContinue
strMsg = "È necessario che ciascun record per impiegato abbia " _
& "un numero ID impiegato univoco. Verificare di nuovo i dati."
MsgBox strMsg
End If
End Sub
Beh, quello che hai postato è quello che intendevo, ho provato a leggere
la guida, ma non ho trovato nulla, se non:
dalla guida.......
"DataErr Il codice di errore restituito dall'oggetto Err quando si verifica
un errore.
È possibile utilizzare l'argomento DataErr con la funzione Error per
associare il numero al messaggio di errore corrispondente."
Da quì ho dedotto che si potesse usare Err direttamente, anche se in effetti
non serve.
C'è da dire che non ho mai usato questa tecnica, quindi non ne conosco i
difetti
perchè solitamente uso Form non associate su inserienti e usando le
transazioni sul
metodo Execute mi risolvo molte rogne.......!
Questa però mi pareva, con le opportune correzioni, la strada più semplice
da spiegare..........!!!
@Alex.
Piu' che altro l'errore non verrebbe proprio intercettato e comparirebbe
la pappardella di cui sopra (se non sbaglio).
> C'č da dire che non ho mai usato questa tecnica, quindi non ne conosco i
> difetti
> perchč solitamente uso Form non associate su inserienti e usando le
> transazioni sul
> metodo Execute mi risolvo molte rogne.......!
> Questa perň mi pareva, con le opportune correzioni, la strada piů semplice
> da spiegare..........!!!
Ecco, appunto. Allora tu non hai bisogno di intercettare tali errori
perche' con le maschere unbound tali eventi di errore non si scatenano
proprio. (Sempre se non sbaglio).
> Vabbe', come battuta e' buona ma autorizzerebbe a dirti di ripassare
> piu' tardi, dopo che avrai digerito le nozioni basilari, oppure ad
invitarti
> a collaborare un po' di piu'...
M.......a non penserai che mi pesti da solo quelle cose che finiscono con
gli oni? no vero? :-))))
C'e' pero' anche la remotissima possibilita'
> che io non abbia afferrato il senso del 3d. :-))))
> Per ottenere cio' che richiedi dovrai avere una struttura del tipo:
> Tabella: DettagliVendita
> Campi:
> idFatturaVendita: Numerico, Intero lungo, Richiesto;
> idProdottoVendita: Numerico, Intero lungo, Richiesto;
> idDettaglioVendita: Numerico, Intero lungo, Richiesto.
> Indici:
> pk: idDettaglioVendita, Primario, Univoco;
> ukFattProd: idFatturaVendita, idProdottoVendita, Univoco;
> kFatt: idFatturaVendita;
> kProd: idProdotto.
Si ho una struttura uguale tranne per questo:
" ukFattProd: idFatturaVendita, idProdottoVendita, Univoco; "
che non so come fare.
> In questo modo, grazie alla chiave univoca ukFattProd, non ti sara'
> possibile avere prodotti duplicati nella stessa fattura.
Hai centrato il problema! era questo che volevo sapere.
Consentendomi di scaricare lo stesso prodotto con una maschera singola,
senza fare una fattura. giusto?
> Chiaramente non va bene spaventare gli utenti della nostra applicazione
> con questa pappardella, meglio un messaggio conciso ma chiaro, che indichi
> anche come l'utente deve comportarsi per rimediare. Questo lo si ottiene
> appunto intercettando l'errore nella procedura evento di cui ti ho
parlato.
Certamente adesso si può intercettare il messaggio e modificare il testo. Ma
prima no perchè non avevo nessun messaggio, settando a si duplicati ammessi
idprodotto, invece mettendolo a no duplicati non ammessi, non riuscivo a
scaricare senza fattura.
saluti Daniele
---
Non saprei, non ho fatto prove in merito.
> > C'è da dire che non ho mai usato questa tecnica, quindi non ne conosco i
> > difetti
> > perchè solitamente uso Form non associate su inserienti e usando le
> > transazioni sul
> > metodo Execute mi risolvo molte rogne.......!
> > Questa però mi pareva, con le opportune correzioni, la strada più
semplice
> > da spiegare..........!!!
>
> Ecco, appunto. Allora tu non hai bisogno di intercettare tali errori
> perche' con le maschere unbound tali eventi di errore non si scatenano
> proprio. (Sempre se non sbaglio).
>
Beh, in realtà gli errori li hai, solo che io imposto SetWarning=False, ma
come opzione del'Execute uso dbFailOnerror, poi controllo quanti Record
ha modificato la QRY, di quì gestisco con le transazioni una corretta
gestione.
Poi dipende tutto da come si struttura la cosa..........!
@Alex.
Imparata la lezione degli indici multicampo. Nella sottomaschera fattura
intercetto il messaggio d'errore standard, però non risolvo il problema. La
chiave univoca vale anche per la maschera Scarico ed ovviamente mi blocca
appena inserisco lo stesso prodotto due volte. Qualche altra info per
un'altro passettino in avanti? Grazie
saluti Daniele
Mi sa che non ci sia altro da fare che eliminare quell'indice e gestire
la cosa in altro modo: un indice o va bene in tutte le circostanze o non
merita di esistere.
Un modo potrebbe essere quello di verificare, nella fase di carico, in
cui non sono ammessi duplicati, prima della registrazione del record, se
c'e' la possibilita' di ottenere un duplicato... Oppure non preoccuparsene
ed intercettare l'errore.
oddio... la sibilla cumana! :-))
Maurizio, ti prego, non giudicarmi male. Considerata la tua bravura non
posso e non voglio essere irrispettoso ma la tua risposta mi è oscura.
Una domanda: è possibile leggere la query della sottomaschera ed impedire i
duplicati?
saluti Daniele
Vabbe', ma quanno ce vo' ce vo'!... Per esempio, in questo caso avresti
dovuto domandarmi:
"ma che caspita c'entra la frase 'Oppure non preoccuparsene ed
intercettare l'errore'?!?!"
che, rileggendomi, neppur io capisco perche' l'abbia scritta. E'
evidentemente un "avanzo" del discorso precedente a proposito dell'indice
multichiave che qui pero' non c'entra piu' niente. Scusami.
> ma la tua risposta mi è oscura.
> Una domanda: è possibile leggere la query della sottomaschera ed impedire
> i duplicati?
Facciamo un esempio, ok?
Tabella: x cidi
Campi:
id: numerico, intero lungo, richiesto, duplicati non
ammessi, valido se >0, primario;
idTipoOperazione: numerico, intero lungo, richiesto,
duplicati ammessi, valido se between 1 and 2,
descrizione 1=Carico; 2=Scarico;
idDocumento: numerico, intero lungo, richiesto,
duplicati ammessi, valido se >0;
idArticolo: numerico, intero lungo, richiesto,
duplicati ammessi, valido se >0;
Quantità: numerico, precisione doppia, richiesto.
Maschera: x cidi
Origine record: x cidi
Su apertura: =docmd.restore
Casella di testo id:
Valore predefinito: nz(DMax([id].[Name];"x cidi");0)+1
Modulo Visual basic:
Option Base 0
Option Compare Database
Option Explicit
Private Sub Form_BeforeUpdate( _
ByRef Cancel As Integer)
Const c_lIdTipoOperazioneSenzaDuplicati& = 1
Dim sWhere As String
Dim sTitle As String
Dim sPrompt As String
Dim lButtons As VBA.VbMsgBoxStyle
Dim oDaoRst As DAO.Recordset
With Me
If (.NewRecord = True) Then
If ( _
.idTipoOperazione.Value _
= c_lIdTipoOperazioneSenzaDuplicati _
) Then
lButtons = vbExclamation + vbOKOnly
sWhere _
= "[" & .idDocumento.ControlSource & "]" _
& " = " & .idDocumento.Value _
& " AND " _
& "[" & .idArticolo.ControlSource & "]" _
& " = " & .idArticolo.Value
Debug.Print sWhere
sTitle = "Attenzione!"
sPrompt _
= "Articolo " & .idArticolo.Value _
& " già presente" & vbCrLf _
& "nel Documento " & .idDocumento.Value _
& "."
Debug.Print sPrompt
Set oDaoRst = .RecordsetClone
With oDaoRst
.FindFirst sWhere
If (.NoMatch = False) Then
Cancel = True
MsgBox sPrompt, lButtons, sTitle
End If
End With
Set oDaoRst = Nothing
End If
End If
End With
End Sub
Prova a farlo girare.
Questa e' ancora piu' bellina:
nz(DMax([id].[Name];[recordset]![id].[sourcetable]);0)+1
> Prova a farlo girare.
Grazie, ci provo.
saluti Daniele
---
Fallo anche con A97..........!!! ;-)
@Alex.
Nun cello'... Che succede? BSOD?
Un se pole................, i vecchietti che hanno come me 97 devono
rimpiangere parecchie migliorie di XP e 2000.....!
Arriveranno tempi migliori....... ne rimarrà solo 1.
@Alex.
Grazie... Chissa' che mi credevo. Se non ricordo male in A97 Form non ha
la proprieta' recordset. Sbaglio?
> i vecchietti che hanno come me 97 devono
> rimpiangere parecchie migliorie di XP e 2000.....!
> Arriveranno tempi migliori....... ne rimarrà solo 1.
Seee... Quando mai...
No, difficilmente sbagli, e mi tocca darti ragione anche ora....! ;-)
> > i vecchietti che hanno come me 97 devono
> > rimpiangere parecchie migliorie di XP e 2000.....!
> > Arriveranno tempi migliori....... ne rimarrà solo 1.
>
> Seee... Quando mai...
Mai.
@Alex.
Ciao Maurizio, ho provato il tuo codice e funziona tutto perfettamente. Però
non riesco a capire come adattarlo al mio caso. Certamente tu avresti fatto
tutto con 3-4 tabelle per fare carico dei prodotti da fornitori, e scarico a
dettaglio e tramite le fatture di vendita. Io invece ho per gli acquisti:
fornitori, fattureacquisti e dettagliacquisti. per le vendite: clienti,
fatturevendite e dettaglivendite con la tabella prodotti legata alle due dei
dettagli. Prima o poi troverò una soluzione. grazie
saluti Daniele