Option Explicit
Sub test2()
Dim Dico As Object, cel As Range, myarray, k
Dim i As Integer
Set Dico = CreateObject("scripting.dictionary")
For Each cel In ThisWorkbook.Sheets("Feuil1").Range("TbAfectAnimal").Columns(2).Cells
If Not Dico.Exists(cel.Text) Then
Dico(cel.Text) = Array(cel.Text, 1, cel.Offset(, 2).Value)
Else
myarray = Dico(cel.Text)
myarray(1) = myarray(1) + 1
Dico(cel.Text) = myarray
End If
Next
'tes 3 valeurs pour chaque NoDOSSIER ,sont dans les items du dico (sous la forme d'un array)
'a savoir [ NoDossier , occurence , IdPerson]
For Each k In Dico.Keys
Debug.Print Join(Dico(k), " | ")
Next
End Sub
for i=0 to dico.count-1
debug.print dico.keys()(i)
next i
Sub test()
Const adVarWChar = 202, adInteger = 3, adDBDate = 133
Dim Rs As Object, cel As Range
Set Rs = CreateObject("ADODB.Recordset")
With Rs
.Fields.Append "Societe", adVarWChar, 50
.Fields.Append "nb", adInteger
.Fields.Append "Date", adDBDate
.Open
For Each cel In ThisWorkbook.Sheets("Source").Range("TbSource").Columns(1).Cells
.Filter = "Societe='" & Replace(cel.Text, "'", "''") & "'"
If .EOF Then .AddNew
!Societe = cel.Text: !nb = !nb + 1: If !Date < cel.Offset(, 2) Then !Date = cel.Offset(, 2)
Next
.Filter = "nb>1": .Update: .MoveFirst
End With
With Feuil2.ListObjects("TbResultat")
If Not .DataBodyRange Is Nothing Then .DataBodyRange.Delete
If Not Rs.EOF Then .Parent.Cells(2, 1).CopyFromRecordset Rs
End With
End Sub
Étant sur excel 2010, je n'ai pas installé le complément Power query. Je ne suis donc pas partant pour PQ.Si l'idée est de récupérer Les numéros de dossier ayant plusieurs aucurance il y a plus simple.
Certains de proposerai à juste titre power querry. Personnellement je n'y ai pas accès mais d'autres peuvent t'accompagner.
Personnellement je pourrais t'offrir un solutions SQL ma il faudra préciser ce que tu veux sélectionné comme information et sur la base de quel filtre. Et je te donnerai un script et toutes les explications qui si rattachement.
Je vais devoir m'absenter mais j'attends t'a réponse et en fonction je m'y colle ce soir.
je t'ai donné un moteur simple à toi d'en faire ce que tu veux aprèsBonjour,
Je reviens avec un autre souci. De ma précédente discussion, j'ai adapté un code de @patricktoulon.
Le code fonctionne bien mais encore faire des trucs.
Je voudrais supprimer toutes les clés dont l'occurrence est >1 et ensuite copier celles qui restent dans le tableau de la feuil2.VB:Option Explicit Sub test2() Dim Dico As Object, cel As Range, myarray, k Dim i As Integer Set Dico = CreateObject("scripting.dictionary") For Each cel In ThisWorkbook.Sheets("Feuil1").Range("TbAfectAnimal").Columns(2).Cells If Not Dico.Exists(cel.Text) Then Dico(cel.Text) = Array(cel.Text, 1, cel.Offset(, 2).Value) Else myarray = Dico(cel.Text) myarray(1) = myarray(1) + 1 Dico(cel.Text) = myarray End If Next 'tes 3 valeurs pour chaque NoDOSSIER ,sont dans les items du dico (sous la forme d'un array) 'a savoir [ NoDossier , occurence , IdPerson] For Each k In Dico.Keys Debug.Print Join(Dico(k), " | ") Next End Sub
J'arrive à lire les clés comme ceci dans une boucle
Mais je n'arrive pas à lire les items.Code:for i=0 to dico.count-1 debug.print dico.keys()(i) next i
Merci pour votre aide.
j'en ai fait bon usage. Lorsqu'on me fait des propositions. La moindre des politesses est que je réponde.je t'ai donné un moteur simple à toi d'en faire ce que tu veux après
D'où as-tu tiré ça. je ne suis pas très fort mais pas débile à ce point.et ta boucle sur dico.counts c'est pas bon
N'y a-t-il pas une bibliothèque a activé comme pour le Dictionary?Création : On crée une instance de ADODB.Recordset en utilisant CreateObject("ADODB.Recordset").
1 c'est bienj'en ai fait bon usage. Lorsqu'on me fait des propositions. La moindre des politesses est que je réponde.
D'où as-tu tiré ça. je ne suis pas très fort mais pas débile à ce point.
Si je l'ai fait, je dois consulter car ça ne va plus dans ma petite tête.
Mes boucles sur les dicos sont
for i=0 to dico.count-1
.......................................
next i
ou
for each cle in dico.keys
............................
next clé
Ce que je n'avais pas compris, c'est comment lire les items du dico lorsqu'ils sont dans un array.
Et tu me l'as bien expliqué dans la vidéos je t'en remercie.
non c'est les arrays qui sont dans le items et pas l'inversec'est comment lire les items du dico lorsqu'ils sont dans un array.
Sub test2()
Dim sql As String
Feuil1.[E1] = "TOTO" ' Change la valeur de la cellule E1 sur Feuil1 à "TOTO"
' Supprime les données existantes dans le tableau nommé "TbRes" sur Feuil2, s'il y en a
If Not Feuil2.ListObjects("TbRes").DataBodyRange Is Nothing Then
Feuil2.ListObjects("TbRes").DataBodyRange.Delete
End If
' Définition de la requête SQL
sql = "SELECT Max([Date]), NoDossier, Last(IdAnimal), Last(IdPerson), Last(TOTO) " & _
"FROM [Feuil1$] GROUP BY NoDossier HAVING COUNT(NoDossier) > 1"
' Création d'une connexion ADODB
Dim Cn As Object
Set Cn = CreateObject("ADODB.Connection")
With Cn
' Ouverture de la connexion avec une chaîne de connexion directe
.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0 Xml;HDR=YES;"""
' Exécution de la requête SQL et copie des résultats dans la cellule A2 de Feuil2
Feuil2.[A2].CopyFromRecordset .Execute(sql)
' Fermeture de la connexion
.Close
End With
' Réinitialisation de la valeur de la cellule E1 sur Feuil1
Feuil1.[E1] = "Cat."
End Sub
SELECT Max([Date]), NoDossier, Last(IdAnimal), Last(IdPerson), Last(TOTO)
FROM [Feuil1$]
GROUP BY NoDossier
HAVING COUNT(NoDossier) > 1
Sub test()
' Déclaration des constantes pour les types de données
Const adVarWChar = 202, adInteger = 3, adDBDate = 133
' Déclaration des variables
Dim Rs As Object, cel As Range
Set Rs = CreateObject("ADODB.Recordset")
' Configuration du Recordset avec les champs nécessaires
With Rs
.Fields.Append "Societe", adVarWChar, 50 ' Champ pour le nom de la société
.Fields.Append "nb", adInteger ' Champ pour le nombre d'occurrences
.Fields.Append "Date", adDBDate ' Champ pour la date la plus récente
.Open
' Parcours de chaque cellule dans la colonne 1 du tableau TbSource
For Each cel In ThisWorkbook.Sheets("Source").Range("TbSource").Columns(1).Cells
.Filter = "Societe='" & Replace(cel.Text, "'", "''") & "'" ' Filtrer par société
If .EOF Then .AddNew ' Ajouter un nouvel enregistrement si non trouvé
!Societe = cel.Text
!nb = !nb + 1 ' Incrémenter le compteur
If !Date < cel.Offset(, 2) Then !Date = cel.Offset(, 2) ' Mettre à jour la date la plus récente
Next
.Filter = "nb>1" ' Ne conserver que les sociétés apparaissant plus d'une fois
.Update ' Appliquer les modifications
.MoveFirst ' Se positionner au début du recordset
End With
' Copie des résultats dans le tableau TbResultat sur Feuil2
With Feuil2.ListObjects("TbResultat")
If Not .DataBodyRange Is Nothing Then .DataBodyRange.Delete ' Vider le tableau s'il contient des données
If Not Rs.EOF Then .Parent.Cells(2, 1).CopyFromRecordset Rs ' Copier les résultats dans le tableau
End With
End Sub
Merci beaucoup.non c'est les arrays qui sont dans le items et pas l'inverse
Bonjour @dysorthographieCe code VBA montre comment utiliser une connexion ADODB pour exécuter une requête SQL sur une feuille Excel, puis copier les résultats dans une autre feuille. Je vais expliquer chaque partie du code et les objets ADODB utilisés.
Présentation et Explication du Code
VB:Sub test2() Dim sql As String Feuil1.[E1] = "TOTO" ' Change la valeur de la cellule E1 sur Feuil1 à "TOTO" ' Supprime les données existantes dans le tableau nommé "TbRes" sur Feuil2, s'il y en a If Not Feuil2.ListObjects("TbRes").DataBodyRange Is Nothing Then Feuil2.ListObjects("TbRes").DataBodyRange.Delete End If ' Définition de la requête SQL sql = "SELECT Max([Date]), NoDossier, Last(IdAnimal), Last(IdPerson), Last(TOTO) " & _ "FROM [Feuil1$] GROUP BY NoDossier HAVING COUNT(NoDossier) > 1" ' Création d'une connexion ADODB Dim Cn As Object Set Cn = CreateObject("ADODB.Connection") With Cn ' Ouverture de la connexion avec une chaîne de connexion directe .Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0 Xml;HDR=YES;""" ' Exécution de la requête SQL et copie des résultats dans la cellule A2 de Feuil2 Feuil2.[A2].CopyFromRecordset .Execute(sql) ' Fermeture de la connexion .Close End With ' Réinitialisation de la valeur de la cellule E1 sur Feuil1 Feuil1.[E1] = "Cat." End Sub
Explication des Objets et Méthodes Utilisés
- Feuil1.[E1] et Feuil2.[A2]:
- Utilisation : Ces expressions accèdent directement aux cellules E1 sur Feuil1 et A2 sur Feuil2. Cette notation permet de lire ou écrire des valeurs dans des cellules spécifiques.
- Modifications : La cellule E1 sur Feuil1 est temporairement changée à "TOTO", puis elle est modifiée en "Cat." après l'exécution de la requête, la raison est du au fait que les champ contenant un [.] point sont difficilement gérable dans les requête de regroupement .
- Feuil2.ListObjects("TbRes").DataBodyRange:
- Utilisation : Accède au tableau nommé "TbRes" sur Feuil2 et son corps de données (DataBodyRange).
- Suppression des Données : Si le tableau contient des données (DataBodyRange n'est pas Nothing), les données existantes sont supprimées pour préparer l'insertion des nouveaux résultats.
- sql:
- Définition : La chaîne sql contient la requête SQL à exécuter. Cette requête sélectionne la date maximale, le numéro de dossier, et les dernières valeurs de plusieurs colonnes, groupées par NoDossier, avec une condition sur le nombre de dossiers.
- CreateObject("ADODB.Connection"):
- Création : Crée une instance d'un objet ADODB.Connection, utilisé pour se connecter à une source de données.
- Chaîne de Connexion:
- Format: Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & ThisWorkbook.FullName & ";Extended Properties=""Excel 12.0 Xml;HDR=YES;""
- Provider : Microsoft.ACE.OLEDB.12.0 est le fournisseur OLEDB utilisé pour se connecter à un fichier Excel.
- Data Source : Spécifie le chemin du fichier Excel, ici le fichier courant (ThisWorkbook.FullName).
- Extended Properties : Détermine des options supplémentaires pour la connexion. Excel 12.0 Xml indique que le fichier est un fichier Excel 2007 ou plus récent. HDR=YES signifie que la première ligne de données est utilisée comme en-tête.
- .Execute(sql):
- Exécution de Requête : Exécute la requête SQL définie dans la variable sql et retourne un objet ADODB.Recordset contenant les résultats de la requête.
- Feuil2.[A2].CopyFromRecordset:
- Copie des Résultats : La méthode CopyFromRecordset copie les données du Recordset retourné par l'exécution de la requête SQL directement dans la cellule A2 de Feuil2.
- Cn.Close:
- Fermeture de Connexion : Ferme la connexion à la source de données pour libérer les ressources.
Conclusion
Le code utilise l'objet ADODB.Connection pour ouvrir une connexion à une feuille Excel, exécuter une requête SQL, et copier les résultats dans un tableau Excel. La chaîne de connexion directe est utilisée pour se connecter au fichier Excel en spécifiant le fournisseur OLEDB et les propriétés étendues pour le fichier Excel. Ce code montre comment utiliser ADODB pour manipuler des données dans Excel en utilisant SQL, et comment intégrer ces données dans des tableaux Excel pour présentation.
Requête SQL Commentée
Code:SELECT Max([Date]), NoDossier, Last(IdAnimal), Last(IdPerson), Last(TOTO) FROM [Feuil1$] GROUP BY NoDossier HAVING COUNT(NoDossier) > 1
Explication de Chaque Partie
- SELECT Max([Date]), NoDossier, Last(IdAnimal), Last(IdPerson), Last(TOTO):
- SELECT : Cette clause indique les colonnes et les expressions à inclure dans les résultats de la requête.
- Max([Date]) : Sélectionne la valeur maximale du champ [Date]. Max() est une fonction d'agrégation qui renvoie la plus grande valeur dans le groupe d'enregistrements.
- NoDossier : Inclut le champ NoDossier dans les résultats. Ce champ est utilisé pour grouper les enregistrements.
- Last(IdAnimal) : Renvoie la dernière valeur trouvée dans le champ IdAnimal pour chaque groupe d'enregistrements. Notez que la fonction Last() n'est pas standard SQL, mais est supportée dans les connexions OLEDB avec Excel pour obtenir la dernière valeur d'un champ dans un groupe.
- Last(IdPerson) : Renvoie la dernière valeur trouvée dans le champ IdPerson pour chaque groupe d'enregistrements.
- Last(TOTO) : Renvoie la dernière valeur trouvée dans le champ TOTO pour chaque groupe d'enregistrements.
- FROM [Feuil1$]:
- FROM : Spécifie la source des données pour la requête.
- [Feuil1$] : Indique le nom de la feuille Excel à partir de laquelle les données sont extraites. Le $ est utilisé pour désigner une feuille de calcul dans Excel dans les requêtes OLEDB.
- GROUP BY NoDossier:
- GROUP BY : Cette clause regroupe les résultats en ensembles d'enregistrements qui partagent la même valeur dans une colonne spécifique.
- NoDossier : Les enregistrements sont regroupés par le champ NoDossier. Cela signifie que les fonctions d'agrégation comme Max() et Last() sont calculées pour chaque groupe distinct de NoDossier.
- HAVING COUNT(NoDossier) > 1:
- HAVING : Cette clause est utilisée pour filtrer les groupes créés par GROUP BY, en se basant sur une condition.
- COUNT(NoDossier) > 1 : Condition qui filtre les groupes pour inclure uniquement ceux où le nombre d'enregistrements (pour chaque NoDossier) est supérieur à 1. En d'autres termes, cette condition conserve uniquement les groupes où NoDossier apparaît plus d'une fois.
Résumé
La requête SQL sélectionne les données de la feuille Excel Feuil1 avec les colonnes suivantes :
Les résultats sont regroupés par NoDossier, et seuls les groupes où NoDossier apparaît plus d'une fois sont inclus dans les résultats finaux.
- La date maximale pour chaque groupe de NoDossier.
- Le champ NoDossier.
- La dernière valeur trouvée pour IdAnimal, IdPerson, et TOTO dans chaque groupe de NoDossier.
Cette requête est utilisée pour analyser et extraire des informations agrégées des données dans une feuille Excel, avec un focus sur les groupes ayant plusieurs occurrences.
Merci beaucoup. Tu m'avais tout expliqué au post#10.Voici le code du poste#10 commenté.
VB:Sub test() ' Déclaration des constantes pour les types de données Const adVarWChar = 202, adInteger = 3, adDBDate = 133 ' Déclaration des variables Dim Rs As Object, cel As Range Set Rs = CreateObject("ADODB.Recordset") ' Configuration du Recordset avec les champs nécessaires With Rs .Fields.Append "Societe", adVarWChar, 50 ' Champ pour le nom de la société .Fields.Append "nb", adInteger ' Champ pour le nombre d'occurrences .Fields.Append "Date", adDBDate ' Champ pour la date la plus récente .Open ' Parcours de chaque cellule dans la colonne 1 du tableau TbSource For Each cel In ThisWorkbook.Sheets("Source").Range("TbSource").Columns(1).Cells .Filter = "Societe='" & Replace(cel.Text, "'", "''") & "'" ' Filtrer par société If .EOF Then .AddNew ' Ajouter un nouvel enregistrement si non trouvé !Societe = cel.Text !nb = !nb + 1 ' Incrémenter le compteur If !Date < cel.Offset(, 2) Then !Date = cel.Offset(, 2) ' Mettre à jour la date la plus récente Next .Filter = "nb>1" ' Ne conserver que les sociétés apparaissant plus d'une fois .Update ' Appliquer les modifications .MoveFirst ' Se positionner au début du recordset End With ' Copie des résultats dans le tableau TbResultat sur Feuil2 With Feuil2.ListObjects("TbResultat") If Not .DataBodyRange Is Nothing Then .DataBodyRange.Delete ' Vider le tableau s'il contient des données If Not Rs.EOF Then .Parent.Cells(2, 1).CopyFromRecordset Rs ' Copier les résultats dans le tableau End With End Sub
Rebonjour,Non tout comme un dictionnary
### Late Binding (liaison tardive) vs Early Binding (liaison anticipée)
- **Early Binding (liaison anticipée)** :
- Se produit lorsque les types d'objets sont définis au moment de la compilation du code. En VBA, cela signifie que tu as référencé la bibliothèque d'objets appropriée via `Outils > Références`, et que tu utilises le mot-clé `New` pour créer une instance d'un objet.
- Exemple : `Set Dico = New Scripting.Dictionary`
- Avantages :
- Meilleure performance : Le code est plus rapide car les références sont résolues lors de la compilation.
- Assistance IntelliSense : Tu bénéficies de l'auto-complétion et des vérifications de syntaxe pendant que tu écris ton code.
- Vérification de type : Les erreurs de type peuvent être détectées lors de la compilation.
- **Late Binding (liaison tardive)** :
- Se produit lorsque les objets sont créés au moment de l'exécution et non à la compilation. Cela se fait souvent en utilisant `CreateObject`, où l'objet est défini comme `Object` jusqu'à ce qu'il soit réellement instancié.
- Exemple : `Set Dico = CreateObject("Scripting.Dictionary")`
- Avantages :
- Flexibilité : Utile lorsque le code doit fonctionner dans différents environnements où la bibliothèque pourrait ne pas être installée, ou avec différentes versions.
- Aucune référence nécessaire : Tu n'as pas besoin de référencer la bibliothèque d'objets explicitement dans ton projet.
### Application dans ton cas :
- **Early Binding** (avec `New`) : Si tu utilises `Set Dico = New Scripting.Dictionary`, tu fais de la liaison anticipée. La bibliothèque `Microsoft Scripting Runtime` doit être référencée dans ton projet VBA.
- **Late Binding** (avec `CreateObject`) : Si tu utilises `Set Dico = CreateObject("Scripting.Dictionary")`, tu fais de la liaison tardive. Cela te permet de créer l'objet `Dictionary` même si la bibliothèque n'est pas référencée dans ton projet, mais cela se fait au détriment de la performance et de la vérification de type lors de la compilation.
Donc, en résumé, le choix entre `CreateObject` et `New` dépend principalement de la manière dont tu souhaites gérer les références aux bibliothèques d'objets dans ton code VBA, ainsi que du besoin de flexibilité par rapport à la performance.
' Déclaration des variables
Dim Rs As Object, cel As Range
Set Rs = CreateObject("ADODB.Recordset")
Bonjour,Si on veut utiliser le Early Binding pour ADODB.Recordset, quelle référence doit-on activer?
Je suis fainéant comme pas deux, je rédige le code mois même, car je n'es pas confiance,et je soustraite à Chatgpt le soins de d'expliquer et doccumenter.Tu viens de me faire un cours
Merci beaucoup.Bonjour,
Adodb fait référence à la librairie: Microsoft Activex Data Object {A.D.O}. Si tu veux utiliser ADODB en Early Binding alors Oui il te faudra activer la librairie.
Je suis fainéant comme pas deux, je rédige le code mois même, car je n'es pas confiance,et je soustraite à Chatgpt le soins de d'expliquer et doccumenter.
Si tu analyse mes différents postes tu trouveras la différence.