XL 2016 Depuis un Module Standard pouvoir Récupérer la Photocopie d'une Classe (dont/Avec) la collection qui est incluse dans le Module de Classe.

laurent950

XLDnaute Barbatruc
Bonjour Le Forum,

J'ai réalisé un Module de classe (CPays) avec une Variable de Type Collection (Coll) qui inclut dans le Module de classe.

Le Principe avec une boucle For je viens Créer une nouvelle instance à chaque itération
de l'objet Pays, dont je me sers pour remplir cette classe.

Je souhaite une fois cette classe remplie consigner cette classe dans la collection qui elle est incluse dans le module de classe.

Par la suite je souhaite appeler cette collection depuis le module standard, car cette collection se trouve dans le module de classe, avec un code pour y retrouver la photocopie de la classe correspondante a ce qui a était précédemment enregistré et remplis !

J'ai réalisé la macro, mais cela ne fonctionne pas.

En Exemple :
j'ai écrit le code, dans la zone de texte sur la Feuil à côté du tableau structurée.
la collection se situe dans le module standard, et cela me renvois les bon résultat.
je souhaite l'inverse la collection dans le module de classe et aucune collection dans le module standard.

Je poste le code qui ne fonctionne pas ci-dessous avec le fichier joint.

Si vous avez l'explication et même la solution je vous remercie car je ne trouve pas la solution après plusieurs recherches ?

Module Standard : Ci-Dessous

VB:
Sub CollectionDansModuleDeClasse()

Dim data As Variant ' ............................................................. 1)
data = Sheets("Collections").ListObjects(1).DataBodyRange.Value2 ' ................ 1)
Dim i As Long ' ................................................................... 1)

Dim PaysGlobal As New ClsPays ' ................................................... 2)

Dim Pays As ClsPays ' ............................................................. 3)

For i = 1 To UBound(data, 1) ' .................................................... 1)
    Set Pays = PaysGlobal.Item(data(i, 1))
    Set Pays = Pays
    Pays.Code = data(i, 1) ' ...................................................... 4)
    Pays.Nom = data(i, 2) ' ....................................................... 4)
    Pays.Capitale = data(i, 3) ' .................................................. 4)
Next i

For i = 1 To UBound(data, 1)
    Set Pays = Pays.TransferCollection(data(i, 1)) ' .............................. Bloque) Un seule Item est remplis avec mauvais code !
        Debug.Print Pays.Code, Pays.Nom, Pays.Capitale
Next i
End Sub

Module De Classe(ClsPays) : Ci-Dessous

Code:
Private mCode As String
Private mNom As String
Private mCapitale As String
Private mCLn As Collection
'
Property Get Code() As String
    Code = mCode
End Property
Property Let Code(ByVal NewValue As String)
    mCode = NewValue
End Property
'
Property Get Nom() As String
    Nom = mNom
End Property
Property Let Nom(ByVal NewValue As String)
    mNom = NewValue
End Property
'
Property Get Capitale() As String
    Capitale = mCapitale
End Property
Property Let Capitale(ByVal NewValue As String)
    mCapitale = NewValue
End Property
'
Property Get PhtosCopieClassWithKey() As String
    Capitale = mCapitale
End Property
'
Public Function TransferCollection(ByVal NewValue As String) As ClsPays
   Set TransferCollection = mCLn(NewValue)
End Function
Private Sub Class_Initialize()
   Set mCLn = New Collection
   End Sub
Public Function Item(ByVal NewValue As String) As ClsPays
   On Error Resume Next
   Set Item = mCLn(NewValue)
   If Err Then
      Set Item = New ClsPays
      Set Item = Me
      mCLn.Add Item, NewValue
   End If
   End Function
 

Pièces jointes

  • Test Module de classe Inclus Object Collection.xlsm
    31.7 KB · Affichages: 6
Dernière édition:

dysorthographie

XLDnaute Accro
Module Standard
VB:
Sub CollectionDansModuleStandard()
' Ici la collection est dans le Module Standard

' Récupère le contenu du tableau des pays dans un tableau VBA à 2 dimensions
Dim data As Variant
    data = Sheets("Collections").ListObjects(1).DataBodyRange.Value2

' Ajoute les noms des pays dans une collection
Dim Coll As Collection
    'Set Coll = New Collection

Dim pays As New CPays2  ' Module de Classe

Dim i As Long
For i = 1 To UBound(data, 1)
pays.Add data(i, 1), data(i, 2), data(i, 3)
'   Set pays = New CPays ' ......... Crée et initialise l'objet Pays(Module de Classe)
'       pays.Code = data(i, 1) ' ... Initialise la classe pour le Code
'       pays.Nom = data(i, 2) ' .... Initialise la classe pour le Nom
'       pays.Capitale = data(i, 3) ' Initialise la classe pour la Capitale
'   Coll.Add pays ' .................Ajoute le pays(Module de Classe) à la collection(Coll)
Next i

' Affiche les Codes, Nom des Pays, et leurs capitales dans le panneau d'exécution
'For Each pays In Coll
   Debug.Print pays.RETOURN
'Next

' Résultat
'AT            Autriche      Vienne
'BE            Belgique      Bruxelles
'BG            Bulgarie      Sofia
'CY            Chypre        Nicosie
'HR            Croatie       Zagreb
'DK            Danemark      Copenhague
'ES            Espagne       Madrid
'EE            Estonie       Tallinn

End Sub

module de classe CPays2
Code:
Private mCode As String, mNom As String, mCapitale As String
Dim Col As New Collection

Property Get Code() As String
' Renvoi la valeur actuelle
   Code = mCode
End Property
Property Let Code(ByVal NewValue As String)
' Mise à jour de la valeur
   mCode = NewValue
End Property
'
Property Get Nom() As String
' Renvoi la valeur actuelle
   Nom = mNom
End Property
Property Let Nom(ByVal NewValue As String)
' Mise à jour de la valeur
   mNom = NewValue
End Property
'
Property Get Capitale() As String
' Renvoi la valeur actuelle
   Capitale = mCapitale
End Property
Property Let Capitale(ByVal NewValue As String)
' Mise à jour de la valeur
   mCapitale = NewValue
End Property
Public Function RETOURN() As String
For Each pays In Col
   RETOURN = RETOURN & pays.Code & vbTab & vbTab & pays.Nom & vbTab & vbTab & pays.Capitale & vbCrLf
Next
End Function
Public Sub Add(Code, Nom, Capitale)
Col.Add New CPays2
With Col(Col.Count)
   .Code = Code: .Nom = Nom: .Capitale = Capitale
End With
End Sub

la seule chose qui me gène c'est que tu utilise les collection comme un tableau redimensionnable mais pourquoi pas!
 
Dernière édition:

Dranreb

XLDnaute Barbatruc
Bonjour.
Il n'est pas interdit de prévoir aussi une collection en tant que propriété d'une classe, mais ce autour de quoi semble tout le temps tourner @laurent950 semble l'idée pour le moins casse gueule qu'un exemplaire puisse être membre de sa propre collection. Jamais ma fonction Gigogne ne fait ça !
 

laurent950

XLDnaute Barbatruc
Bonjour @Dranreb @dysorthographie @patricktoulon Le Forum

Alors Un très Grand Merci à toi @dysorthographie Pour le code en Poste #43 que je vais analyser par la suite extra.

Merci aussi a @patricktoulon

Mais Aussi un très très grand merci a @Dranreb qui m'aide beaucoup avec ces structures de code très complexes.

Justement @Dranreb Je suis entrain de décortiquer tous vos codes @Dranreb et j'ai quelques questions aussi.

Question @Dranreb
Votre Module Standard (MGigogne) Continet des fonctions Property (Let/Get) ?

VB:
' Let = Ecriture
Property Let DernièreLigneÀIndexer(ByVal L As Long)
Property Let LignesÀFiltrer(ByVal TL)
Property Let Entête(ByRef C As Long, ByVal S As String)
Property Let TableauRetaillé(ByVal LOt As ListObject, Optional ByVal LMax As Long, TVals())
Property Let TitresDuTableau(ByVal LOt As ListObject, Optional ByVal CInser As Long, TTitres())

Puis Celle-ci
' get = Lecture
Property Get Entête(ByRef C As Long) As String

Alors Voici Ma question, Property est Spécifique au Module de Classe mais aussi applicable et compatible avec Module Standard ? :

Pouvez vous me donner cette réponse @Dranreb et encore merci pour votre Aide précieuse
 
Dernière édition:

dysorthographie

XLDnaute Accro
Si les Property était réservé aux seules modules de classe VBA générerait un message d'erreur.

Certaines personnes qui ce prétende puriste considère que les Property non rien a faire dans un module standard mais force est de constater que sa marche! pourquoi utiliser un sub et un fonction alors qu'une Property est bidirectionnelle?

les Property sont à l'origine pour isoler les variables interne d'une classe du reste du programme; les Property sont des interfaces entre la classe et le programme pour permettre de qualifier le données transmise; les Property contiennent en générale du code; dans ce que tu utilises
VB:
Property Let Code(ByVal NewValue As String)
' Mise à jour de la valeur
   mCode = NewValue
End Property
ta Property n'est rien d'autre qu'un passe plat tu pourrais déclarer mCodeen public!

un exemple qui montre l'intérêt d'un Property dans un module standard!

Code:
Sub Test2()

PressePapier = Range("A1").Value
Debug.Print PressePapier
ClearPressePapier
End Sub
Public Function ClearPressePapier()
With CreateObject("htmlfile").parentwindow.clipboardData.clearData("Text"): End With
End Function
Public Property Let PressePapier(valeur)
With CreateObject("htmlfile").parentwindow.clipboardData.SetData("Text", valeur): End With
End Property

Public Property Get PressePapier()
PressePapier = CreateObject("htmlfile").parentwindow.clipboardData.GetData("TEXT")
End Property
 

laurent950

XLDnaute Barbatruc
pourquoi utiliser un sub et un fonction alors qu'une Property est bidirectionnelle?
Je te remercie @dysorthographie pour cette explication qui est devenu clair pour moi.
J'avais bien compris que l'utilisation de Property était bidirectionnelle, mais j'avais pas saisie cette intérêt de substituer d'un un module standard une Sub et Fonction par une Property

Pour ma pars je n'utiliserais que la Property dans un Module de classe pour éviter des confusions, mais j'ai vraiment saisie le sens.

Pour ta question :
la seule chose qui me gène c'est que tu utilise les collection comme un tableau redimensionnable mais pourquoi pas!

Je vais en établir un exemple parlant, je vais l'écrire pas en code mais a la main avec des exemples pour comprendre ma recherche et savoir si cela est Possible aussi.

@Dranreb à raison sur ce point :
l'idée pour le moins casse gueule qu'un exemplaire puisse être membre de sa propre collection. et j'ai constaté que cette fonction Gigogne ne fait ça effectivement !

C'est pour cela que je vais prendre le temps d'écrire l'exemple et le documenter. et je vais regarde votre Poste #46 @dysorthographie avec celui de @Dranreb et analyser ce que je souhaite faire et construire.
 
Dernière édition:

dysorthographie

XLDnaute Accro
Et comme tu peux le voir dans l'exemple j'utilise creatobject pour créer un une de
("htmlfile").parentwindow.clipboardData.GetDat
Il peut y avoir des if, select case et autre for i dans une Property.

J'aurais pu replace Public Function RETOURN() As String par un Property GET {en lecture Seule} si j'avais voulu.

Pour ce qui concerne les collections c'est plus facile de trouver col("Allemagne") que de chercher dans le tableau collection l'instance de l'Allemagne.
 
Dernière édition:

laurent950

XLDnaute Barbatruc
Bonsoir @dysorthographie

Poste #43 dans votre module de classe :
Col.Add New CPays ' New Correspond a quoi ?
Col.Add = Ajout à l collectionNew CPays
New = Je sais pas
CPays = C'est la classe pays

J'aurais plus vu cela
Col.Add Item:=La Classe, Key:=une clé comme votre exemple col("Allemagne")

Si vous pouvez me renseigner sur cela en vous remerciant pour toutes vos explications précédente.
 

dysorthographie

XLDnaute Accro
Bonsoir,
New est le constructeur d'une nouvelle instance de la classe ClsPays.
Code:
Dim Pays As ClsPays
Set  Pays = New ClsPays

On resseigne un collection en fournissant la valeur puis la clé.
Code:
Col.add New ClsPays, "Allemagne"
Col("Allemagne").Capitale= "Berlin"
Col("Allemagne").Nom= "Munich"
Col.add New ClsPays, "France"
Col("France").Capitale ="Paris"
Col("France").Nom= "Paris"
Par exemple
Maintenant si tu veux gère plusieurs villes pour un pays il faut chêner les collections
Code:
Col("France").Col.add new ClsPays,"Paris"
Col("France").Col.add new ClsPays,"Lyon"
Col("France").Col("Paris").Mere="Anne Hidalgo"
En nommant tes instances dans ted collections tu y accèdes par leur nom .

On verra qu'il faut évaluer l'existence d'une clé affin de ne pas gêner d'erreur.

Patrick utilise on error moi j'ai une autre méthode.
 
Dernière édition:

laurent950

XLDnaute Barbatruc
@dysorthographie

J'ai créer une fonction qui Renvoie la valeur True si une clé spécifiée existe dans l’objet (Equivalent a L'objet Dictionary) ; False si ce n’est pas le cas.

VB:
Function Exists(ByRef col As Collection, ByVal key As String) As Boolean
' Le code suivant vérifie si une clé existe
    On Error GoTo EH
    IsObject (col.item(key))
    Exists = True
EH:
End Function
 

laurent950

XLDnaute Barbatruc
@dysorthographie

Maintenant je vois cela avec cette possibilité de chêner les collections.

C'est a dire a partir d'un module standard :
remplire un Module de Classe.
Une fois celui-ci remplis.
l'enregistre dans une Collection
Comme des photocopies.

Ce qui est plus complexe c'est de pouvoir créer une Arborescence de collections :
Comme par exemple :
Col("France").Col.add new ClsPays,"Paris"
Col("France").Col.add new ClsPays,"Lyon"
Col("France").Col("Paris").Mere=les noms

C'est a dire France la racine = Collection avec un Code exemple "FR"
Puis France content deux Ville = Paris et Lyon
Puis Pour Paris C'est Anne Hidalgo.

Donc pour France, Remplir une classe avec La surfaces, Nombres habitants, etc.
soit une classe enregistré
en sous arborescence
la ville Paris une classe avec avec La surfaces, Nombres habitants, etc.
la ville Lyon une classe avec avec La surfaces, Nombres habitants, etc.
Puis pour les noms un autre module de classe mais qui serait enregistré cette collection.

C'est complexe je sais mais j'aimerais partir de quelque choses de très simple comme votre
premier code en Poste #46 merci @dysorthographie

j'avance doucement dans la compréhension.
 

dysorthographie

XLDnaute Accro
@dysorthographie

J'ai créer une fonction qui Renvoie la valeur True si une clé spécifiée existe dans l’objet (Equivalent a L'objet Dictionary) ; False si ce n’est pas le cas.

VB:
...
  On Error GoTo EH
    ...
End Function
VB:
dim tExiste as string
Public Property Get Existe(t As String) As Boolean
Existe = InStr(1, "©" & tExiste & "©", "©" & t & "©")
End Property

Public Sub createElement(tagName As String)
If Not Existe(tagName) Then
    childs.Add New XmlElement, tagName
    Set childs(tagName).parentX = Me
    tExiste = tExiste & "©" & tagName & "©"
 
End If
    childs(tagName).Tag = tagName
End Sub
 

dysorthographie

XLDnaute Accro
Dernière édition:

Discussions similaires

Statistiques des forums

Discussions
314 727
Messages
2 112 264
Membres
111 478
dernier inscrit
Excel_INFO