Utiliser la fonction DLookup

A quoi sert la fonction DLookup ? Comment l’utiliser en Visual Basic ?

Présentation de DLookup

DLookup (ou RechDom en français) permet de rechercher une valeur unique dans une table : cette valeur est celle d’un champ précis, pour une ligne précise de la table. Même si elle n’est pas ultra-performante, DLookup a quelques avantages :

  • Elle nécessite peu de code (une formule d’une ligne suffit).
  • En tant que fonction VBA, elle peut s’employer dans des contextes hors programmation : un champ calculé de requête, ou une zone de texte de formulaire ou d’état par exemple. Elle peut bien sûr être exploitée en VBA si nécessaire…

Utilisation de DLookup

La fonction DLookup reçoit 3 paramètres, dont le dernier est optionnel :

  • En premier : le nom du champ dont on cherche la valeur. Entre guillemets, et de préférence également entre crochets. Par exemple : "[Prix HT]"
  • En second : le nom de la table ou de la requête dans laquelle on fait la recherche (sans crochets). Par exemple : "tbl Produits"
  • En troisième : un critère facultatif qui permettra de localiser un enregistrement précis. Ce critère est l’équivalent d’une clause WHERE en SQL, sans le mot-clef WHERE. Par exemple : "[Numéro Produit] = 1234"

Quelques exemples

  • Extraire le premier nom de client trouvé (la variable strNomClient est de type String) :
    strNomClient = DLookup("[Nom Client]", "tblClients")
  • Extraire le prix du produit dont la référence st 1234, de type Numérique :
    dblPrix = DLookup("[Prix]", "tblProduits", "[Référence] = 1234")
  • La même chose, avec une référence de type Texte :
    dblPrix = DLookup("[Prix]", "tblProduits", "[Référence] = 'JB007'")

Combiner les critères

Les critères peuvent être combinés, dans le 3ème argument de DLookup(). Dans ce cas, ils sont séparés par le mot AND (Ou) ou le mot  OR (Ou). Par exemple :

  • Extraire le nom du premier client dont le nom commence par I et le prénom par H :
    strNom = DLookup("[Nom Client]", "tblClients", _
    "[Nom Client] LIKE 'I*' AND [Prénom Client] LIKE 'H*'")
Attention
Si vous écrivez un DLookup dans une requête ou sur un formulaire, les mots-clefs AND et OR doivent quand même être écrits en anglais, même si les objets graphiques sont en français, et même si le nom de la fonction devient RechDom() après coup !

Gérer les valeurs Null

Il se peut qu’aucune valeur ne soit trouvée dans la table, parce qu’aucun enregistrement ne répond à vos critères, notamment. Dans ce cas, DLookup renvoie la valeur Null. Ca veut dire que ce bout de code échoue :

parce qu’une variable de type Double ne peut pas recevoir de valeur Null. Aïe. Dans ce cas, vous pouvez :

  • Tester le DLookup avec la fonction IsNull() avant de l’affecter à dblPrix
  • Forcer une conversion de la valeur Null en 0, de façon à l’affecter directement à dblPrix. Dans ce 2ème cas, le code devient :

Utiliser des expressions dans DLookup

En fait, le premier argument de DLookup() peut également être une expression combinant plusieurs champs de table, ou faisant appel à des fonctions VBA. Voici par exemple comment extraire le nom et le prénom d’un client, en les concaténant et en les séparant par un espace (seul le premier client trouvé est extrait) :

Ne vaut-il pas mieux utiliser les Recordsets ?

Oui et non (z’êtes bien avancés, avec ça !).

S’il s’agit vraiment de récupérer une seule valeur, DLookup sera plus courte à écrire. Voici par exemple la formule pour récupérer le champ Prix d’une table tblProduits, pour un produit dont la référence (de type Texte) est JB007 :

Et voici strictement la même chose avec un Recordset DAO :

Pour récupérer un seul champ, le code du Recordset est un peu long. Mais s’il faut lire plusieurs valeurs, les performances seront meilleures qu’avec une suite de DLookup. Tout dépend donc de l’usage !

Vous aimerez aussi...

67 réponses

  1. Felix Poussin dit :

    Bjr a tous
    Voici mon probleme:
    J’ai une table « TableEmeteur » avec un seul enregistrement
    Comprenat un champ « nom du beneficiaire »
    En cliquant sur « procedure evenementielle » je veux que ma fonction aille recuperer le nom du beneficiaire afin de l’inserer dans le fichier créé.
    Mais au lieu de cela je recoit le message :
    « Impossible de trouver le champ Impossible de trouver le champ ‘I’ auquel il est fait reference dans votre expression. »
    Help please

    Voici ma fonction :

    Private Sub Commande4_Click()
    On Error GoTo Err_Commande4_Click

    If Len(Dir(« c:\SERFADIN\SALARYSERFADIN.txt »)) > 0 Then
    ‘File exists so rename

    Set db = CurrentDb
    Me.[Nom du Beneficiaire] = DLookup(« [Nom du Beneficiaire] », « TableEmeteur »)

    FileCopy « c:\SERFADIN\SALARYSERFADIN.txt « , « c:\SERFADIN\ » & Me.[Nom du Beneficiaire] & « – » & Format(Now, « ddmmyyyyhhnnss ») & « .txt »

    Kill « C:\SERFADIN\SALARYSERFADIN.txt  »

    MsgBox « File Created »
    Else
    ‘File does not exist – Unable to rename
    ‘MsgBox « File does not exist »
    DoCmd.Close acForm, « Bank »
    End If

    DoCmd.Close acForm, « Bank »
    DoCmd.Quit

    Exit_Commande4_Click:
    Exit Sub

    Err_Commande4_Click:
    MsgBox Err.Description
    Resume Exit_Commande4_Click

    End Sub

    • Hervé Inisan dit :

      Je ne vois pas de champ « I » dans le code.
      Par contre, quelques pistes :
      1. Si l’objectif est d’utiliser une valeur dans un nom de fichier, il n’est pas utile de stocker cette valeur dans un champ de formulaire. Je passerais plutôt par une variable. Ca donnerait quelque chose comme ça (je reprends seulement une partie du code, après le CurrentDb) :

      2. CurrentDb n’est pas utile ici (il ne sert pas dans le cas d’un DLookup()), et je vois pas la variable utilisée ailleurs.

  2. Saulin dit :

    Bonsoir,
    Je m’arrache les cheveux pour refaire quelque chose qui a du être créé des centaines de fois, à savoir une gestion sous VBA Access ‘ADO’ de la gestion des conditions de paiement. Je n’ai rien trouvé me permettant une base de départ. Auriez vous une idée pour que je ne me refasse pas toute la procédure ?
    Cordialement

  3. SODRE Kassoum dit :

    Bonjour Hervé!
    Pourquoi quand je met sur une requête ou un formulaire cette formule =DLookUp(« [Date] », »Temps ») Access me signale une erreur de syntaxe.
    Et même quand je copie une formule qui marche à ailleurs. Access me donne le même message.
    Doit on paramétrer d’abord la fonction DLookUp()?
    Aider moi je veux bien utiliser cette fonction.

    • Hervé Inisan dit :

      Il n’y a rien de particulier à paramétrer. Par contre, je vois que Dlookup() est utilisé dans un formulaire. Ça veut dire que le délimiteur doit être ; à la place de , (sur une machine française en tout cas). Du style :

      Après, il faut aussi que la base contienne une table ou une requête qui s’appelle « Temps », laquelle doit contenir un champ qui s’appelle « Date »), vu ce qui est écrit dans le DLookup().

  4. Arthur Diagne dit :

    Aidez moi j’ai créer une Base de donnée accès avec une table utilisateur (prénom et nom; userlogin; password; sécurité utilisateur: administrateur ou simple) j’ai une formulaire Utilisateur(Nom Utilisateur, Mot de Passe). Maintenant je veux que si on entre on met son nom utilisateur et mot de passe à verifier sur la table utilisateur et on pourra entrer dans le formulaire menu et affiche le nom d’utilisateur et sa securité utilisateur(administrateur ou simple) JE VEUX LE CODE
    Private Sub Commande1_Click()
    Dim Db As Database
    Dim Rs As Recordset
    Set Db = CurrentDb
    Set Rs = Db.OpenRecordset(« Utilisateur »)
    If IsNull(Me.TxtLoginId) Then
    MsgBox « Veuillez Entrer Votre Identifiant S.V.P. », vbInformation, « Identifiant »
    Me.TxtLoginId.SetFocus
    ElseIf IsNull(Me.TxtPassword) Then
    MsgBox « Veuillez Entrer Votre Mot de Passe S.V.P. », vbInformation, « Mot de Passe »
    Me.TxtPassword.SetFocus
    Else
    ‘process the job
    If Rs.Fields(« UserLogin »).Value = TxtLoginId.Value Then
    If Rs.Fields(« Password ») = TxtPassword.Value Then
    MsgBox « Identifiant et Mot de Passe sont correctes »
    TxtLoginId.Value = «  »
    TxtPassword.Value = «  »
    DoCmd.OpenForm « Menu »
    Me.Visible = False
    Else
    MsgBox « Identifiant et Mot de Passe sont Incorrectes », vbInformation, « ACCES AU MENU »
    End If
    End If
    End If

    End Sub

  5. FDK dit :

    Re-bonjour,

    J’ai une question complémentaire à vous poser. Sans vouloir abuser.

    Dans le recordset j’indique WHERE [RefPOL] = ‘POL0001′”,
    Cependant y-a-t-il moyen de demander qu’il retourne toutes les valeurs en lien avec la valeur sur laquelle on a cliqué de manière générique plutôt que d’indiquer une référence précise Car cela m’oblige à dupliquer le recordset sur toutes les valeurs séparément.

    Grand grand merci,

    • Hervé Inisan dit :

      Je suppose qu’on a récupéré POL0001 dans une variable de type String (strParametre). Dans ce cas, on peut écrire :

      Ouala !

  6. FDK dit :

    Bonjour,

    Tout d’abord un tout grand merci pour ces explications claires et concises.

    J’ai malgré tout un petit souci… J’ai crée une base de données comprenant 4 tables (politiques – process – procédures – opérations). Ces tables ont des relations de type plusieurs à plusieurs. Par conséquent j’ai crée 3 tables de jonction (JCTPolitiquesProcess – JCT ProcessProcédures – JCTProcéduresOpérations).

    J’ai ensuite crée 1 formulaire Politique auquel est lié un formulaire Process auquel est lié un formulaire Procédure auquel est lié un formulaire Opérations (à chaque fois sur double clic de la référence concernée).

    C’est là que le choses se compliquent. Lorsque je double cliquait sur une référence de Politique par exemple, Access me retournait toutes la liste de Process présentent dans la table Process et pas uniquement les process liés à la politique en question.

    La formule DLookup ne m’intéressant pas dans ce cas présent, j’ai intégré le recordset ci-dessous, mais il me retourne une erreur de type : Run time error 13 – type mismatch/

    Private Sub RefPOL_DblClick(Cancel As Integer)
    Dim dblRefPR As Single
    Dim rst As DAO.Recordset
    Set rst = CurrentDb.OpenRecordset( _
    « SELECT [RefPR] FROM [JCTPoliciesProcesses] WHERE [RefPOL] = ‘POL0001′ », _
    dbOpenSnapshot)
    dblRefPR = rst(« RefPR »)
    MsgBox « La RefPR est de » & dblRefPR
    rst.Close
    Set rst = Nothing

    End Sub

    Pouvez-vous me dire comment je dois rédiger ce code afin que cela fonctionne. Comme je suis novice dans le domaine je ne comprends pas toutes les subtilités du langage.

    Un tout grand merci d’avance

    • Hervé Inisan dit :

      RefPR est un champ de quel type ?
      J’ai l’impression qu’il s’agit d’un champ de type Texte, ce qui expliquerait le « Type mismatch ».
      Ceci veut dire qu’il faudrait plutôt déclarer la variable équivalente de cette manière :

      Et adapter plus bas :

      Vu le type d’extraction, un DLookup devrait suffire. Ça donnerait :

      • Hervé Inisan dit :

        En relisant les conditions : si la condition WHERE peut renvoyer plusieurs lignes :
        1. Effectivement, le DLookup() ne fera pas l’affaire.
        2. Le code VBA nécessitera une boucle pour parcourir le Recordset.
        3. … mais ça ne sera pas très pratique ergonomiquement (pour l’affichage, les mises à jour éventuelles).
        4. Au final, est-ce que la piste ne serait pas un sous-formulaire ? 😉

        • Fanny Demuynck dit :

          Merci pour votre réponse.

          Effectivement la condition where doit pouvoir renvoyer plusieurs lignes.
          Et ce serait plus logique que je fasse des sous formulaires vu que je descend à chaque fois d’un niveau.
          Comment puis-je faire un sous+formulaire de type datasheet à partir d’un formulaire qui lui aussi est de type datasheet?
          Lorsque j’aurais fait ces sous-formulaires, devrais-je encore utiliser un code VBA pour parcourir le recordset? Si oui, est-ce que je dois l’écrire de la façon suivante?:

          Dim strSQL As String
          strSQL = « SELECT [RefPR], [JCTPoliciesProcesses] WHERE [RefPol] = ‘ » & strParametre & « ‘ »

          J’espère ne pas abuser…
          En tout cas je vous remercie beaucoup.

          • Hervé Inisan dit :

            Un formulaire en mode Feuille de données (DataSheet) ne peut pas intégrer un autre formulaire (mais je ne pense pas que ce soit un inconvénient : ça ferait une interface graphique chargée). Par contre, on peut faire en sorte d’ouvrir un autre formulaire à partir du sous-formulaire Feuille de données.

            La représentation classique est :
            1. Un formule en mode Colonne simple (ou Formulaire unique).
            2. Un sous-formulaire en mode quelconque (DataSheet étant plus clair pour l’utilisateur).

            Dans le cas de formulaire/sous-formulaire, l’affichage est géré par Access, il n’y a pas besoin de Recordset.
            Il y aura peut-être une ligne de VBA pour afficher un autre formulaire, si ça se présente.

        • Fanny Demuynck dit :

          Bonjour,

          Je reviens vers concernant la création de sous formulaires. Cela me semble logique. Cependant je n’y arrive pas. Je ne sais pas si on peut créer des sous-formulaires dans un formulaire de type datasheet et qui sont par ailleurs liés avec une relation plusieurs à plusieurs?

          Si cela n’est pas possible, quelle code puis-je utiliser dans des formulaires liés pour que sur double clique sur une référence il ouvre le formulaire lié et ne fasse appaître que les enregistrements liés (via une table de jonction contenant RefPol et RefPR).

          Merci de votre compréhension

          • Hervé Inisan dit :

            Pour compléter ma réponse précédente, il est possible de faire apparaître un sous-formulaire basé sur une relation Plusieurs/Plusieurs.
            1. Le formulaire principal sera basé sur la table principale à afficher (ou sur une requête s’il y a besoin de tris, de calculs, etc.).
            2. Le sous-formulaire sera basé sur une requête qui assemble la table de jonction et la 3ème table.
            3. Pour faire simple lors des premiers tests, il vaut mieux que cette requête comporte TOUS les champs des tables.
            4. Il faudra ensuite paramétrer les champs pères/fils du sous-formulaire pour relier la clef primaire de la table principale à la clef étrangère de la table de jonction.

            Pas facile à expliquer comme ça, mais le principe est là ! 🙂

  7. mel dit :

    salut Hervé, j’ai une question. Comment peut-on obtenir la plus grande valeur et par catégorie dans une requête. je m’explique : j’ai une requête ayant un champs Produit : riz, banane, mangue ayant plusieurs enregistrement et un champs Prix donnant le prix de chaque produit je voudrais faire une autre requête qui me donnera la liste de produit le plus chair et le moins chair.
    Merci.

  8. Hervé Inisan dit :

    catvando78 > Quelle est la partie qui ne marche pas ?

    La table PARAMS existe bien, et elle contient bien un champ ID de type Numérique ?

  9. catvando78 dit :

    Bonjour, J’ai un problème avec DLookup que je ne comprends pas, car cela fonctionnait avant puis cela a cessé brusquement et impossible de le rétablir sous peine de message « argument ou appel de procédure incorrect ».
    Voici ce dont il s’agit : j’ai un formulaire principal pour les paiements (basé sur requête finances, basée sur tables adhérents et finances), et un sous formulaire (basé sur requête détail_finances basée sur table détail_finances avec calcul Total par Ligne et Total_Déplacement) où, par ligne, on a l’année de l’opération, une liste déroulante pour choisir le type de règlement, puis les champs monétaires correspondants : abonnement, cotisation, hotel, transport, single, etc.
    J’étais arrivée à ce que, par DLookup, en Got_Focus, l’année soit cherchée dans une table appelée PARAMS, colonne Valeur, position 6, par le code VBA :
    Private Sub Année_GotFocus()
    Me.Année = DLookup(« Valeur », « PARAMS », « ID = 6 »)
    End Sub
    puis pour les autres champs, j’avais écrit les codes du style (je n’en donne que 2)n toujours en Got_Focus :
    Private Sub Cotisation€_GotFocus()
    If Me.Type = « COTS » Then
    Me.Cotisation€ = DLookup(« Valeur », « PARAMS », « ID = 1 »)
    ElseIf Me.Type = « COTC » Then
    Me.Cotisation€ = DLookup(« Valeur », « PARAMS », « ID = 2 »)
    Else: Me.Cotisation€ = 0
    End If
    End Sub
    ou
    Private Sub Single€_GotFocus()
    If Me.Type = « SINGL » Then
    Me.Single€ = DLookup(« Valeur », « PARAMS », « ID = 5 »)
    Else: Me.Single€ = 0
    End If
    End Sub
    C’est la 1ère fois que je me sers du VBA, et je ne suis pas très sure d’avoir tout compris. J’ai dû modifier un critère quelque part dans une table ou faire une mauvaise manip, toujours est-il que je n’y arrive plus.
    D’avance merci de m’aider.
    Salutations, Catherine vd

  10. Hervé Inisan dit :

    roman > Euh ? 😉

  11. Hervé Inisan dit :

    Anais > Super, content que ça marche ! 🙂

  12. Anaïs dit :

    J’avais simplement fait une faute dans la clause where de ma requête, inversion de deux lettres ^^ donc c’est bon, merci tout fonctionne bien depuis hier,
    voilà, je fais maintenant un publipostage sous forme de tableaux sous Word, donc votre blog est vraiment clair avec toutes les astuces,
    Merci beaucoup

  13. Hervé Inisan dit :

    Anais > Que contiennent MotPasseSaisie et ServiceSelectionne ? Est-ce que ce sont des valeurs existantes dans la table ServiceE ?

    Notamment, est-ce que ceci affiche le bon critère SQL :

    En passant : LoginX et NomService sont bien des champs de la table ServiceE ?

  14. Anaïs dit :

    Maintenant, la fonction renvoie toujours une valeur nulle même si le login saisi est bon.

  15. Anaïs dit :

    Après vérification, l’erreur était loginApplication dans l’écriture de la condition, tout bête 😀
    Merci encore, maintenant il faut que je regarde la suite du projet

  16. Anaïs dit :

    Bonjour, merci beaucoup de m’avoir répondu.
    Bon, c’est bien à l’appel de la fonction DLookUp que l’opération est annulée.
    Le message Hello n’est pas lu.

  17. Hervé Inisan dit :

    Anais > De quel endroit est appelé le code VBA dont on parle ? Parce que je pense que c’est cet appel qui est considéré comme annulé (sans doute à cause du DoCmd.Close). Par contre, si le DLookup() est correct, ce n’est sans doute pas lui qui génère ce message. J’essaierais de placer un MsgBox "Hello" juste sous le Then (et avant le DoCmd.Close), pour vérifier.

  18. Anais dit :

    Bon, j’ai tout rectifié au niveau des erreurs, mais VBA m’annule tout simplement l’action avec erreur ‘2001’ : opération annulée.

  19. Anais dit :

    Bon, je viens de rajouter les & & pour les expressions dans la clause de condition.

  20. Anais dit :

    Bonjour, j’utilise la fonction DLookUp comme ceci :
    If IsNull(DLookup(« [LoginX] », « ServiceE », « [LoginX]= ‘MotPasseSaisi’ And [NomService] = ‘ServiceSelectionne' »)) Then
    ‘ Fermer la boîte de dialogue « Identification »
    DoCmd.Close
    MsgBox « Le mot de passe saisi est incorrect. », vbExclamation
    Mais lorsque je déclenche le processus, il ne me trouve pas loginX qui est bien dans ServiceE.
    Merci d’avance.
    Anais

  21. Hervé Inisan dit :

    Anais > Ce serait effectivement plutôt quelque chose comme :

  22. Archeis dit :

    Bon sang ! Un sujet qui date mais un auteur toujours vivace et qui répond gentiment. Pour ma part, je n’étais venu que chercher une information de fonctionnement. Cependant, il fallait saluer le travail de M. Inisan.

  23. Hervé Inisan dit :

    David > On peut faire de cette manière : dans l’événement AfterUpdate du numéro d’article (NumArticle, donc), écrire quelque chose comme :

    A aménager. Dans mon exemple :

    • [PrixArticle] est le champ à alimenter. Il doit être présent dans le formulaire et dans la table sous-jacente.
    • [Prix Article XYZ] est le prix de l’article dans la table Article. J’ai mis les XYZ pour différencier ici.
    • Me![NumArticle] est le champ NumArticle qui est mis à jour sur le formulaire (et qui déclenche la recherche du prix). J’ai supposé que ce champ était numérique.
  24. DAVID dit :

    Bonjour,
    je cherches quelques lumières sur un petit problème :
    J’ai une base access 2007 avec deux formulaires F_ARTICLE et F_FACTURE
    basés respectivement sur deux tables ARTICLE et FACTURE et un sous-formulaire F_DETAIL_FACTURE. Dans ce dernier, bien que le champs NumArticle est lié au champs NumArticle de la table ARTICLE j’ai tout de même choisi, pour des raisons pratiques de reprendre aussi le champs PrixArticle afin qu’il apparaisse dans F_DETAIL_FACTURE
    J’aimerais lorsque je renseigne dans celui ci le champs NumArticle le champs PrixArticle reprenne automatiquement la valeur adéquate.
    J’ai pensé à RechDom mais je ne sais pas l’intégrer en vba; j’ai également essayé en événement BeforeUpdate comme suit :

    Me. [PrixArticle]=[ARTICLE]![PrixArticle]

    ça ne marche pas ! auriez vous des pistes ?
    Merci pour vos lumières

  25. Hervé Inisan dit :

    wiiking73 > En écrivant cela, tu lis seulement le 1er niveau disponible de la table T_Intervenant, puisqu’il n’y a pas de filtre. Donc tu extrais un niveau qui ne correspond pas forcément à l’utilisateur.

    Ce que tu peux faire, par contre, c’est aménager le code précédent (intNiveau ayant été déclarée en global) :

  26. wiiking73 dit :

    Ok par contre je n’arrive pas à transformer le champ niveau de ma table en variable globale.
    J’utilise
    Dim intniveau As integer
    intniveau = Dlookup »[Niveau] », « T_Intervenant »)
    mais lorsque je change de formulaire ça ne prend pas en compte la variable et du coup les boutons restent apparents.
    Merci d’avance

  27. Hervé Inisan dit :

    Wiiking73 > Oui. La première chose à faire, peut-être, serait de stocker le nom (login) de l’utilisateur et son niveau dans 2 variables globales, de façon à les utiliser n’importe où dans l’application. Appelons ces variables strUtilisateur (de type String) et intNiveau (de type Integer), par exemple. Il suffit ensuite, dans l’événement « Sur ouverture » du formulaire, d’écrire quelque chose comme :

    Dans cet exemple, le bouton est invisible pour les niveaux 1, et  visible pour les niveaux 2. On peut bien sûr ajouter autant de boutons et autant de niveaux que nécessaire.

    Ouala !

  28. Wiiking73 dit :

    OK ça fonctionne bien . merci 🙂
    Encore une petite question, du coup quand j’ouvre le formulaire suivant, il y a plusieurs boutons (maintenance préventive; maintenance curative, stock). Chaque opérateur aura un niveau. 1 pour ouvrir uniquement la maintenance préventive, 2 pour la préventive et curative et 3 pour les 3 boutons.
    Les niveaux sont rajoutés dans la table T_Intervenant. Serait il possible de bloquer les boutons selon le niveau de la personne connectée??

  29. Wiiking73 dit :

    Bonjour

    Tout d’abord bravo pour ce blog qui m’as deja bien fait avancé dans la conception de ma base.
    Je suis en train de (essayé de!!) développer une base de maintenance. Je souhaiterai faire un premier formulaire login/mot de passe. Le login est en liste déroulante et le mot de passe est à completer par le technicien. J’ai fait un code que j’ai mis sur le bouton « valider »:
    Dim vPassword As Variant
    vPassword = Dlookup(« [Motdepasse] », »T_Intervenant », »Motdepasse = Password »)
    ‘pas bon
    if isnull(vPassword) Then
    MsgBox « Login et ou mot de passe incorrect »
    else
    ‘c’est bon et on ouvre le formulaire
    Docmd.Openform « ecran principal »
    end if

    La table T_Intervenant contient le login et le Motdepasse (plus le numéro auto). Password est un texte indépendant sur le formulaire Login/Mot de passe.
    Cela fonctionne sauf que si je rentre un mot de passe d’un utilisateur X avec un login d’un utilisateur Y ça marche aussi
    Alors please Help!!!
    Merci

  30. Hervé Inisan dit :

    Wiiking73 > Il faut vérifier à la fois le login et le mot de passe (sinon, on entre dans la base avec l’un ou l’autre). D’autre part, il faut concaténer la condition du DLookup() pour y injecter les valeurs saisies. Ça donnerait :

    J’ai supposé que Utilisateur et MotDePasse étaient les champs de la table, et que les valeurs saisies s’appelaient strUser et strPassword. Je mettrais plutôt [Utilisateur] (ou [Login], si c’est le nom du champ dans ta table) en 1er paramètre du DLookup(). Ici, ça n’a pas d’importance réelle, l’intérêt est surtout de vérifier si on récupère quelque chose, mais c’est pour la forme 🙂

  31. MuadJabbar dit :

    A défaut de pouvoir éditer le post qui ne va pas tarder à apparaitre, je retire ma question sur l’apostrophe j’avais zappé la première ligne qui l’expliquait.
    .
    J’ai finalement réussi à faire ma macro (Voir le bout de code qui suit). La Textbox6 permettant de contrôler que la macro fonctionne (à terme celle ci aura le même type de requête), et j sera réutilisé.
    .

    Private Sub Commande2_Click()
    Dim i As String
    Dim j As String
    i = Texte0.Value

    j = DLookup(« [IDPersonne] », « Personnes », « [Nom]=' » & i & « ‘ »)
    Texte6.Value = j
    EndSub
    .
    .
    Encore merci pour l’aide apportée.

  32. MuadJabbar dit :

    Tout d’abord, merci pour cette promptitude à la réponse. J’ai peut être voulu être trop synthétique.
    .
    .
    J’aimerais revenir sur ce que tu m’as marqué:
    Adaptons : j = DLookup(« [Nom] », « Personnes », « [Nom]=' » & i & « ‘ »)
    en: j= DLookup(« [Nom] », « Personnes », « [IDPersonne]=' » & i & « ‘ »)
    le double guillemet «  » permet bien de sauter une colonne ?
    IDPersonne | Nom | Prénom |
    53 | Emmare | Jean |
    54 | Dupond | Henri |
    Pour i=Dupond il devrait me définire j=54 ? (Je viens de tester en parallèle cette syntaxe, et ça bug au niveau du DLookup et j= » »)
    .
    Quel sens a le signe ‘ ?
    .
    .
    .
    Pour dire vrai. j’ai 6 Tables (± imposées par le projet éducatif):
    -CmdImg Commande des images
    -Evenements Événements auxquels appartiennent les images.
    -Images
    -Personnes
    -Présence
    -Tarifs

    Dans la table présence, je veux relier l’IDFichier au IDPersonne, et à un IDFichier peu correspondre n IDPersonne.
    Ce qui m’intéresse est de venir chercher dans la base personne l’IDPersonne qui correspond au Nom de la personne que j’ai tapé dans mon interface.
    .
    Le but de la macro à terme (mais je veux aussi me prendre la tête là dessus, mais j’arrivais pas à mettre en place ce DLookUp) est que lorsque je lance une recherche via un critère (Nom,Prénom,Surnom,Evenement) je puisse trouver les photos associées.
    .
    .
    Dans un second temps, il me faudra pouvoir ajouter une/des photos à une commande, édition de facture, bla²… rien de palpitant, et déjà fait sur Excel quelque chose de similaire 🙂

  33. Hervé Inisan dit :

    MuadJabbar > Comme le nom est de type texte, il faut le délimiter d’apostrophes. D’autre part, la variable ne doit pas figurer dans le critère, mais elle doit être concaténée. Ce qui donnerait :

    j = DLookup("[Nom]", "Personnes", "[Nom]='" & i & "'")

    Mais dans ce cas, ça m’amène une question : le DLookup() ne sert plus à rien ici, puisqu’on fait une recherche sur un nom qu’on connaît déjà. On va nécessairement retrouver i. Ou bien…?

    Je pense en fait qu’il faut peut-être revoir l’analyse des tables. S’il y a des personnes et des images, ça veut dire :

    1. Qu’une image peut représenter plusieurs personnes.
    2. Qu’une personne peut être présente sur plusieurs images.

    Il faut donc 3 tables pour gérer ça :

    • Personnes
    • Images
    • Et une table de jonction entre les 2, pour établir les correspondances Personnes/Images.

    Et après, le DLookup() ne sera sans doute plus utile : il sera possible de construire un formulaire principal Personnes, avec un sous-formulaires Images.

  34. MuadJabbar dit :

    Salut,
    Noob spoted 🙂 Après moults errements sur différents forums et sur l’aide de VBA/Access (et ce post), il me semble que la commande Dlookup est la plus adapté à mon cas. Cependant, j’arrive pas à la mettre en pratique

    Pour mettre dans le bain, cependant le bouton fait presque rien, je cherche juste à comprendre pourquoi ma syntaxe n’est pas juste

    Tables:
    -J’ai une interface utilisateur ou je cherche à afficher des photos où M. Dupont est dessus.
    – J’ai une table « Personnes »: [IDPersonne],[Nom],[Prénom],…
    – J’ai une table « Images »: [IDFichier],[Adresse Fichier],[Evenement],[Personnes sur la Photo],…

    Interface:
    – J’ai une zone de texte ou je rentre un « [Nom] » (de famille).
    – J’ai un bouton qui doit chercher le « [Nom] » dans la Table « Personnes » et afficher une liste des photos où apparait M. Dupont.
    – J’ai un cadre image.

    Le code associé à ce bouton est le suivant:

    Private Sub Commande2_Click()
    Dim i As String
    Dim j As String
    i = Texte0.Value

    j = DLookup(Nom],Personnes,i)
    ‘j = DLookup(« [Nom] », « Personnes », « [Nom]=i ») LIGNE DÉSACTIVÉE
    End Sub

    Ce programme bug à la ligne du Dlookup, j’analyse les valeurs, je trouve i=Dupont qui est Texte0.Value , et Personnes et Nom sont Vide. (sans les Crochets et Guillemets, j’arrive à lire les valeurs, tandis qu’avec, rien ne s’affiche)

  35. Hervé Inisan dit :

    triton > Comme c’est une question sur un autre sujet, le mieux est de continuer la conversation sur les forums du site. Ce sera plus pratique.

    Inscris-toi et reposte la question là-bas, on s’y retrouve 🙂

  36. triton dit :

    En effet, et un grand merci!J’ai bien compris maitenant à quoi sert exactement la requête et le formulaire(j’avais mal pensé le problème). Sans vouloir abuser, 1 point délicat:
    – j’essaie de construire une base de donnée sur l’exemple d’une exploitation agricole. J’ai donc une table « parcelle » avec une série de champs et notemment le champ « variété plantée ». Les valeurs de ce champs se trouvant dans une seconde table « variétés » disposant d’un champ unique « variétés disponibles » listant toutes les variétés possibles. Enfin une troisième table  » journal taches journalières » destinée à identifier les taches realisées sur chaque parcelle et variété.
    Le problème est que si l’année suivante une variete plantée(golden) est remplacée par une autre (gala) la table « journal… » est(trop) affectée (actualisée): les tâches antérieures qui ont été effectuées sur l’ancienne variété (golden) apparaissent désormais comme si elles avaient été réalisées sur la nouvelle (gala)! Comment résoudre ce problème? D’avance merci!

  37. Hervé Inisan dit :

    triton > Sauf cas particulier, les champs Nom et Prénom ne doivent pas se trouver dans la table Tâches. L’une des raisons étant que ça créerait des doublons dans les données, ce qui est à éviter en bases de données. Donc seul le code de l’agent doit se retrouver dans la table des tâches (et il doit y avoir une relation entre Agents et Tâches, sur ce code). Si tu as ensuite besoin de toutes les infos, tu peux créer une requête basée sur les 2 tables. Si tu construis un formulaire sur la requête, tu as toutes tes infos, sans faire appel à DLookup.

  38. triton dit :

    Bonjour,
    moi aussi je commence avec access et j’ai le doute suivant:

    si je dispose de 2 tables, l’une s’appelle « agents » avec les champs: 1-code, 2-nom, 3-prenom et une seconde table « tâches réalisées » avec les champs: 1-code, 2- nom, 3-…….

    Pour remplir le champs « code » de la deconde table je fais donc une recherche ds les registres de la première,…et pour simplifier le reste j’aimerai que le champs « nom » de la table « taches » se remplisse seul en fonction du champs « code » rempli.

    Je dois utilisé le DLookup?

    Merci pour votre aide!

  39. firefly_459 dit :

    Merci beaucoup!

  40. Hervé Inisan dit :

    firefly_459 > Dans ce cas, pas besoin de DLookup() qui est une recherche ponctuelle. L’équivalent des RechercheV() – ou VLookup() – sur Excel est tout simplement les relations sur Access. Tu peux donc faire ça :

    1. Crée une requête avec les 2 tables.
    2. S’il y a une relation entre les tables (dans la requête), tu la supprimes.
    3. Tu glisses le champ1 de la table1 sur son « correspondant » dans la table2. Ça recrée une relation entre les tables, sur le champ qui nous intéresse.
    4. Tu déposes champ1 et champ2 (au minimum) sur la grille de requête.

    A ce stade là, si tu exécutes la requête, tu obtiens la liste des correspondances exactes entre les 2 tables (donc l’inverse de ce que tu cherches, mais on n’est pas loin :-)). Ensuite :

    1. Tu doubles cliques sur le trait qui relie les 2 tables.
    2. Dans la boîte qui s’affiche, tu as 3 choix (le 1 étant coché). Choisis 2 ou 3. Après avoir validé, tu as une flèche entre les 2 tables.
    3. Exécutes de nouveau la requête.

    Tu obtiens maintenant toutes les lignes de la table1 (ou table2, selon le choix du dessus), et les correspondances éventuelles de la table2. S’il n’y a pas de correspondance, le champ de la table2 est vide. Pour afficher seulement les lignes de table2 qui ont un souci (donc qui sont vides), tu rajoutes un critère Null sous le champ2.
    Tu peux faire la même opération en inversant le sens de la flèche entre les 2 tables…

  41. firefly_459 dit :

    Non, elles sont dans deux tables différentes. Mais je peux faire un query pour les mettre l’une à côté de l’autre si c’est plus simple…

  42. Hervé Inisan dit :

    firefly_459 > Les colonnes sont dans la même table ?

  43. firefly_459 dit :

    Bonjour,

    Je suis débutant en access. J’ai 2 colonnes de plus ou moins 300 000 données. J’aimerais juste savoir quels sont les données qui sont dans une colonne et pas dans l’autre et vis versa. Une macro avec la fonction DLOOKUP est-elle la solution? où y-a-t-il plus rapide? Comment dois-je m’y prendre pour que le résultat de la macro soit dans une colonne du fichier access? En excel, il y a la fonction VlOOKUP qui répond exactement à ma demande mais là j’ai trop de données pour le faire en excel…

    Merci d’avance pour votre réponse

  44. Hervé Inisan dit :

    El Bachir > Je ne vois pas bien la structure de la table. Mais s’il faut appliquer 2 conditions, c’est détaillé dans le point « Combiner les critères », plus haut. Si tu cherches une égalité stricte, remplace les "[champ] LIKE 'I*'" de l’exemple par des "[champ] = valeur" (attention aux apostrophes, si les champs sont de type Texte).

  45. El Bachir dit :

    je vous remerier d’avance pour vottre aide ,j’ai un petit probleme avec la fonction dlookup ,je veux renvoyer la valeur d’un champ quirépond à deux condition .mais je ne sais pas comment
    exemple :
    les chams suivants dans la premiere table:
    champs 1)enreg. 2)enreg. 3)enreg.
    variété cle cle cl
    type de taille fort leger moyen
    unité fertilisante 20 10 15

    pour renvoyer les valeurs de (unité fertilisante ) qui depond de la variété et de type de taille.

  46. enkie dit :

    Exactement ce que je cherchais à savoir! tout est dit =D
    Merci!! ^^

  47. gin88 dit :

    Clair et précis merci pour le boulot effectué

  48. lavebel dit :

    Je vous remercie pour votre réponse qui a été rapide. Comme je ne suis pas une pro d’Access, j’ai du avancer sur d’autres problèmes qui auraient dus être résolus avant même que je vous pose ma question.

    Je pense que je suis dans le dernier cas que vous évoquez: je veux faire un nouvel enregistrement qui comporte la référence d’un contact, mais si je dois vérifier si le nom et le prénom de ce contact sont déjà dans ma table. S’ils sont présents je dois choisir ensuite de conserver cette référence pour mon nouvel enregistrement ou d’en créer un nouveau (personne qui aurait les mêmes noms et prénoms mais qui serait un homonyme).

    Comme je ne parviens pas à expliquer le problème que je rencontre actuellement en termes simples, je m’arrête-là… mais pas sans vous remercier pour votre réponse efficace.

  49. Hervé Inisan dit :

    > Lavebel : s’il s’agit juste d’éviter les doublons, je jouerais à un niveau plus bas, en définissant un index sur les champs, dans la table (pas un index sur chaque champ, mais un index composé, à l’aide de l’icône Index). Ca garantira que la paire Nom/Prénom sera bien unique, quel que soit le mode d’alimentation de la table. Par exemple, si la table est alimentée via un fichier texte externe, la vérification des noms/prénoms sera déclenchée par le moteur, et les doublons ne passeront pas. Autre avantage : ça ne nécessite aucun code VB…

    Maintenant, s’il s’agit de faire une vérification ponctuelle, un DLookup peut effectivement convenir. Attention à bien gérer l’enregistrement lui-même aussi. Je m’explique : si je crée un enregistrement avec Nom = Hervé et Prénom = Inisan, il n’existe pas dans la table, ça passe. Maintenant, si je suis en cours de modification du même enregistrement, l’enregistrement existe forcément dans la table, et me sera renvoyé par le DLookup.
    On peut s’aider de la propriété booléenne Me.NewRecord pour détecter si on est sur enregistrement nouveau ou pas (du style : si Me.NewRecord, lancer le DLookup, sinon ne rien faire).

  50. Lavebel dit :

    Je cherche à vérifier si le Nom et le Prénom d’un client que je saisis dans une formulaire sont identiques à d’autres champs Nom et Prénom existants déjà dans la même table. Dlookup est-il la bonne façon de faire? Et si oui, comment puis-je faire apparaître « sur le même écran de formulaire » tous les enregistrements identiques existants? Oui, moi aussi je suis un bleu en access mais je trouve que votre site, lui au moins , a le mérite d’être très clair. Bravo!!

  51. Hervé Inisan dit :

    Si l’objectif est d’éviter des valeurs identiques dans un champ, ce n’est pas par DLookup() qu’il faut procéder (on pourrait, mais ça fait du code à ajouter, et ce n’est pas la meilleure solution). La solution « naturelle » est d’ouvrir la table en mode Création, de se placer sur le champ concerné, et de lui ajouter un index sans doublons (en bas de l’écran). Ce sera le moteur de base de données qui gèrera les contraintes, automatiquement.

  52. lemmy dit :

    Salut,

    C’est très bien expliqué. Mais je ne sais pas si c’est la bonne manip que je dois faire (je suis un bleu en access !). Parce que j’ai essayé et la formule ne marche pas.
    Voilà, je cherche à paramètrer un champ de ma table afin qu’il n’y ai pas de répétition par rapport à toutes les valeurs antérieures de ce même champ lors de la saisie (valide si). Problème classique sans doute mais je suis un débutant…

  53. Bebe dit :

    juste un peti commentaire pour vous dire que c’est agréable e lire votre blog 🙂

Laisser un commentaire

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