Ajouter un élément dans une liste déroulante – Episode 2

J’ai une liste déroulante basée sur une table. Je voudrais ajouter des données à la table, donc à la liste (par exemple : des personnes, des produits). Comment faire ?

Scénario

Dans l’article Ajouter un élément dans une liste déroulante, j’avais déjà traité une première technique proposée par Access, technique qui utilise l’événement VBA NotInList (Sur absence dans liste). Cette méthode a des avantages et des inconvénients :

  • Avantage : l’élément est ajouté directement dans la liste déroulante, et dans la table sous-jacente. L’opération est transparente pour l’utilisateur, pas de manipulation complexe.
  • Inconvénient : la technique ne permet d’alimenter qu’un seul champ de table (la valeur qui a été tapée par l’utilisateur dans la liste déroulante). En conditions réelles, il y a souvent plus d’une valeur à renseigner.

Dans ce nouvel article, nous allons voir une méthode pour résoudre cet inconvénient, quelle que soit la version d’Access, et quel que soit le scénario. Les Access 2007 et suivants proposent une variante supplémentaire, qui repose sur le même principe mais qui simplifie encore les choses ; attendez le prochain article !

Au départ, je dispose d’une table simple :

tbl_personnes.png

J’ai aussi préparé un formulaire qui contient une liste déroulante (ComboBox). Quelques infos sur cette liste, que vous pouvez construire à l’aide de l’Assistant Liste déroulante :

  • Elle est construite « sur » la table des personnes.
  • Elle reprend les 3 premiers champs de la table Personnes, mais le champ est masqué.
  • Elle est triée sur le nom puis le prénom.
  • Elle s’appelle cmbPersonnes (propriété Nom).

Formulaire

On va construire ensemble le bouton Ajouter (nommé techniquement btnAjouterPersonne) qui va justement permettre… d’ajouter une personne dans la liste.

Le formulaire

Dans Access, la logique veut que, pour alimenter une table, vous prépariez un formulaire dédié. C’est sur ce formulaire que l’opérateur aura tous les champs de saisie, et que vous pourrez gérer la validation des données.

Par conséquent, vous devez dans un premier temps construire un formulaire pour la saisie des personnes, formulaire basé sur la table tbl Personnes donnée plus haut. En voici un exemple :

Formulaire de saisie des personnes

Le bouton

Vous avez donc maintenant 2 formulaires dans votre base :

  • le formulaire avec la liste déroulante de personnes ;
  • le formulaire de consultation et de mise à jour des personnes.
  1. Rouvrez le premier formulaire (en mode Création), c’est lui qui doit recevoir notre bouton « Ajouter« .
  2. Cliquez sur l’icône Bouton du ruban (onglet Création). Pour les versions d’Access plus anciennes, pas de ruban, mais l’icône existe également.
  3. Cliquez sur le fond du formulaire pour placer votre bouton. Ceci a en principe pour effet de démarrer l’Assistant Bouton de commande.
  4. Choisissez la catégorie Opérations sur formulaire, et l’action Ouvrir un formulaire. Cliquez sur le bouton Suivant.
    bouton_ouvrir_formulaire.png
  5. Choisissez ensuite le formulaire à ouvrir (dans mon cas : frm Personnes ; celui où la saisie des personnes devra se faire). Cliquez encore sur Suivant.
  6. Conservez l’option proposée : « Ouvrir le formulaire et afficher tous les enregistrements« , et validez par Suivant.
  7. Choisissez ensuite un texte ou une image pour votre bouton. Dans mon cas, j’ai préféré un texte.
    bouton_ouvrir_texte.png
  8. Enfin, donnez un nom à votre bouton. Il s’agit du nom technique, utilisé notamment côté programmation : btnAjouterPersonne.

Normalement, à ce stade, si vous testez votre formulaire, le bouton ouvre bien le formulaire de saisie de personnes. Mais il reste 2 défauts à régler :

  1. Comme tout formulaire Access, le formulaire de personnes s’ouvre sur la première ligne de table saisie (la première personne). Dans notre cas, il serait plus pratique de se positionner sur une fiche vierge.
  2. Si vous saisissez une nouvelle personne, puis que vous fermez le formulaire de saisie, la liste déroulante ne contient pas cette personne. Il va falloir aider un peu Access pour que cela se fasse automatiquement !

Améliorer l’ouverture du formulaire de saisie

On a donc décidé que le formulaire de saisie se positionnerait sur un enregistrement vide, à l’ouverture. Ceci peut se régler de plusieurs manières. Ici, on va le faire par le code du bouton.

Si vous êtes sur un Access récent (2010 ou plus), ce code est en fait une macro :

  1. Faites apparaître les propriétés du bouton, onglet Événement.
  2. Cliquez sur les points de suspension à droite de l’événement Sur clic (donc à droite de [Macro incorporée]).
  3. Modifiez la propriété Mode Données (qui doit être vide pour l’instant), en y mettant la valeur Ajout.
    macro_ouvrir_formulaire.png
  4. Fermez la fenêtre de macro, en acceptant les changements.

Si vous avez un Access plus ancien, le code du bouton est écrit en VBA. Dans ce cas :

  1. Reprenez les étapes 1 et 2 précédentes, sachant que la mention [Macro incorporée] sera remplacée par [Procédure événementielle].
  2. Modifiez la ligne DoCmd.OpenForm... comme ceci :

Repassez en mode Formulaire, et cliquez sur le bouton Ajouter. Vérifiez que ce formulaire est bien vide à l’ouverture.

Info
Par contre, lorsque vous ouvrez le formulaire frm Personnes directement (par un double-clic), on est toujours positionné sur le premier enregistrement (c’est normal également : c’est le bouton qui modifie le comportement à l’ouverture).

Actualiser la liste déroulante

L’aller fonctionne (ouvrir le formulaire de saisie). Il nous reste à régler le retour : l’actualisation de la liste déroulante :

  1. Ouvrez le premier formulaire en mode Création.
  2. Faites apparaître ses propriétés.
    event_activate.png
  3. Vérifiez que la sélection en cours est bien Formulaire (cf. repère 1 sur l’illustration).
  4. Activez l’onglet Événement (repère 2 sur l’illustration).
  5. Réglez l’événement sur Procédure événementielle (repère 3).
  6. Cliquez sur les points de suspension (repère 4).
  7. Dans le code Visual Basic, tapez ceci (rappelez-vous que cmbPersonnes est le nom de la liste déroulante)  :

Tester !

  1. Passez en mode Formulaire.
  2. Cliquez sur le bouton Ajouter.
  3. Créez une personne (et validez-la, bien sûr : tant que la saisie n’est pas terminée, les données du formulaire ne sont pas transférées dans la table, et elle ne peuvent donc pas s’afficher dans la liste déroulante… C’est normal).
  4. Fermez le formulaire de saisie (ou revenez simplement sur le formulaire initial).
  5. Déroulez la liste : les nouvelles personnes y figurent. Pratique, non ?

Vous aimerez aussi...

24 réponses

  1. Paul dit :

    Lu en diagonale
    Si j’ai bien tout compris, il faut appuyer sur un bouton « ajouter » pour… ajouter.
    Et si l’entrée existe déjà ? bon, mettons que les doublons soient gérés, ça fait une manip de plus, v’là tout.
    Mais l’utilisateur doit connaître par coeur chaque item de chaque table pour savoir quand ajouter ou non…
    J’ai sûrement pas tout compris !

    • Hervé Inisan dit :

      Cette manipulation est intéressante dans une base plus complète, bien sûr. Par exemple :
      1. J’ai une table Clients, en relation 1:n avec une table Factures.
      2. J’ai un formulaire Factures que j’alimente.
      3. Sur ce formulaire, une liste de clients qui permet de relier la facture au client.
      4. J’ai un nouveau client qui ne figure pas dans la liste déroulante. C’est ici qu’on va utiliser le bouton Ajouter (pas pour ajouter une facture, mais pour ajouter un client et actualiser en même temps dans la liste déroulante).
      Ça permet de ne pas quitter la saisie principale (Facture), mais de créer quand même des données en amont (Client).

  2. bisko dit :

    Bonjour Hervé

    Tout d’abord merci de bien vouloir m’accompagner dans mes recherches car tu dois avoir d’autres choses plus urgentes à faire. Je suis un papy qui s’essaie à Access et qui compte y arriver. J’ai donc tout repris à zéro.
    Mon problème est simple. J’ai 3 tables : « Clients (N°(auto), Nom, Prenom et Adresse)», « Medicaments (NumMed(auto), Code, Nom, PrixHT) « et « Délivrés (N°(auto),NumClient, DMedicament,Quantite)»
    J’ai créé un formulaire avec sous-formulaire basé sur la table « Clients » pour le premier et la table « Délivrés » pour le second. Le sous-formualire se présente sous la forme d’un cadre avec plusieurs lignes situées les unes à la suite des autres puisque les deux formulaires sont liés par N° de « Clients » et NumClient de « Délivrés ».
    Je recherche un client dans une zone de liste déroulante indépendante et si ce client existe, il apparaît normalement dans les contrôles dépendants « nom, prenom, adresse » du formulaire principal. S’il est inexistant, je le créé grâce à ton conseil via un bouton « Ajouter client » et le client apparaît dans la liste déroulante. Toutefois, je dois refermer le formulaire puis le réouvrir pour que la liste se mette à jour et remplisse les contrôles dépendants « nom, prenom, adresse » du formulaire principal. C’est une bidouille, je l’admets car pas très académique.
    Dans le sous-formulaire, je sélectionne un produit grâce à un contrôle (liste déroulante) dont la source est « IDMedicament » et dont le contenu est un « SELECT Medicaments.NumMed, Medicaments.NOM, Medicaments.CODE, Medicaments.PRIXHT FROM Medicaments ORDER BY Medicaments.NOM;
    Lorsque je recherche un médicament, celui-ci s’affiche dès lors qu’il existe. Par contre, s’il est inexistant, je le créé via le bouton « Ajouter médicament ». Lorsque je reviens sur le sous-formulaire et que je recherche le médicament nouvellement créé avec la liste déroulante du sous-formulaire, j’obtiens la même réponse « Produit inexistant ». Je bidouille alors en choisissant un médicament existant, ce qui active en quelque sorte le liste déroulante puis je recherche de nouveau mon médicament nouvellement créé et Miracle … il apparaît. Tout cela me permet d’affecter à chaque client une liste de médicaments qui lui sont délivrés.
    J’avoue humblement que je fais sûrement partie des n….ls en access mais j’ai vraiment envie de comprendre.
    Merci encore

    • Hervé Inisan dit :

      Dans les 2 listes, le problème a l’air d’être un problème d’actualisation : les données d’une liste ne sont lues qu’à l’ouverture du formulaire. Si les données évoluent parallèlement (ce qui est le cas ici), elles ne s’affichent pas dans la liste. La solution est dans le paragraphe « Actualiser la liste déroulante » de cet article.
      Attention : la 2ème liste se trouve dans un sous-formule, si j’ai suivi ? La syntaxe pour la réactualiser sera donc différente (voir cet autre article).

  3. bisko dit :

    Merci Hervé,

    J’ai fait un « requery » sur chaque champ indépendant selon tes conseils et les valeurs des champs du client nouvellement crée s’affichent. Par contre lorsque je saisis dans le sous formulaire, les produits qu’il achète, rien ne se passe. Le formulaire et le sous formulaire sont pourtant liés par un champ père et fils. Grâce à tes conseils avisés, j’ai réussi à résoudre ce problème après deux semaines de recherche infructueuse. Il me reste cette dernière étape à franchir … Merci beaucoup

  4. bisko dit :

    Merci Hervé,
    Le contact que j’ai créé est bien visible dans la liste déroulante lorsque je reviens sur le premier formulaire. Toutefois les champs indépendants qui figurent sur le formulaire et qui sont destinés à recevoir les différentes valeurs de la liste déroulante à l’aide de l’instruction column(n) restent bloqués sur les valeurs des champs du premier enregistrement de la table. Par contre, si je choisis un contact déjà existant, tout fonctionne. Pour le contact nouvellement créé, je suis obligé de fermer le formulaire principal puis de l’ouvrir afin de voir ma liste fonctionner normalement. Je suis vraiment bloqué sans pouvoir continuer plus en avant. Grande déception

    • Hervé Inisan dit :

      D’accord, on progresse. 😉 En fait, il n’y a pas de problème sur l’actualisation de la liste. Ça serait plutôt un problème d’actualisation des champs indépendants.
      Qu’est-ce qui se passe si, une fois de retour sur le formulaire, tu sélectionnes le contact dans la liste ? (les champs indépendants suivent, ou pas ?)
      Deux pistes sinon :

      1. Il faut que la liste déroulante ne soit elle-même pas indépendante.
      2. Si ça ne suffit pas : en traitant chaque champ indépendant comme la liste, ça devrait passer. Du genre :
  5. bisko dit :

    Bonsoir,
    J’ai créé le second formulaire (pour saisir mon contact avec nom, prénom, adresse) et lorsque je reviens sur le premier formulaire, me liste déroulante ne se met jamais à jour. Pourquoi ?
    Merci d’avance à tous ceux qui voudraient me dépanner. Cela fait deux semaines que je me casse la tête

    • Hervé Inisan dit :

      Est-ce que tu as suivi le point « Actualiser la liste déroulante » ?
      Si oui, adapte le code de cette façon, et teste si un message s’affiche lors du retour sur le formulaire. Ça permettra de vérifier que le retour est bien pris en compte :

  6. Hervé Inisan dit :

    Brutus > Ça ne marche pas avec l’autre méthode du fait que le formulaire est ouvert en mode « Boîte de dialogue » (acDialog). Dans ce cas, la boîte de dialogue bloque l’exécution du code VBA appelant (donc le Forms![...] = ... n’est pas traité tout de suite. Ensuite, lorsque le formulaire est fermé, l’exécution reprend, la ligne de VBA peut s’exécuter mais le formulaire n’existe plus (d’où le message d’erreur).

  7. Brutus dit :

    En fait, pour faire apparaître automatiquement dans un 2e formulaire le nom recherché dans la liste déroulante d’un premier formulaire (et qui n’existe pas, donc ça déclenche l’événement NotInList), il faut insérer ce code dans le 2e formulaire :

    Private Sub Form_Load ()
    If Not IsNull(Me.OpenArgs) Then
    Me![Nom] = Me.OpenArgs
    End If
    End Sub

  8. Brutus dit :

    Merci Hervé. Malgré tout, ça ne fonctionne pas.
    Dans le formulaire 1, appelé Lexique, j’ai ce code :

    Option Compare Database

    Private Sub Form_Activate()
    On Error Resume Next
    Me.Modifiable0.Requery
    End Sub

    Private Sub Modifiable0_NotInList(NewData As String, Response As Integer)
    If MsgBox(« Voulez-vous ajouter  » & NewData &  » au Dictionnaire ? », _
    vbYesNo + vbQuestion + vbDefaultButton2, « Ajout ») = vbYes Then

    DoCmd.OpenForm « Termes », , , , acFormAdd, acDialog, NewData
    Forms![Termes]![Terme] = NewData
    Response = acDataErrAdded
    Else
    Response = acDataErrContinue
    Modifiable0.Undo
    End If
    End Sub

    la valeur NewData est bien enregistrée (véifiée par un MsgBox à l’ouverture du formulaire 2), mais la valeur n’apparaît pas dans son champ, et à l’enregistrement du formulaire 2 j’ai un message d’erreur 2450, me disant que le formulaire « Termes » n’existe pas… alors que c’est lui qui est ouvert !
    Et le nouveau terme est enregistré dans ma base, avec le champ vide !

    Le code du formulaire 2, nommé Termes, est le suivant :

    Option Compare Database

    Private Sub Form_Open(cancel As Integer)
    ‘Test
    MsgBox Me.OpenArgs
    End Sub

    Private Sub Enregistrer_Click()
    DoCmd.RunCommand acCmdSaveRecord
    DoCmd.Close
    End Sub

    J’ai essayé de remplacer NewData par Me.OpenArgs, ça ne change rien.

    Auriez-vous une idée d’une solution pour passer et écrire ce NewData à sa place dans le 2e formulaire ? Merci.

  9. Hervé Inisan dit :

    Brutus > J’imagine qu’il y a un DoCmd.OpenForm dans l’événement NotInList. A vue de nez, il suffit d’ajouter après :

  10. Brutus dit :

    Bonjour,
    Super, cet exemple fonctionne bien, mais je voudrais faire plus. J’ai un événement not in list qui propose d’ouvrir le 2e formulaire, au lieu de cliquer sur « ajouter ». Je souhaiterais qu’un nom, recherché dans la liste déroulante mais qui n’y figure pas, apparaisse directement dans le 2e formulaire de saisie qui va s’ouvrir, et que je puisse saisir les autres infos concernant la personne (suite à l’événement not in list, le formulaire de saisie s’ouvre bien sur un nouvel enregistrement, mais le formulaire est complètement vierge, j’aimerais que la valeur – présente dans NewData et aussi dans un OpenArgs – soit automatiquement écrite dans mon champ « nom »). Est-ce possible ? Merci.

  11. greg0uld dit :

    Hervé Inisan => Merci Hervé pour ta réponse, je me suis débrouillé autrement afin de rafraîchir mes listes. J’ai créer un bouton de rafraîchissement par combobox avec le code VBA correspondant pour chacune d’elle. Du coup, sa fonctionne parfaitement.
    Merci encore,

    Bonne continuation!

  12. Hervé Inisan dit :

    cyrielle > Ça peut se faire de différentes manières, dont une requête UNION. Un peu délicat à détailler dans un commentaire, mais si j’ai un peu de temps, j’essaierai de poster un article sur le sujet…

  13. Hervé Inisan dit :

    greg0uld > Est-ce que les autres listes existent bien sur le formulaire (et avec ces noms précis) ?

    Au cas où, l’idée serait de supprimer la ligne On Error Resume Next, pour voir où ça peut casser (et de la remettre ensuite).

  14. greg0uld dit :

    Bonjour,

    Ce tuto est super il m’a permis de bien avancer dans mon projet. J’ai cependant une petite question concernant l’actualisation de la combobox. Dans mon formulaire principal d’ajout, j’ai plusieurs combobox à actualiser. Mon code a donc cette forme :
    Private Sub Form_Activate()
    On Error Resume Next
    cboCategory.Requery
    cboTechno.Requery
    cboVoltage.Requery
    cboCapacity.Requery
    End Sub
    Ce code me permet d’actualiser la première liste à sa voir cboCategory mais pas les autres… Que faire ? Erreur dans le code ? (Je suis novice en VBA…)
    Aidez moi svp,
    Merci

  15. cyrielle dit :

    Bonjour,

    Ici, vous proposez une méthode pour ajouter un élementà la liste. Mais comment fait t on pour ajouter  » aucun filtre  » à la liste déroulante ?

    Merci par avance

  16. Hervé Inisan dit :

    Guillaume > Ça veut dire que le bouton « Ajouter » ne fonctionne plus à partir de la deuxième fois ? (plus d’effet ?)

  17. Guillaume dit :

    Bonjour,

    Je d’utiliser cette méthode pour ajouter une personne à une liste déroulante, cela marche parfaitement. Cependant, après avoir ré-ouvert ma base, je ne peux plus ajouter de nouvel utilisateur, seulement modifier la premiere ligne de ma base…
    Une idée d’où peut venir le problème ? (niveau access débutant)

    Merci par avance,

  18. Hervé Inisan dit :

    az0te > Et demain, une petite variante pour Access 2007 et +. Mais l’essentiel est ici. 🙂

  19. az0te dit :

    Merci beaucoup pour cette article!! il met vraiment d’une grande aide. Et surtout ayant poser la question que hier avoir un post si complet déjà maintenant c’est incroyable !!

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *