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 :

[VB]Retouver les clés des items d'une Collection, c'est possible ?


Sujet :

VBA Access

  1. #1
    Membre averti

    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 418
    Points : 328
    Points
    328
    Par défaut [VB]Retouver les clés des items d'une Collection, c'est possible ?
    Bonjour à tous.

    Explication : j'ai une librairie VB (très) peu documentée, qui utilise des collections.
    Dans l'une d'elles, il est possible de récupérer les items grâce à une clé, mais je ne comprends pas vraiment comment les clés ont été choisies lors de l'alimentation de la Collection.

    Du coup, j'aimerais lister les clés des items d'une Collection. (Comment) est-ce possible ?
    J'ai cru entendre parler d'une méthode getKey() pour les items, mais les objets de cette Collection n'ont manifestement pas cette méthode.
    J'ai aussi tenté un :
    la_collection.getKey(la_collection.item(1));
    et
    la_collection.getKey(1);
    mais évidemment, ça ne marche pas...

    Merci d'avance pour l'aide.

    PS : ma question n'est pas spécifique à VBA Access, mais je ne savais pas quel état le forum le plus adéquat...

  2. #2
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 184
    Points : 1 363
    Points
    1 363
    Par défaut
    un for each ..., ça peut pas le faire ?

  3. #3
    Membre averti

    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 418
    Points : 328
    Points
    328
    Par défaut
    Citation Envoyé par Kloun
    un for each ..., ça peut pas le faire ?
    Sauf que je mets quoi dans le For Each ??
    Ca me permet de lister mes items, mais je fais comment pour connaître les clés correspondantes ?

    L'idée, c'est d'essayer de comprendre comment est remplie cette collection (ou plutôt, comment sont choisies les clés lorsqu'elle a été alimentée). Tout ça, afin de pouvoir utiliser les clés afin d'accéder directement à mes items par la suite.
    Parce que sinon, je serais effectivement obliger de faire des For Each à chaque fois que j'en cherche un en particulier.

    Donc je cherche plutôt une fonction ou méthode, (si elle existe...) qui prendrait un index "i" en paramètre, et me retournerait la clé correspondante pour mon item.

  4. #4
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 184
    Points : 1 363
    Points
    1 363
    Par défaut
    Un p'tit
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Dim iVar_Element As Variant
        For Each iVar_Element In la_collection.ItemsSelected
        Next iVar_Element
    Et en debug, tu jette un oeil sur les propriétés de iVar_Element et leurs valeurs.

  5. #5
    Membre averti

    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 418
    Points : 328
    Points
    328
    Par défaut
    Je n'y avais même pas pensé

    Problème : j'utilise Visual Basic Editor avec les outils Office pour utiliser une librairie VB fournie avec un logiciel.
    Je ne sais pas si ça vient de la librairie, mais quand je mets un espion sur ma Collection et mon item (tous deux issus de cette librairie), dans la colonne "Valeur" de l'espion, j'ai "Aucune variable" pour mon item en particulier, et pour tous les items de la Collection en général, alors que je peux bien faire appel aux méthodes de l'item...

    Est-ce normal ? Y'a-t-il une autre méthode pour voir les propriétés des objets ?

    PS : c'est pas
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    For Each iVar in la_Collection
    plutôt que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    For Each iVar in la_Collection.ItemsSelected
    ?

  6. #6
    Membre expérimenté

    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    1 184
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Janvier 2006
    Messages : 1 184
    Points : 1 363
    Points
    1 363
    Par défaut
    Oui, c'est plutôt :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    For Each iVar in la_Collection
    Pour le reste, difficile de dire sans la librairie et le logiciel
    T'as rien trouvé sur le net ?

  7. #7
    Expert éminent sénior
    Avatar de Arkham46
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    5 865
    Détails du profil
    Informations personnelles :
    Localisation : France, Loiret (Centre)

    Informations forums :
    Inscription : Septembre 2003
    Messages : 5 865
    Points : 14 526
    Points
    14 526
    Par défaut
    Bjr,

    Les collections en VBA ne proposent pas de méthode pour retrouver la clé d'un item.
    De plus si on ajoute un item sans préciser la clé, le VBA ne génère pas de clé tout seul.
    L'item ne sera alors accessible que par son indice.

    En regardant un peu comment sont construtites les collections, on peut trouver l'emplacement du premier item, qui contient l'emplacement de l'item suivant, qui lui même contient l'emplacement de l'item suivant, etc jusqu'à la fin de la collection.
    En fait c'est une liste liée.
    Mieux encore on trouve un pointeur vers la clé pour chaque item.
    S'il n'y a pas de clé, le pointeur est nul.

    Bref voilà le code :
    Code à mettre dans un module : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
     
    Option Explicit
     
    ' API pour déplacement de zone mémoire
    Private Declare Sub RtlMoveMemory Lib "kernel32" (pDst As Any, pSrc As Any, ByVal ByteLen As Long)
     
    ' --------------------------------------------------------------------
    ' Renvoit la clé d'un item d'indice pItem d'une collection pColl
    ' --------------------------------------------------------------------
    Function CollGetKey(pColl As Collection, pItem As Long) As String
    Dim lBuffer(1 To 8) As Long ' Buffer pour information sur la collection
    Dim lItem(1 To 7) As Long ' Buffer pour information sur l'Item
    Dim lKey() As Byte ' Buffer pour la clé de l'item
    Dim lCpt As Long ' Compteur d'item
    Dim lPtr As Long ' Pointeur
    Dim lSize As Long ' Taille de la clé
    On Error GoTo Gestion_Erreurs
    ' Test objet initialisé
    If ObjPtr(pColl) <> 0 Then
        ' Lecture informations de la collection
        RtlMoveMemory lBuffer(1), ByVal ObjPtr(pColl), 8 * 4
        ' Lecture informations du premier item
        If lBuffer(7) <> 0 Then
            RtlMoveMemory lItem(1), ByVal lBuffer(7), 7 * 4
            ' Boucle pour lire les items
            Do
                lCpt = lCpt + 1
                ' Si l'indice de l'item correspond
                If lCpt = pItem Then
                    ' Pointeur vers clé
                    lPtr = lItem(5)
                    ' Si une clé existe
                    If lPtr <> 0 Then
                        ' Taille de la clé
                        RtlMoveMemory lSize, ByVal lPtr - 4, 4
                        ' Buffer de réception de la clé
                        ReDim lKey(1 To lSize)
                        ' Récupère la clé
                        RtlMoveMemory lKey(1), ByVal lPtr, lSize
                        ' Conversion unicode
                        CollGetKey = StrConv(lKey(), vbUnicode)
                        CollGetKey = StrConv(CollGetKey, vbFromUnicode)
                        Exit Do
                    Else
                        ' Pas de clé
                        CollGetKey = ""
                        Exit Do
                    End If
                Else ' Sinon, on passe à l'item suivant
                    ' Pointeur vers item suivant
                    lPtr = lItem(7)
                    If lPtr <> 0 Then
                        ' Lecture informations de l'item
                        RtlMoveMemory lItem(1), ByVal lPtr, 7 * 4
                    Else
                        ' On a parcouru tous les items => pas normal
                        CollGetKey = ""
                        Exit Do
                    End If
                End If
            Loop
        Else
            CollGetKey = ""
        End If
    Else
        CollGetKey = ""
    End If
    ' Gestion des erreurs
    On Error GoTo 0
    Exit Function
    Gestion_Erreurs:
        CollGetKey = ""
    End Function

    Remarque : j'ai testé sur quelques collections, c'est une usine à gaz mais ça a l'air de marcher...

    Pour l'utiliser :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    Function TestCollKey()
    Dim lColl As New Collection
    lColl.Add "Item1", "Clé1"
    lColl.Add "Item2" ' Pas de clé
    Debug.Print "1", CollGetKey(lColl, 1)
    Debug.Print "2", CollGetKey(lColl, 2)
    End Function
    CollGetKey(lColl, 1) renvoit "Clé1"
    CollGetKey(lColl, 1) renvoit une chaine vide

    A tester sur ta collection pour voir s'il y a des clés dans la collection.
    Avec un peu de chance ça trouvera des clés, sinon il ne reste plus qu'à utiliser l'indice.

  8. #8
    Membre averti

    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 418
    Points : 328
    Points
    328
    Par défaut
    Ouch, j'aurais du mal à trouver ça tout seul !!!

    Merci

    Je teste ça.

  9. #9
    Membre émérite

    Profil pro
    Inscrit en
    Février 2005
    Messages
    1 751
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Février 2005
    Messages : 1 751
    Points : 2 368
    Points
    2 368
    Par défaut
    Bonjour et BRAVO à Arkham46 !

    Cette fonction CollGetKey() est une première il me semble (pas vu d'équivalent sur l'internet, ou alors j'ai peut être mal regardé).

    Merci Arkham46 pour ce très bon travail, utile notamment pour déboguer des bibliothèques tierces !


    En passant, juste une petite chose (j'ai honte mais c'est en toute simplicité) ...
    La terminologie consacrée est: << liste chaînée >>.
    Citation Envoyé par Arkham46 Voir le message
    En regardant un peu comment sont construtites les collections, on peut trouver l'emplacement du premier item, qui contient l'emplacement de l'item suivant, qui lui même contient l'emplacement de l'item suivant, etc jusqu'à la fin de la collection.
    En fait c'est une liste liée.

  10. #10
    Expert éminent sénior
    Avatar de Arkham46
    Profil pro
    Inscrit en
    Septembre 2003
    Messages
    5 865
    Détails du profil
    Informations personnelles :
    Localisation : France, Loiret (Centre)

    Informations forums :
    Inscription : Septembre 2003
    Messages : 5 865
    Points : 14 526
    Points
    14 526
    Par défaut
    Effectivement JBO, j'ai cherché il y a déjà quelque temps (y compris en anglais), et je n'ai pas trouvé ça sur le net.
    Donc c'est empirique, j'ai créé une collection et ajouté des éléments un à un en regardant ce qui changeait en mémoire...

    Pour le terme "liste chainée" ça me semble mieux effectivement.

    Au passage j'ai ajouté deux tests dans le code pour éviter un plantage si collection non initialisée ou vide.

  11. #11
    Membre averti

    Profil pro
    Inscrit en
    Juillet 2005
    Messages
    418
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2005
    Messages : 418
    Points : 328
    Points
    328
    Par défaut
    Bonjour.

    Malheureusement, ça ne fonctionne pas avec mes Collections...
    Plus précisément, ces Collections sortent d'un SDK compatible avec VBA, mais elle est en fait censée tourner sur un "moteur" VB spécifique (fourni avec le SDK). L'implémentation de tout ça est assez obscure...
    Et bien que des classes soient spécifiées (et vaguement documentées), lorsqu'on écrit un code, toutes les variables doivent être des "Object", sinon ça plante (erreur : incompatibilité de type). J'imagine que ça explique l'échec de CollGetKey() avec ces objets...

    C'est rageant, mais un grand merci quand même

  12. #12
    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 Lister les items d'une collection et leur valeur
    Bonjour,

    Avec ce que propose Arkham46, on le peut :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    Function TestCollKey()
      Dim lColl As New Collection
      Dim oItem As Variant
      Dim i As Integer
      'Peupler la collection
      lColl.Add "Belgique", "Bruxelles"
      lColl.Add "France", "Paris"
      lColl.Add "Italie", "Rome"
      'Lister son contenu
      i = 1
      For Each oItem In lColl
        Debug.Print lColl.Item(i), CollGetKey(lColl, Eval(i))
        i = i + 1
      Next oItem
     
    End Function

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 35
    Dernier message: 26/09/2010, 22h38
  2. Réponses: 0
    Dernier message: 23/05/2009, 16h18
  3. OnMouseEnter et OnMouseLeave sur des items d'une collection
    Par petitprince dans le forum Composants VCL
    Réponses: 3
    Dernier message: 17/09/2007, 21h57
  4. [Portal 9iAS] : ordre des items dans une région
    Par melitta dans le forum Oracle
    Réponses: 8
    Dernier message: 21/10/2004, 15h01
  5. [VB.NET] Choisir les valeurs des items d'un combo box?
    Par Eithelgul dans le forum Windows Forms
    Réponses: 2
    Dernier message: 07/06/2004, 11h13

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