XL 2010 Module de classe avec Dictionary

cathodique

XLDnaute Barbatruc
Bonsoir,

Je n'ai jamais monté de module de classe tout seul. Et encore moins avec un dictionnaire.

J'ai suivi un tuto (en Allemand, je n'ai rien compris aux explications), je n'ai pas lâché le morceau m'aidant de Google pour la traduction des commentaires du code.

En gros, il utilise un module de classe pour cumuler des heures et récupérer plus de 2 données dans le dictionnaire.
Son code fonctionne parfaitement bien.

J'ai voulu modifier un peu son code pour, au lieu de faire le cumul, compter le nombre d’occurrences.

Et pour aller plus, supprimer toutes les clés qu'on rencontre plus d'une fois.

Pour ceux et celles qui n'ouvrent jamais les fichiers joints voici le code.

Dans module standard
VB:
Option Explicit
Sub ResultatDictionary()
   Dim dic As Dictionary, key As Variant, lig As ListRow

   Set dic = RemplirDictionary

   With Feuil2.ListObjects("TbResultat")
      'Vider le tableau
      If Not .DataBodyRange Is Nothing Then .DataBodyRange.Delete
      'boucle sur toutes les clés du dictionnaire
      For Each key In dic
         'Ajouter une ligne au tableau
         Set lig = .ListRows.Add
         lig.Range(, 1) = dic(key).Societe
         lig.Range(, 2) = dic(key).HeurTrav
         lig.Range(, 3) = dic(key).LaDate
      Next key
   End With
End Sub

Function RemplirDictionary() As Dictionary
'on ajoute as dictionary
'Activer bibliothèque Microsoft Runtime Scripting
   Dim dic As New Dictionary
   Dim cel As Range
   'on declare variable du module de classe
   Dim HeureTravail As ClsHtravail

   'parcourir toutes les cellules des entreprises
   For Each cel In Range("TbSource[Société]")
      'Vérifiez si l'entreprise existe dans le dictionnaire
      If dic.Exists(cel.Value) = True Then
         'compter les heures
          dic(cel.Value).HeurTrav = dic(cel.Value).HeurTrav + cel.Offset(0, 1).Value

         'Déterminez la date de fin
         If dic(cel.Value).LaDate < cel.Offset(0, 2).Value Then dic(cel.Value).LaDate = cel.Offset(0, 2).Value

      Else
         'initialisation de la classe
         Set HeureTravail = New ClsHtravail
         'on rempli(alimente) la classe
         HeureTravail.Societe = cel.Value
         HeureTravail.HeurTrav = cel.Offset(0, 1).Value
         HeureTravail.LaDate = cel.Offset(0, 2).Value

         Set dic(cel.Value) = HeureTravail
      End If
   Next cel
   'Définir la valeur de retour pour la fonction
   Set RemplirDictionary = dic
End Function

Dans module de classe
Code:
Option Explicit

Public Societe As String
Public HeurTrav As Double
Public LaDate As Date

En vous remerciant par avance.
 

Pièces jointes

  • le dictionnaire (avec une classe) - Copie.xlsm
    33.1 KB · Affichages: 19

dysorthographie

XLDnaute Accro
désolé si je tes blaisé, c'était pas mon intension.
oui je sévissait sur dévelopez.com comme pratiquement tous ceux qui on répondu à ta question, je leur fait un grand salut au passage.

j'ai quitté DVP.com,comme tous ceux qui on répondu à ta question, pour les même raison que tu me soupçonne d'avoir.

relie le poste et tu verras que c'est pas ton code que je site!

il est normale que tu cherche des réponses sur tous les support possibles, mais malheureusement on trouve beaucoup de source pas très fiable. cette gambit de code est du fait que bon nombre de développeur VBA font du traitement procédural alors qu'il s'agit de la programmation objet.

chatGPT fait la même chose et je suis souvent obligé de le remettre sur le bon chemin. je l'utilises pour "pisser du code " comme on dit par chez nous .

je déclare mon instance de classe et je manipule les objets. ma classe sait ce qu'elle a à faire et dégage le plus de traitement à la procédure appelante. c'est ça que je voulais t'expliquer même si je mis prend comme un chien dans un jeux de quilles.
VB:
Sub test()
 Dim cls As New ClsHtravail
 cls.Societe = "BASF"
 Debug.Print cls.Societe, cls.Occurences
cls.Societe = "BASF"
 Debug.Print cls.Societe, cls.Occurences
 cls.HeurTrav = 4.5
 Debug.Print cls.Societe, cls.HeurTrav
  cls.HeurTrav = 10
 Debug.Print cls.Societe, cls.HeurTrav
 cls.LaDate = #1/1/2024#
 Debug.Print cls.Societe, cls.LaDate
  cls.LaDate = #12/8/2024#
 Debug.Print cls.Societe, cls.LaDate
 cls.LaDate = #12/4/2024#
 Debug.Print cls.Societe, cls.LaDate
End Sub
 

Pièces jointes

  • le dictionnaire (avec une classe) - Copie.xlsm
    34.1 KB · Affichages: 6
Dernière édition:

mapomme

XLDnaute Barbatruc
Bonjour @cathodique :), et à tous les autres ;),

J'ai bien compris @cathodique que tu désires t’entrainer à utiliser des modules de classe.
Cependant pour ton exemple, je ne vois pas ce qu'apporte un module de classe et donc on aura du mal à en comprendre l'utilité et la nécessité dans ce cas précis.

Pour faire varier les plaisirs, voici un code très rapide qui n'utilise aucun dictionary et qui par conséquent est compatible avec les utilisateurs de MAC qui ne disposent pas de la bibliothèque Microsoft.Scripting.runtime. Le code n'utilise que des arrays. L'astuce consiste en un tri initial des données sources (en rétablissant au final les données sources comme elles étaient au départ).

Le code est dans module1. Le code est commenté.

Bon, ça ne fait pas du tout avancer ton apprentissage :( mais ça m'a détendu de le faire 🤪.
 

Pièces jointes

  • Cathodique- Calculs sur TS- v1.xlsm
    219.7 KB · Affichages: 7
Dernière édition:

Dranreb

XLDnaute Barbatruc
Un module de classe sert à définir un type d'objet.
En conséquence toutes ses variables globales, qu'elles soient Public ou Private, seront adressées par rapport à l'exemplaire traité, de sorte que celui ci devra obligatoirement avoir été préalablement défini par une instruction Set. C'est je crois la seule chose qu'il faut avoir bien compris, et tout devient limpide.
 

mapomme

XLDnaute Barbatruc
Bonjour @Dranreb :) ,

et tout devient limpide.

C'est sans doute limpide pour qui a déjà fait de la POO. Mais pour un débutant, ne serait-ce que les variables globales, privées, accessibles ou non, instanciation, propriétés, méthodes, etc. ne sont guère évidentes à appréhender. Et la limpidité ne vient qu'après pas mal de pratique (comme pour toutes les notions). Mais c'est passionnant 🤩.
 

cathodique

XLDnaute Barbatruc
désolé si je tes blaisé, c'était pas mon intension.
oui je sévissait sur dévelopez.com comme pratiquement tous ceux qui on répondu à ta question, je leur fait un grand salut au passage.

j'ai quitté DVP.com,comme tous ceux qui on répondu à ta question, pour les même raison que tu me soupçonne d'avoir.

relie le poste et tu verras que c'est pas ton code que je site!

il est normale que tu cherche des réponses sur tous les support possibles, mais malheureusement on trouve beaucoup de source pas très fiable. cette gambit de code est du fait que bon nombre de développeur VBA font du traitement procédural alors qu'il s'agit de la programmation objet.

chatGPT fait la même chose et je suis souvent obligé de le remettre sur le bon chemin. je l'utilises pour "pisser du code " comme on dit par chez nous .

je déclare mon instance de classe et je manipule les objets. ma classe sait ce qu'elle a à faire et dégage le plus de traitement à la procédure appelante. c'est ça que je voulais t'expliquer même si je mis prend comme un chien dans un jeux de quilles.
VB:
Sub test()
 Dim cls As New ClsHtravail
 cls.Societe = "BASF"
 Debug.Print cls.Societe, cls.Occurences
cls.Societe = "BASF"
 Debug.Print cls.Societe, cls.Occurences
 cls.HeurTrav = 4.5
 Debug.Print cls.Societe, cls.HeurTrav
  cls.HeurTrav = 10
 Debug.Print cls.Societe, cls.HeurTrav
 cls.LaDate = #1/1/2024#
 Debug.Print cls.Societe, cls.LaDate
  cls.LaDate = #12/8/2024#
 Debug.Print cls.Societe, cls.LaDate
 cls.LaDate = #12/4/2024#
 Debug.Print cls.Societe, cls.LaDate
End Sub
Ayant moi-même quémandé de l'aide sur DVP alors que je découvrais le VBA. J'ai très vite quitté cette communauté, apparemment dédié à des pros. La majorité me prenait de très haute.
Quoique que quelques uns ont été très gentils et compréhensifs. Ils se comptaient sur le bout des doigts.
ça m'a juste rappelé ces brefs moments de désappointement.
Merci beaucoup. Ton code fonctionne très bien.
Amicalement,
 

cathodique

XLDnaute Barbatruc
Bonjour @Dranreb :) ,



C'est sans doute limpide pour qui a déjà fait de la POO. Mais pour un débutant, ne serait-ce que les variables globales, privées, accessibles ou non, instanciation, propriétés, méthodes, etc. ne sont guère évidentes à appréhender. Et la limpidité ne vient qu'après pas mal de pratique (comme pour toutes les notions). Mais c'est passionnant 🤩.
Bonjour @mapomme ;),

Dans le mille, bien que je fasse partie des très anciens. Je ne code pas régulièrement. D'où ma piètre expérience. J'ai utilisé des classes que l'on m'a fait bêtement. Cette fois-ci, j'ai voulu m'y intéressé.
J'ai suivi un tuto (vidéo mais je n'ai pas ce que disait le monsieur Allemand), je n'ai pas compris beaucoup de chose, d'où cette discussion.
Merci beaucoup à tous ceux qui m'ont répondu.
 

patricktoulon

XLDnaute Barbatruc
Bonjour,

@patricktoulon ;), Tes solutions du post#18 donnent un résultat juste via la msgbox.
Je voudrais reporter le résultat sur une feuille de calcul.
Je t'avoue que je sèche depuis 6h.
Un coup de pouce stp.

Merci.
re
ben c'est simple
j'explique tout in the video
 

Pièces jointes

  • le dictionnaire (avec une classe) - Copie.xlsm
    32.6 KB · Affichages: 11

cathodique

XLDnaute Barbatruc
re
ben c'est simple
j'explique tout in the video
Mince, je viens d'ouvrir une discussion pour ça justement.

Merci beaucoup. Très gentil de ta part.

edit: En visionnant juste le début de ta vidéo. Je constate que je me suis encore une mal fait comprendre. J'ai bien récupéré les données sur la feuille avec ton code utilisant un module de classe.

Tu m'as proposé un code sans module de classe, utilisant un array pour récupéré les items du dictionnaires. je suis resté coincé avec ce code.
j'espère que cette fois-ci c'est plus. désolé, si je me suis mal exprimé.
 
Dernière édition:

cathodique

XLDnaute Barbatruc

Dranreb

XLDnaute Barbatruc
Les variables globales sont celles déclarées en tête d'un module, avant toute procédure.
Dans un module standard elles sont définies à l'initialisation du projet VBA.
Dans un module de classe est le sont à l'affectation par un Set d'un exemplaire à la variable objet.
Techniquement, la variable objet ne contient qu'une simple adresse de cet exemplaire (ou peut être un handle fixé par Windows, c'est à dire un indice dans une table d'adresse qui lui est propre et dont il assume la maintenance au gré des allocations dynamiques de mémoire qui lui sont demandées),
 

Dranreb

XLDnaute Barbatruc
Bien sûr mes explication sont un peu schématiques. On a l'impression d'après ce que je dis qu'il s'effectue un traitement pour chaque variable globale de chaque module. Or non, c'est plus simple: chaque module et chaque procédure dispose simplement de son adresse de base par rapport à laquelle la part scalaire de chaque variable n'est connue dans le code que par un décalage fixé une fois pour toute à la compilation.
Pour un module standard, son adresse de base est définie lors de l'initialisation du projet VBA, pour un module de classe elle est définie lors d'une instruction Set,
et pour une procédure (on parle donc là de ses paramètres et variables locales) elle est définie comme la 1ère adresse libre dans la pile, lors de son appel.
Dans tous les cas l'adresse de base à définir pour un truc dépend naturellement du volume des parts scalaires des variables réclamées par le dernier truc pourvu.
 
Dernière édition:

Discussions similaires

Réponses
29
Affichages
2 K
Réponses
2
Affichages
322

Statistiques des forums

Discussions
315 116
Messages
2 116 408
Membres
112 742
dernier inscrit
julien.sch