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 :

Lister et ordonner les éléments d'une structure


Sujet :

VBA Access

  1. #21
    Membre éprouvé

    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    981
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 981
    Points : 1 028
    Points
    1 028
    Billets dans le blog
    36
    Par défaut
    Citation Envoyé par galoir Voir le message
    Bonjour Informer,

    Désolé, ce ne sont pas les meilleurs qui t'ont répondu...

    Parfois avec Access, il faut mettre les mains dans le cambouis pour arriver au résultat attendu, c'est à dire programmer sa propre fonction de tri,...
    Par contre je n'ai pas compris si tu avais une collection de structure, un tableau de structure, ou une seule structure avec plein de colonnes a,b,c,...
    Point de départ et usage de cet structure ?

    cordialement
    Bonjour Galoir,

    Pour l’instant c’est juste une structure. Mon besoin est d'avoir une collection d’éléments qui

    • Peuvent être lus par l’index de leur position
    • Ont toujours le même index dans la collection
    • Peuvent être appelés par leur nom
    Mal nommer un objet, c'est ajouter au malheur de ce monde, car le mensonge est justement la grande misère humaine, c'est pourquoi la grande tâche humaine correspondante sera de ne pas servir le mensonge
    Poésie 44, n° 17 - Albert Camus

    Mes réponses vous ont aidés, un clic sur leur pouce vert
    Bonjour chez vous

  2. #22
    Invité
    Invité(e)
    Par défaut
    Bonjour Informer et bonnes fêtes !

    Ci-dessous deux solutions avec une collection de string qui a pour intérêt de ne pas ajouter une référence à une librairie externe...
    Par défaut, la collection permet de rechercher un élément par son index ou par une clef texte associée facultative qui doit être UNIQUE donc sans doublon ! (voir aide Access si besoin)
    Pour afficher une collection triée, il faut créer une fonction en vba.

    première solution : Ajouter un élément et ordonner la collection en même temps
    Performance : Compter 100ms pour ajouter ~2500 éléments, 500ms pour 5000, 1 seconde pour 7000
    Inconvénient : Ordre de la collection modifié

    Exemple d'utilisation (possibilité d'ajouter une clef à la collection si besoin via l'argument 'Key' de la fonction AddTriCroissant) :
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
     
    Public Function test()
        Dim c As Collection, v As Variant, i As Long
     
        Set c = New Collection
     
        'peupler la collection avec des lettres aléatoires
        Randomize
        For i = 1 To 7
            v = Chr(65 + Int(Rnd() * 26))
            Debug.Print v
            AddTriCroissant c, v
        Next i
     
        Debug.Print vbCrLf & "afficher la collection dans l'ordre croissant"
        For Each v In c
            Debug.Print v
        Next v
     
        Debug.Print "Afficher dans l'ordre décroissant"
        For i = c.Count To 1 Step -1
            Debug.Print c(i)
        Next i
     
    End Function
    Le code de la fonction AddTriCroissant :
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
     
    Public Sub AddTriCroissant(ByRef c As Collection, ByVal Valeur As Variant, Optional ByVal key As Variant)
        Dim lMin As Long, lMax As Long, lMid As Long, lBefore As Long, lAfter As Long
        If c.Count > 0 Then
            If Not IsNull(Valeur) Then
                'recherche dichotomique dans c pour déterminer la position d'insertion
                lMin = 1: lMax = c.Count
                Do While lMax > lMin
                    lMid = (lMax + lMin) \ 2
                    If c.Item(lMid) = Valeur Then
                        lMin = lMid: lMax = lMid
                    ElseIf c.Item(lMid) > Valeur Then
                        lMax = lMid - 1
                    Else
                        lMin = lMid + 1
                    End If
                Loop
                If Valeur <= c.Item(lMin) Then lBefore = lMin Else lAfter = lMax
            Else
                lBefore = 1
            End If
            If IsMissing(key) Then
             If lBefore > 0 Then c.Add Valeur, , lBefore Else c.Add Valeur, , , lAfter
            Else
             If lBefore > 0 Then c.Add Valeur, CStr(key), lBefore Else c.Add Valeur, CStr(key), , lAfter
            End If
        Else
            If IsMissing(key) Then c.Add Valeur Else c.Add Valeur, CStr(key)
        End If
    End Sub
    Deuxième solution : Créer un index de tri de la collection
    Temps de création de l'index : Compter 250ms si 1000 éléments, >1 seconde si 5000, >2 secondes si 7000
    Avantage : Ordre de la collection non modifié
    Exemple d'utilisation :
    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
     
    Public Function testIndex()
        Dim c As Collection, Idx() As Long, v As Variant, i As Long
     
        Set c = New Collection
     
        'peupler la collection avec des lettres aléatoires
        Randomize
        For i = 1 To 7
            v = Chr(65 + Int(Rnd() * 26))
            Debug.Print v
            c.Add v
        Next i
     
     
        setCollTriIndex c, Idx
     
        Debug.Print vbCrLf & "afficher la collection dans l'ordre croissant"
        For i = 1 To c.Count
            Debug.Print c(Idx(i))
        Next i
     
        Debug.Print "Afficher dans l'ordre décroissant"
        For i = c.Count To 1 Step -1
            Debug.Print c(Idx(i))
        Next i
     
    End Function
    Le code de la fonction setCollTriIndex pour créer l'index de la collection :
    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
    17
    18
    19
    20
    21
    22
    23
    24
     
    Public Sub setCollTriIndex(ByRef c As Collection, ByRef Idx() As Long)
        Dim ref As Variant
        Dim h As Long, i As Long, j As Long, k As Long, l As Long, m As Long, n As Long, refIdx As Long, g As Variant
     
        n = c.Count: If n = 0 Then Exit Sub
        ReDim Idx(1 To n)
        For i = 1 To n: Idx(i) = i: Next i
        g = Array(1, 4, 10, 23, 57, 132, 301, 701, 1750, 4376, 10941, 27353, 68383, 170958, 427396, 1068491, 2671228)
        l = LBound(g)
        If n < g(UBound(g)) Then k = l: While g(k + 1) < n: k = k + 1: Wend Else k = UBound(g)
        While k >= l
            h = g(k): m = 1 + h
            For i = m To n
                ref = c(Idx(i)): refIdx = Idx(i): j = i
                Do While ref < c(Idx(j - h))
                    Idx(j) = Idx(j - h): j = j - h
                    If j < m Then Exit Do
                Loop
                Idx(j) = refIdx
            Next i
            k = k - 1
        Wend
    End Sub
    On peut créer aussi une fonction de recherche dichotomique très rapide via l'index créé :
    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
    17
    18
     
    'recherche dichotomique dans c via l'index pour obtenir la position de la valeur
    Public Function CollRechercheIndex(ByRef c As Collection, ByRef Idx() As Long, ByVal Valeur As Variant) As Long
        Dim lMin As Long, lMax As Long, lMid As Long
        If c.Count > 0 Then
            lMin = 1: lMax = c.Count
            Do While lMax >= lMin
                lMid = (lMax + lMin) \ 2
                If c.Item(Idx(lMid)) = Valeur Then
                    CollRechercheIndex = Idx(lMid): Exit Do
                ElseIf c.Item(Idx(lMid)) > Valeur Then
                    lMax = lMid - 1
                Else
                    lMin = lMid + 1
                End If
            Loop
        End If
    End Function
    Exemple d'utilisation après avoir créé l'index :
    ...
    x = CollRechercheIndex(c, Idx, "Texte cherché")
    if x > 0 then Debug.Print c(x)
    Si besoin, Il existe des solutions plus élaborées via une classe par exemple si la collection et ces fonctions associées ne suffisent pas.

    Amicalement

    ps: j'espère que le père Noël a apporté à mes amis plein de bouquins généralistes pour débuter sur Access, Vba , sql...

  3. #23
    Invité
    Invité(e)
    Par défaut
    bonjour,

    créer sa propre méthode de trie si tu travail sur Mac je peux comprendre, mais personnellement je connais pas Mac.


    donc je ne vois pas l’intérêt de créer sa propre méthode de trie {" .Sort = "[Key] DESC,[Value] ASC"}.

    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
    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
    Enum ConAdo
        adEmpty = 0
        adSmallInt = 2
        adInteger = 3
        adSingle = 4
        adDouble = 5
        adCurrency = 6
        adDate = 7
        adBSTR = 8
        adIDispatch = 9
        adError = 10
        adBoolean = 11
        adVariant = 12
        adIUnknown = 13
        adDecimal = 14
        adTinyInt = 16
        adUnsignedTinyInt = 17
        adUnsignedSmallInt = 18
        adUnsignedInt = 19
        adBigInt = 20
        adUnsignedBigInt = 21
        adFileTime = 64
        adGUID = 72
        adBinary = 128
        adChar = 129
        adWChar = 130
        adNumeric = 131
        adUserDefined = 132
        adDBDate = 133
        adDBTime = 134
        adDBTimeStamp = 135
        adChapter = 136
        adPropVariant = 138
        adVarNumeric = 139
        adVarChar = 200
        adLongVarChar = 201
        adVarWChar = 202
        adLongVarWChar = 203
        adVarBinary = 204
        adLongVarBinary = 205
    End Enum
     
     
    Sub test()
    Dim Tableau As Variant
    With CreateObject("ADODB.Recordset")
        .Fields.Append "Index", adInteger
        .Fields.Append "Key", adVarChar, 50
        .Fields.Append "Value", adVarChar, 50
        .Open
        For i = 1 To 91
              .AddNew
            .Fields("Index") = i
            .Fields("Key") = Format(i, "0000")
            .Fields("Value") = Chr(64 + i)
        .Update
        Next
        .Sort = "[Key] desc,[Value]"
        .MoveFirst
        .Filter = "[Index]=2"
        If Not .EOF Then
              Debug.Print .Fields("Value"), .Fields("Key"), .Fields("Value")
              Tableau = .getrows
        End If
     
       End With
    End Sub
    Dernière modification par Invité ; 26/12/2018 à 14h45.

  4. #24
    Membre éprouvé

    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    981
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 981
    Points : 1 028
    Points
    1 028
    Billets dans le blog
    36
    Par défaut
    Encore merci à tous pour cette profusion de solutions que je trouve particulièrement riche et très très intéressante.

    Si ma question portait sur une structure TYPE c’est que ces éléments sont ensuite appelés quand on tape . après le nom de l’instance de la structure au contraire des autres solutions où il faut se rappeler des éléments que se soit pour les collections ou les dictionnaires.

    Enfin, c’est à confirmer, pour mettre à jour un élément d’une collection, il faut d’abord le supprimer et ensuite l’ajouter. Par défaut son index représente la dernière position dans la collection. Or je veux que son index reste identique.

    Bonne fêtes de fin d’année à tous
    Mal nommer un objet, c'est ajouter au malheur de ce monde, car le mensonge est justement la grande misère humaine, c'est pourquoi la grande tâche humaine correspondante sera de ne pas servir le mensonge
    Poésie 44, n° 17 - Albert Camus

    Mes réponses vous ont aidés, un clic sur leur pouce vert
    Bonjour chez vous

  5. #25
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Pour ce qui concerne les type il faut créer un tableau de type dim t(10) as MuType.

    Un tri par ordre croissant consiste à réorganiser le tableau donc à modifier les indexe.

    Il n'est pas possible d'affecter un type personnalisé à une collection mais une classe si.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyCollection.add MyCle, New MyClasse
    Et tu auras accès aux propriétés et méthodes public de ta classe.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MyCollection(MyCle).Mypropriétés=valeur
    Dernière modification par Invité ; 30/12/2018 à 16h24. Motif: Ajout des balises [CODE] et [C]

  6. #26
    Membre éprouvé

    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    981
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 981
    Points : 1 028
    Points
    1 028
    Billets dans le blog
    36
    Par défaut
    Merci dysorthographie pour tes conseils toujours très pertinents.

    Il est peut être intéressant d’expliquer pourquoi j’ai ouvert ce post.

    Pour pouvoir analyser la MAJ d’un fichier Excel par un recordset Access qui se fait sequenciellement car des informations sont saisies par les utilisateurs dans Excel et qu’elles doivent être conservées, j’ai un fichier de log au format CSV qui récupère des données du recordset et de la ligne du fichiers Excel MAJ .

    J’utilise actuellement #print
    • Un premier appel permet de charger les noms des champs dans un tableau avec la fonction ARRAY puis utilisation de JOIN pour ajouter "," comme séparateur
    • A chaque MAJ d’une colonne (60 en tout) d’une ligne d’excel
      • #print est appelé pour charger des données du recordset et d’excel via ARRAY dans un tableau et ensuite appel à JOIN sur le tableau avec comme séparateur ","


    Mais en raison du grand nombre d’infos du log, dès que je rajoute une info supplémentaire, je risque un décalage avec les entetes.

    Mais je presens qu’une solution plus efficace est possible avec les classes !
    Mal nommer un objet, c'est ajouter au malheur de ce monde, car le mensonge est justement la grande misère humaine, c'est pourquoi la grande tâche humaine correspondante sera de ne pas servir le mensonge
    Poésie 44, n° 17 - Albert Camus

    Mes réponses vous ont aidés, un clic sur leur pouce vert
    Bonjour chez vous

  7. #27
    Invité
    Invité(e)
    Par défaut
    Comme il est possible de faire des jointures externe entre Excel et Access, je ne comprends pas tons système de synchronisation.

    https://mon-partage.fr/f/LoCWKVjq/

  8. #28
    Membre éprouvé

    Profil pro
    Inscrit en
    Janvier 2010
    Messages
    981
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2010
    Messages : 981
    Points : 1 028
    Points
    1 028
    Billets dans le blog
    36
    Par défaut
    Citation Envoyé par dysorthographie Voir le message
    Comme il est possible de faire des jointures externe entre Excel et Access, je ne comprends pas tons système de synchronisation.

    https://mon-partage.fr/f/LoCWKVjq/
    Bonjour dysorthographie,

    Merci pour le lien que je vais étudier plus tard.

    Pour te répondre sur ce point, voici les contraintes
    • Chargement de fichiers CSV selon une certaine fréquence par jour dans une base de données (backEnd)
    • Cette base de données est le référentiel Data (backEnd) pour de multiples bases de donnnees métiers (frontEnd)
    • chaque frontEnd est la source de données de MAJ de fichiers Excel spécifiques
    • Les fichiers Excel sont les supports de travail des utilisateurs
    • Les fichiers Excel sont MAJ à la même fréquence que celle du réf. Data
    • Les données de MAJ provenant du réf. data sont le résultat de traitements complexes de données propres au frontEnd
    • Les lignes qui existent dans le recordset mais pas dans un fichier Excel sont ajoutées au fichier Excel et si existent dans les deux alors MAJ de la ligne dans le fichier Excel
    • Les données du réf. data peuvent être modifiées entre J et J+n par les utilisateurs dans le fichier Excel. Ces données modifiées ne doivent pas être ecrasées par les données de la MAJ du réf. data.


    J’ai donc un fichier de log qui restitue des infos sur les données du recordset de MAJ et sur les lignes MAJ (infos par colonne pour entre autre tracer la non MAJ des données modifiées par l’utlisateur dans Excel) ou ajoutées

    Bonnes fêtes de réveillon
    Mal nommer un objet, c'est ajouter au malheur de ce monde, car le mensonge est justement la grande misère humaine, c'est pourquoi la grande tâche humaine correspondante sera de ne pas servir le mensonge
    Poésie 44, n° 17 - Albert Camus

    Mes réponses vous ont aidés, un clic sur leur pouce vert
    Bonjour chez vous

+ Répondre à la discussion
Cette discussion est résolue.
Page 2 sur 2 PremièrePremière 12

Discussions similaires

  1. Réponses: 2
    Dernier message: 12/07/2017, 20h10
  2. Réponses: 2
    Dernier message: 25/08/2011, 17h43
  3. Ordonner les éléments d'une map!
    Par jamsgoodon dans le forum SL & STL
    Réponses: 3
    Dernier message: 11/03/2011, 12h02
  4. Ordonner les éléments d'une table
    Par mmahouac dans le forum Servlets/JSP
    Réponses: 8
    Dernier message: 09/06/2009, 16h42
  5. Pointeur sur les éléments d'une structure
    Par Marley_T dans le forum C
    Réponses: 16
    Dernier message: 05/05/2008, 23h31

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