IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

VBA Access Discussion :

empêcher une requête ajout d'afficher des doublons dans une table


Sujet :

VBA Access

  1. #1
    Membre actif
    Inscrit en
    Avril 2007
    Messages
    1 241
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 1 241
    Points : 213
    Points
    213
    Par défaut empêcher une requête ajout d'afficher des doublons dans une table
    Bonjour,
    je reviens à la charge pour un problème que j'ai du mal à resoudre .
    j'ai trouve un début de réponse dans un forum.
    J'ai essayé d'adapter la solution à mon problème mais en vain.

    Je résume le cas :
    J'ai une requête d'ajout parametrée avec une date début et une date fin. Cette requete ajout enregistre divers informations sur une table "statistique_bureaux".
    Cette requête est à effectuer une fois par jour en inserant la date début et la date fin.
    Si l'utilisateur tape encore la mêmes date, il aura des doublons dans la table "statistique_bureaux"

    Comment empêcher cette fausse manoeuvre au moment de lancer la requête.
    "aller verifier si le dernier de la table "statistique_bureaux" contient la même
    journée (champ [jour] que ce que la requête se prépare à copier et l'empêcher..


    Le code que j'ai pu obtenir est le suivant :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    Sub doublon()
     If Me.jour = DMax("[jour]", "T_statistique_bureaux") Then  'test prend la plus grande valeur du champ [jour] de la table de T_statistiques_bureaux
    MsgBox " c'est déjà fait"
    Else
    DoCmd.OpenQuery "R_statistique_bureaux"
    End If
     
    End Sub
    lorsque je lance ce code pour essaie, j 'ai un message d'erreur :
    "erreur de compilation . Utilisation incorrect du mot Me"

  2. #2
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 596
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 596
    Points : 281 920
    Points
    281 920
    Par défaut
    Bonjour,

    le moyen le plus simple pour éviter les doublons est de définir dans ta table que les doublons sont interdits.

    Y a-t-il une (bonne) raison pour faire autrement ?

  3. #3
    Membre régulier Avatar de zoopsys
    Homme Profil pro
    Inscrit en
    Août 2008
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 68
    Points : 80
    Points
    80
    Par défaut
    C'est ce qu'on se tue à lui dire :
    http://www.developpez.net/forums/d12...requete-ajout/

    Facteur, comme te l'as précisé tee_grandbois, tu ne peux pas ajouter de clefs primaire sur ta table car elle contient déjà des doublons.
    Il faut donc d'abord que tu supprimes ces doublons et ensuite tu pourras ajouter des clefs primaires.

    Mais si tu veux quand même faire plus compliquer :
    - tu exécutes une requête sélection avec la date dans la clause Where
    - et si elle te remonte une ligne alors tu n’exécutes pas la requête d'ajout.

  4. #4
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 596
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 596
    Points : 281 920
    Points
    281 920
    Par défaut
    Merci à zoopsys pour l'info

    Citation Envoyé par facteur Voir le message
    il est vrai que mettre le champ [date] est la meilleur façon de ne pas avoir de doublon.
    Mais lorsque j'eesaie de mettre la clef primaire sur ce champ , j'ai un message d'erreur :
    "Modifications non effectuées : risque de doublons dans champ index ou relation interdisant les doublons. Modifier les données des champs contenant les doublons, enlever ou redéfinissez l'index pour permettre les doublons et recommencez"
    Ce message prouve que ta table est actuellement polluée : elle contient déjà des doublons, raison pour laquelle Access n’accepte pas la clé que tu proposes.
    Tu dois d’abord assainir ta table.
    Pour autant que ta table s’appelle « statistique_bureaux » et que la colonne susceptible de doublons s’appelle « jour », l’exécution de la requête qui suit va te lister les cas litigieux :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    SELECT statistique_bureaux.*
    FROM statistique_bureaux
    WHERE (((statistique_bureaux.Jour) In (SELECT statistique_bureaux.Jour FROM statistique_bureaux GROUP BY statistique_bureaux.Jour HAVING (((Sum(1))<>1));)));
    Supprime d’abord les doublons actuels et ensuite définis « jour » en tant que clé primaire.

    N’oublie pas de marquer cette discussion et celle-ci.

  5. #5
    Membre actif
    Inscrit en
    Avril 2007
    Messages
    1 241
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 1 241
    Points : 213
    Points
    213
    Par défaut
    Bonjour Messieurs,

    Je me suis peut etre mal exprimée dans ma demande.
    Effectivement, au début, je voulais inserer la cléf primaire sur mon champ "jour". Mais je me suis rendu compte que ce champ ne pouvait pas etre une clef primaire car la même date revenait plusieurs fois.
    Mais ce n'est pas un doublon : ma table regroupe des données statistiques pour plusieurs bureaux et par journée.

    C'est pourquoi, je me suis retournée vers la création d'une macro qui m'avertirait que je suis en train de vouloir enregistrer des données déja insérées dans ma table.

    Sur un forum, j'ai trouvé cette discussion :
    "si le champ [jour] du dernier enregistrement de la table contient la même
    journée que ce que la requête se prépare à copier alors on stoppe la requete sinon elle s'éxécute ..


    Cette macro était la suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    Sub doublon()
     If Me.jour = DMax("[jour]", "T_statistique_bureaux") Then  'test prend la plus grande valeur du champ [jour] de la table de T_statistiques_bureaux
    MsgBox " c'est déjà fait"
    Else
    DoCmd.OpenQuery "R_statistique_bureaux"
    End If
    End Sub
    mais cette macro bug...

  6. #6
    Rédacteur/Modérateur

    Avatar de ClaudeLELOUP
    Homme Profil pro
    Chercheur de loisirs (ayant trouvé tous les jours !)
    Inscrit en
    Novembre 2006
    Messages
    20 596
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 79
    Localisation : Belgique

    Informations professionnelles :
    Activité : Chercheur de loisirs (ayant trouvé tous les jours !)
    Secteur : Finance

    Informations forums :
    Inscription : Novembre 2006
    Messages : 20 596
    Points : 281 920
    Points
    281 920
    Par défaut
    Bonjour,

    Les données du problème ont changé mais la solution reste la même : il faut définir une clé (ou à tout le moins un index, sans doublon) sur la combinaison de colonnes qui doit être unique. Ce sera donc une clé composite (composée de plusieurs colonnes).

    Veux-tu poster la liste des champs de ta table et indiquer ceux dont la combinaison doit être unique.

  7. #7
    Membre actif
    Inscrit en
    Avril 2007
    Messages
    1 241
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 1 241
    Points : 213
    Points
    213
    Par défaut
    Bonjour ClaudeLELOUP,

    je reviens vers toi concerant la mise en place d'un programme qui me permettrait d'empecher une requete ajout d'inserer des données déjà existante dans une table.
    J'avais mis de coté cette problèmatique pour m'occuper d'autre tache..



    Pour résumé,
    J'ai crée ce code pour eviter que ma requete ajout puisse enregistrer des données déja présente dans la table.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    Function Maj()
    Dim Query As String
     
    If Me.Date = DMax("[date]", "T_compteur injection") Then
    MsgBox "requete déjà effectuée"
    Else
    DoCmd.OpenQuery "R_compteur injection"
    End If
     
    End Function
    Un message d'erreur apparait dans ce code :
    "erreur de compilation . Utilisation incorrect du mot Me"

  8. #8
    Membre actif
    Inscrit en
    Avril 2007
    Messages
    1 241
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 1 241
    Points : 213
    Points
    213
    Par défaut
    oups.. j'ai envoyé un peu trop rapidement la discussion avant que la finisse..

    Dans les discussions précédentes, tu parlais de cléfs primaire.
    dans les forum où j 'ai pu trouver ce code, il ne parle pas de clefs primaires.
    je suis un peu perdu..

  9. #9
    Membre actif
    Inscrit en
    Avril 2007
    Messages
    1 241
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 1 241
    Points : 213
    Points
    213
    Par défaut
    Une petite question :
    dans un code vba access, peut ton utiliser "Me" qui fait appel à un champ d'une requete ?

  10. #10
    Membre régulier Avatar de zoopsys
    Homme Profil pro
    Inscrit en
    Août 2008
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 68
    Points : 80
    Points
    80
    Par défaut
    Citation Envoyé par facteur Voir le message
    Une petite question :
    dans un code vba access, peut ton utiliser "Me" qui fait appel à un champ d'une requete ?
    On utilise Me. pour appeler un objet du formulaire courant (dans le code VBA du formulaire et pas dans une fonction comme tu l'as fait) pas pour appeler le champ d'une requete.

  11. #11
    Membre actif
    Inscrit en
    Avril 2007
    Messages
    1 241
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 1 241
    Points : 213
    Points
    213
    Par défaut
    Bonour zoopsys
    Alors comment appeler le champ [date] d'une requete ?

  12. #12
    Membre régulier Avatar de zoopsys
    Homme Profil pro
    Inscrit en
    Août 2008
    Messages
    68
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 68
    Points : 80
    Points
    80
    Par défaut
    Citation Envoyé par facteur Voir le message
    Bonour zoopsys
    Alors comment appeler le champ [date] d'une requete ?
    euh...
    en fait je ne comprends pas "Me.Date = DMax("[date]", "T_compteur injection")"

    tu essayes de comparer la date max de T_compteur injection (au passage évite les espaces dans le nom des objets) avec quoi ? pour toi c'est quoi Me.Date ?

    tu ne pourrais pas comparer la date max avec la date du jour ?

  13. #13
    Membre actif
    Inscrit en
    Avril 2007
    Messages
    1 241
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 1 241
    Points : 213
    Points
    213
    Par défaut
    Bonjour zoopsys

    Dans la ligne de code "Me.Date = DMax("[date]", "T_compteur injection")"

    "Date" correspond au champ "date" de ma requete ajout "R_compteur injection"

    Ainsi, lorsque j'écris "Me.Date = DMax("[date]", "T_compteur injection")", j'essaie de comparer la date de ma requete ajout avec la derniere date de ma table "T_compteur injection".

  14. #14
    Responsable
    Office & Excel


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 128
    Points : 55 940
    Points
    55 940
    Billets dans le blog
    131
    Par défaut
    Salut.

    1. C'est une très mauvaise idée de donner Date comme nom de colonne (et pas de champ!) à une table. Access te prévient de cela lorsque tu essaies de créer une colonne Date


    Tu dois donc renommer cette colonne si tu veux éviter de futurs ennuis.



    2. La SEULE façon d'éviter des doublons est de placer la contrainte sur la base de données, car cette contrainte s'imposera à tout "client" de la table. Toi, en VBA, tu la places sur l'interface, ce qui fait qu'elle ne s'applique que lors d'une manipulation qui appelle ta procédure de contrôle.

    Donc, comme te l'ont précisé Claude et zoopsys, tu dois placer :
    • soit une clé primaire multicolonne, automatiquement unique (solution non adapté dans ce cas) ;
    • soit un index multicolonne, en n'oubliant pas de mentionner l'unicité de l'index.


    et éventuellement gérer par vba l'erreur rencontrée sur le formulaire, via l'événement SurErreur (Form_Error en VBA)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Private Sub Form_Error(DataErr As Integer, Response As Integer)
     
    End Sub
    Voici une illustration de la création d'un index multicolonne

  15. #15
    Membre actif
    Inscrit en
    Avril 2007
    Messages
    1 241
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 1 241
    Points : 213
    Points
    213
    Par défaut
    Bonjour Pierre,

    J'ai suivi tes conseils ainsi que celles de Claude et zoopsys:

    1) J'ai repris ma table "T_compteur injection" et j 'ai changé l'intitulé "date" par "journée.
    2) J'ai nettoyé la table pour supprimer les doublons.
    3) J'ai ensuite crée une clé primaire multicolonne( sur 2 colonnes ) : l'une sur le champ "Displayname" et la deuxième sur le champ "CounterTimeStamp".

    Et cela fonctionne trés bien :
    lorsque j'exécute le même requete ajout une deuxième fois, j'ai un message d'erreur qui apparait

    "Microsoft office ne peut pas ajouter tous les enregistrements de la requete Ajout.
    Microsft office Access a atttribué la valleur Null à 0 champs à la suite d'une erreur de la conversion de type, 10603 enregistrement n'ont pas été ajoutés à la table à la suite de violation de clé, 0 enregistrements à la suite de violation de verrou.......
    Voulez vous-vous exécutez tout de même cette requete action ?
    Cliquer sur Oui pour ignorer la ou les erreurs et éxécuter la requete
    ..."


    Pierre, serait il possible qu'à la place de ce message un peu lourd à digirer , j'ai un message personnel du type :
    "Enregistrement déja présent sur la table
    Voulez vous-vous exécutez tout de même cette requete action ?
    Cliquer sur Oui éxécuter la requete
    Cliquer sur Non stopper la requeter la requete
    "

  16. #16
    Responsable
    Office & Excel


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 128
    Points : 55 940
    Points
    55 940
    Billets dans le blog
    131
    Par défaut
    Comme je le précisais dans mon premier message, c'est l'événement OnError qui permet cela.

    Dans le module du formulaire, ajoute le code suivant, en adaptant le message à ta sauce
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    Private Sub Form_Error(DataErr As Integer, Response As Integer)
        Response = acDataErrContinue
        If DataErr = 3022 Then MsgBox "Clé primaire en double"
    End Sub

  17. #17
    Membre actif
    Inscrit en
    Avril 2007
    Messages
    1 241
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 1 241
    Points : 213
    Points
    213
    Par défaut
    Pierre,
    Lorsque tu dis " Dans le module du formulaire, ajoute le code suivant, en adaptant le message à ta sauce",

    Je n'ai pas de formulaire, les risques de doublons sont dans une table et non un formulaire..

  18. #18
    Membre actif
    Inscrit en
    Avril 2007
    Messages
    1 241
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 1 241
    Points : 213
    Points
    213
    Par défaut
    Pierre,
    suis je contraint de créer un formulaire à partir de la table pour pouvoir inserer un message d'erreur personnalisé ?

  19. #19
    Responsable
    Office & Excel


    Homme Profil pro
    Formateur et développeur chez EXCELLEZ.net
    Inscrit en
    Novembre 2003
    Messages
    19 128
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 57
    Localisation : Belgique

    Informations professionnelles :
    Activité : Formateur et développeur chez EXCELLEZ.net
    Secteur : Enseignement

    Informations forums :
    Inscription : Novembre 2003
    Messages : 19 128
    Points : 55 940
    Points
    55 940
    Billets dans le blog
    131
    Par défaut
    Oui.

    Tu dois distinguer deux aspects différents d'Access...

    D'une part, tu as le moteur de données. C'est lui qui gère la contrainte d'intégrité. Si la contrainte n'est pas respectée, il se contente d'envoyer un numéro d'erreur et c'est l'applicatif qui le gère.

    Ton applicatif, c'est le formulaire, car tu ne sais pas placer du code sur les tables.

    C'est le formulaire qui va recevoir l'erreur envoyée par le moteur de données et qui va le gérer au sein de la procédure Form_Error.

    Note aussi que, sauf application personnelle et légère, il n'est jamais intéressant de saisir en direct dans les tables ou requêtes, les formulaires étant justement là pour gérer l'ergonomie de ton application.

  20. #20
    Membre actif
    Inscrit en
    Avril 2007
    Messages
    1 241
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 1 241
    Points : 213
    Points
    213
    Par défaut
    merci pour ces infos Pierre,

    Dans mon cas personnel, la création de formulaire n'est pas primordial. car je transfere ces tables en version Excel à mes collegues de travail.
    Donc je me dis que laisser le message d'erreur tel qu 'il n'est pas si dramatique que cela.
    Merci encore pour ton aide Pierre.

Discussions similaires

  1. [AC-2000] Suppression de premières lignes des doublons dans une requête
    Par jyoboue2008 dans le forum Access
    Réponses: 3
    Dernier message: 17/03/2014, 18h55
  2. supprimer des donnees dans une base de données via des checkbox dans un tableau
    Par nourchéne dans le forum PHP & Base de données
    Réponses: 11
    Dernier message: 03/04/2013, 18h01
  3. [AC-2003] éviter les doublons dans une requête ajout
    Par facteur dans le forum VBA Access
    Réponses: 12
    Dernier message: 22/09/2012, 00h17
  4. Réponses: 3
    Dernier message: 19/03/2009, 01h07
  5. ajouter des données dans une requête htttp en js
    Par jeromejanson dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 18/10/2005, 15h34

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo