![]() |
| Le forum de référence en programmation et développement. Articles, cours et tutoriels du débutant au chef de projet et DBA confirmé. | |||||||
|
|||||||
| Défis Ce forum est celui des défis et challenges Office. Prêts à relever le gant ? C'est parti ! |
![]() |
|
|
Outils de la discussion |
|
|
#1 (permalink) |
![]() ![]() Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
|
Bonjour,
Je vous propose un petit exercice : Comment procederiez vous pour avoir une table offrant 3 identifiants par enregistrement ?
Code :
N1 N2 N3 Libelle 1 -858043924 -436861315 Chien 2 1683190266 -1215191821 Chat 3 -594784072 1798275161 Baleine Des idées ? Si possible, j'aimerais que la solution que vous proposiez puisse s'adapter facilement à d'autres champs, genre une dizaine
__________________
Tutoriel : Gestion de favoris sous Access 2007 Cours : Manipulation des fichiers en VBA
|
|
|
|
|
|
#2 (permalink) |
|
Membre expérimenté
![]() Date d'inscription: août 2006
Messages: 588
|
Code :
Sub NouvelEnregistrement(animal As String) Dim n As Long, i As Integer, j As Integer, max As Long,NbChamp As Integer Dim db As DAO.Database, t As DAO.Recordset, t2 As DAO.Recordset Set db = CurrentDb NbChamp = 5 'Nombre de champs N max = DMax("[N1]", "tbAnimaux") + 1 'recherche N1 suivant Set t = db.OpenRecordset("tbAnimaux") t.AddNew t!N1 = max 'champ auto croissant For j = 2 To NbChamp 'pour chacun des champs N Do '################## If Rnd(1) > 0.5 Then 'sélection du signe n = Rnd(1) * 2147483647 Else n = Rnd(1) * -2147483647 End If For i = 2 To NbChamp 'recherche presence du nombre n Set t2 = db.OpenRecordset("SELECT tbAnimaux.N" & CStr(i) & " FROM tbAnimaux WHERE (((tbAnimaux.N" & CStr(i) & ")=" & n & "));") If Not t2.EOF Then t2.Close: Exit For t2.Close Next i If i = 6 Then Exit Do 'nombre n'existe pas Loop '#################### t("N" & CStr(j)) = n 'enregistrement du nombre n dans champ N Next j t!texte = animal t.Update t.Close Set t = Nothing Set db = Nothing End Sub |
|
|
|
|
|
#3 (permalink) |
![]() ![]() Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
|
Bonjour,
Cette solution ne me satisfait qu'à moitié car peu réutilisable. Peut être serait t'il possible de la transformer en fonction qui accepteraient comme argument : Le nom du champ, Celui de la table Le type d'incrémenation Genre DIncrement("N1","MaTable",0) renverrai un numéro autoincrémenté valide DIncrement("N2","MaTable",1) renverrai un numéro aléatoire valide Reste à voir comment utiliser cette fonction facilement dans un formulaire, et aussi lister les avantages et ses inconvénients pour les données En tout cas, merci de ta participation
__________________
Tutoriel : Gestion de favoris sous Access 2007 Cours : Manipulation des fichiers en VBA
|
|
|
|
|
|
#4 (permalink) |
|
Membre expérimenté
![]() Date d'inscription: août 2006
Messages: 588
|
Avec dans le formulaire pour les champs la valeur par defaut =Dincrement("tbTest";0) pour l'increment simple et =Dincrement("tbTest";1) pour le nombre aleatoire
Les champs testés pour le nombre aleatoire sont les champs dont le nom se terminent par un nombre à partir du 2ème caractère N12 est valide, B13 aussi, as12 ou n15d ne le sont pas Code :
Function DIncrement(NomTable As String, TypeIncrement As Integer) As Long Select Case TypeIncrement Case 0 DIncrement = DMax("N1", NomTable) + 1 Case 1 Dim i As Integer, NbChamps As Long Dim db As DAO.Database, t As DAO.Recordset Set db = CurrentDb Set t = db.OpenRecordset(NomTable) NbChamps = 0 For i = 0 To t.Fields.Count - 1 If IsNumeric(Mid$(t.Fields(i).Name, 2)) Then NbChamps = NbChamps + 1 Next i Randomize Do '################## DIncrement = (Rnd(1) * 2147483647) * IIf(Rnd(1) > 0.5, 1, -1) 'genere le nombre aleatoire For i = 2 To NbChamps 'recherche presence du nombre Set t = db.OpenRecordset("SELECT [" & NomTable & "].N" & CStr(i) & " FROM [" & NomTable & "] WHERE (([" & NomTable & "].N" & CStr(i) & ")=" & DIncrement & ");") If Not t.EOF Then t.Close: Exit For t.Close Next i If i = NbChamps + 1 Then Exit Do 'nombre n'existe pas Loop '#################### Set t = Nothing Set db = Nothing End Select End Function |
|
|
|
|
|
#5 (permalink) |
![]() Date d'inscription: décembre 2005
Localisation: IdF
Messages: 2 057
|
Bonjour,
voila ma proposition. Code :
Function NouvId(Table, Champ, Optional Incr = 1) As Long Dim s As Single, vMax As Variant If Incr = 1 Then Randomize Do s = Rnd() * 4294967294# If s > 2147483647 Then s = -s NouvId = CLng(s / 2) Loop Until IsNull(DLookup(Champ, Table, Champ & "=" & NouvId)) Else vMax = DMax(Champ, Table) NouvId = IIf(IsNull(vMax), 0, vMax) + 1 End If End Function |
|
|
|
|
|
#6 (permalink) |
![]() ![]() Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
|
Helas, ta solution ne tiens pas compte du nom du champ à passer en paramètre. De ce fait, la solution de LedZeppII me parait meilleure, toutefois, reste une question, comment allez vous l'utiliser ?
__________________
Tutoriel : Gestion de favoris sous Access 2007 Cours : Manipulation des fichiers en VBA
|
|
|
|
|
|
#7 (permalink) |
|
Membre expérimenté
![]() Date d'inscription: août 2006
Messages: 588
|
Je pensais que le nombre aleatoire devait être unique dans toute la table, c'est pourquoi je testais aussi les autres champs Nn
La version de LedZeppII est effectivement meilleur Pour l'utilisation dans un formulaire, Valeur par defaut = DIncrement(....) |
|
|
|
|
|
#8 (permalink) | |
![]() ![]() Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
|
Citation:
__________________
Tutoriel : Gestion de favoris sous Access 2007 Cours : Manipulation des fichiers en VBA
|
|
|
|
|
|
|
#10 (permalink) |
|
Expert Confirmé Sénior
![]() Date d'inscription: mai 2005
Messages: 3 285
|
champ1 numéro auto incrément
champ2 double valeur par défaut rnd() indexé sans doublon champ3 double valeur par défaut rnd() indexé sans doublon reste à gérer les improbables conflits
__________________
Elle est pas belle la vie ? |
|
|
|
|
|
#11 (permalink) | |
![]() ![]() Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
|
Citation:
Ah ben là c'est clairement déjà mieux puisque d'une part il est possible d'ajouter les données directement dans la table et d'autre part l'index permet de garantir l'intégrité des données. Seul bémol effectivement il faut gérer les conflits très improbable. Ce n'est pas vraiment à cette solution que je pensais mais celle ci n'est pas mal du tout
__________________
Tutoriel : Gestion de favoris sous Access 2007 Cours : Manipulation des fichiers en VBA
|
|
|
|
|
|
|
#12 (permalink) |
|
Expert Confirmé Sénior
![]() Date d'inscription: mai 2005
Messages: 3 285
|
Après test et 510 0000 enregistrements ajoutés en plusieurs passes pas de conflit.
Comme disent les statisticiens « un évènement improbable ne se produit jamais »
__________________
Elle est pas belle la vie ? |
|
|
|
|
|
#13 (permalink) |
![]() ![]() Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
|
Peut être existe t'il une solution qui permettrait d'être sûr qu'aucun doublon ne sera généré
__________________
Tutoriel : Gestion de favoris sous Access 2007 Cours : Manipulation des fichiers en VBA
|
|
|
|
|
|
#14 (permalink) |
|
Expert Confirmé Sénior
![]() Date d'inscription: mai 2005
Messages: 3 285
|
en testant ceci pour champ1=1 à 3000000
champ2=rnd(-champ1) champ3=rnd(-champ2) on trouve 3556 doublons sur champ2 ceci provient de la piètre qualité du générateur de nombres aléatoires de microsoft en examinant les résultats on s'aperçoit que les doublons sont de la forme x, (x*2^y)-1 genre valeur valeur doublon 8....... 2097151 17..... 1114111 18...... 1179647 19.... 1245183 ..... 11718 2999807 le plus grand nombre ayant un doublon qui lui est supérieur est donc 11718 sur l'intervalle choisi conclusion si je définis champ2=rnd(-champ1-11718) champ3=rnd(rnd(-champ1-11718)) je dispose de deux clefs pseudo aléatoires et d'un compteur auqel cas mettre ces clefs dans la base serait inutile Code :
SELECT champ1, Rnd(-[champ1]-11718) AS champ2, Rnd(Rnd(-[champ1]-11718)) AS champ3 FROM matable; nb à ne pas utiliser en sécurité ni en cryptographie sans bien bien réfléchir
__________________
Elle est pas belle la vie ? Dernière modification par random ; 27/03/2007 à 14h17 |
|
|
|
|
|
#15 (permalink) |
![]() ![]() Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
|
C'est pas mal, mais je pense qu'on devrait pouvoir arriver à quelque chose garantissant encore plus le non doublonnage
__________________
Tutoriel : Gestion de favoris sous Access 2007 Cours : Manipulation des fichiers en VBA
|
|
|
|
![]() |
![]() |
||
[Exercice] Numérotation automatique d'enregistrements
|
||
| Outils de la discussion | |
|
|