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
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) :
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 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
Deuxième solution : Créer un index de tri 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
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
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 :
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
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
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
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
Exemple d'utilisation après avoir créé l'index :
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
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....
x = CollRechercheIndex(c, Idx, "Texte cherché")
if x > 0 then Debug.Print c(x)
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...
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.
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
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.
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.add MyCle, New MyClasse
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]
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
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
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager