Forum des développeurs  

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é.
Précédent   Forum des développeurs > Hardware, Systèmes et Logiciels > Microsoft Office > Défis

Défis Ce forum est celui des défis et challenges Office. Prêts à relever le gant ? C'est parti !

Réponse
 
Outils de la discussion
Vieux 24/03/2007, 22h51   #1 (permalink)
Rédacteur

 
Avatar de Tofalu
 
Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
Par défaut [Exercice] Numérotation automatique d'enregistrements

Bonjour,

Je vous propose un petit exercice :

Comment procederiez vous pour avoir une table offrant 3 identifiants par enregistrement ?
  • Le champ 1 serait un numéro auto croissant
  • Le champ 2 serait un numéro aléatoire
  • Le champ 3 serait un autre numéro aléatoire

Code :
N1	N2	N3	Libelle
1	-858043924	-436861315	Chien
2	1683190266	-1215191821	Chat
3	-594784072	1798275161	Baleine
Notez que des valeurs de N1 peuvent se trouver dans N2 ou N3 et vice versa. Par contre, une valeur de N2 ne peut se répeter dans N2 et idem pour les deux autres colonnes.

Des idées ?

Si possible, j'aimerais que la solution que vous proposiez puisse s'adapter facilement à d'autres champs, genre une dizaine
Tofalu est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 25/03/2007, 08h12   #2 (permalink)
Membre expérimenté
 
Date d'inscription: août 2006
Messages: 588
Par défaut

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
 
helas est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 25/03/2007, 13h37   #3 (permalink)
Rédacteur

 
Avatar de Tofalu
 
Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
Par défaut

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
Tofalu est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 25/03/2007, 15h53   #4 (permalink)
Membre expérimenté
 
Date d'inscription: août 2006
Messages: 588
Par défaut

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
 
helas est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 25/03/2007, 17h00   #5 (permalink)
Rédacteur
 
Avatar de LedZeppII
 
Date d'inscription: décembre 2005
Localisation: IdF
Messages: 2 057
Par défaut

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
A+
LedZeppII est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 25/03/2007, 17h12   #6 (permalink)
Rédacteur

 
Avatar de Tofalu
 
Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
Par défaut

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 ?
Tofalu est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 25/03/2007, 19h07   #7 (permalink)
Membre expérimenté
 
Date d'inscription: août 2006
Messages: 588
Par défaut

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(....)
helas est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 25/03/2007, 20h14   #8 (permalink)
Rédacteur

 
Avatar de Tofalu
 
Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
Par défaut

Citation:
Pour l'utilisation dans un formulaire, Valeur par defaut = DIncrement(....)
Arf, et si je ne veux pas passer par un formulaire ?
Tofalu est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 26/03/2007, 08h59   #9 (permalink)
Membre expérimenté
 
Date d'inscription: août 2006
Messages: 588
Par défaut

Passer par quoi ?
Du code ?
helas est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 26/03/2007, 09h34   #10 (permalink)
Expert Confirmé Sénior
 
Date d'inscription: mai 2005
Messages: 3 285
Par défaut

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 ?
random est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 26/03/2007, 12h37   #11 (permalink)
Rédacteur

 
Avatar de Tofalu
 
Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
Par défaut

Citation:
Envoyé par random
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

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
Tofalu est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 26/03/2007, 14h36   #12 (permalink)
Expert Confirmé Sénior
 
Date d'inscription: mai 2005
Messages: 3 285
Par défaut

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 ?
random est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 26/03/2007, 20h52   #13 (permalink)
Rédacteur

 
Avatar de Tofalu
 
Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
Par défaut

Peut être existe t'il une solution qui permettrait d'être sûr qu'aucun doublon ne sera généré
Tofalu est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 27/03/2007, 11h11   #14 (permalink)
Expert Confirmé Sénior
 
Date d'inscription: mai 2005
Messages: 3 285
Par défaut

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;
 
permettant de retrouver à tous moments les clefs

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
random est déconnecté   Envoyer un message privé Réponse avec citation
Vieux 27/03/2007, 20h51   #15 (permalink)
Rédacteur

 
Avatar de Tofalu
 
Date d'inscription: octobre 2004
Localisation: Mâcon
Messages: 5 851
Par défaut

C'est pas mal, mais je pense qu'on devrait pouvoir arriver à quelque chose garantissant encore plus le non doublonnage
Tofalu est déconnecté   Envoyer un message privé Réponse avec citation
Réponse

Précédent   Forum des développeurs > Hardware, Systèmes et Logiciels > Microsoft Office > Défis

 
Offres d' emploi informatique sur Lesjeudis.com


Outils de la discussion

Règles de messages
Vous ne pouvez pas créer de nouvelles discussions
Vous ne pouvez pas envoyer des réponses
Vous ne pouvez pas envoyer des pièces jointes
Vous ne pouvez pas modifier vos messages

Les balises BB sont activées : oui
Les smileys sont activés : oui
La balise [IMG] est activée : oui
Le code HTML peut être employé : non
Trackbacks are non
Pingbacks are non
Refbacks are non
Navigation rapide