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

Macros et VBA Excel Discussion :

Utiliser un dictionnaire en argument d'une classe


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 19
    Par défaut Utiliser un dictionnaire en argument d'une classe
    Bonjour à tous,

    J'ai besoin de parcourir un tableau dans un onglet de données et à partir de ces données, de construire des objets encapsulés les uns dans les autres. Mon projet est plus complexe mais j'ai décidé de le résumer en un exemple plus simple ici afin d'arriver au but plus rapidement.

    Imaginons le problème suivant :
    Nom : tableauExcel.PNG
Affichages : 634
Taille : 4,9 Ko

    • J'ai un tableau avec des numéros de voyage et leur ligne
    • On voit dans la colonne A, que chaque voyage appartient au paquet 1
    • J'aimerais créer une classe "paquetVoyage" dans laquelle je viens ranger les numéros de voyages et leur ligne dedans
    • Pour cela je créé un module de classe "paquetVoyages" et en variable privée je lui met un "dictionnairesVoyages" qui est un Scripting.Dictionnary (voir ci-desous)
    • Ensuite je fais une propriété Let pour passer en argument l'ajout d'une valeur dans mon dictionnaire de voyages depuis mon module principal


    Nom : moduleClasse.PNG
Affichages : 684
Taille : 36,8 Ko

    • et dans mon module principal j'essaie de faire ça :


    Nom : modulePrincipal.PNG
Affichages : 589
Taille : 19,0 Ko

    Mais ça ne fonctionne pas, et j'ai essayé plein d'autres façon d'écrire notamment celle-ci :

    Nom : deuxièmeEcriture.PNG
Affichages : 613
Taille : 7,6 Ko

    Mais là j'ai cette erreur :

    Nom : erreur.PNG
Affichages : 592
Taille : 4,1 Ko

    Et en fait je me rend compte que je ne sais pas du tout utiliser les propriétés des modules de classe pour les objets complexes comme les dictionnaires.

    Alors en aveu, je sais que je pourrais traiter ce sujet en initialisant simplement un dictionnaire dans mon module principale et en le remplissant avec les numéros de voyages en "clé" et avec la ligne en "valeur". Mais j'aimerais passer par la méthode que j'essaie de vous décrire ci-dessus pour deux raisons :

    • j'ai envie de comprendre et de perfectionner mon savoir sur les property dans les modules de classe
    • dans le futur je vais manipuler beaucoup plus d'objets qui vont être imbriqués les uns dans les autres et j'aimerais faire du code propre en me servant le plus possible des property et des classes


    Auriez-vous des conseils pour me guider s'il vous plait ?

    Merci beaucoup par avance de votre et surtout bonne soirée à vous

    Guillaume

    PS :
    J'ai pas mal cherché sur le forum et je suis tomber sur des choses trés intéressantes mais que je n'arrive pas à comprendre ni à maitriser :

    https://www.developpez.net/forums/d1...entre-classes/

    https://www.developpez.net/forums/d1...buts-d-classe/

  2. #2
    Membre Expert Avatar de Thumb down
    Homme Profil pro
    Retraité
    Inscrit en
    Juin 2019
    Messages
    1 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Juin 2019
    Messages : 1 573
    Par défaut
    Bonsoir,
    Tu as bien déclaré ta classe en l'instancient avec le constructeur New ?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    dim instance= as New class
    Instance.property(Key)=value

  3. #3
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 19
    Par défaut
    Bonsoir, merci pour votre retour rapide,

    Quand vous dites instancier avec le constructeur "New" vous parlez bien de la manière donc j'instancie mon objet de classe dans mon module principal ?

    Si oui alors en effet j'ai bien instancié avec le constructeur New comme vous pouvez le voir sur cet imprime écran là :

    Nom : photoNew.PNG
Affichages : 585
Taille : 36,2 Ko

  4. #4
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 508
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 508
    Par défaut
    Salut,

    Déclarer un dictionnaire dans ta classe, c'est une chose, encore faut-il que la classe instancie le dictionnaire.
    C'est le role du constructeur (class_initialize).

    Point de vocabulaire:
    Ton dictionnaire n'est pas un "argument" de la classe, c'est un terme réservé aux fonctions, c'est une variable membre de la classe.

  5. #5
    Membre Expert Avatar de Thumb down
    Homme Profil pro
    Retraité
    Inscrit en
    Juin 2019
    Messages
    1 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Juin 2019
    Messages : 1 573
    Par défaut
    Bonjour,
    Dans ta classe tu as deux événements, initialised et terminateur.
    Dans initialised tu écris Set dico= CreateObject("Scripting.Dictionary")
    Et dans teminat Set Dico=Nothing

  6. #6
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 19
    Par défaut
    Bonjour, merci beaucoup Thumb down et deedolith pour vos réponses

    En effet avec la classe définie de cette manière, j'y arrive très bien :

    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
     
    Option Explicit
     
    Private dictionnaireVoyages As Object
     
    Private Sub Class_Initialize()
     
        Set dictionnaireVoyages = CreateObject("Scripting.Dictionary")
     
    End Sub
    Private Sub Class_Terminate()
     
        Set dictionnaireVoyages = Nothing
     
    End Sub
     
    Public Property Let addItemToPaquet(numVoy, ligneVoy)
     
        dictionnaireVoyages(numVoy) = ligneVoy
     
    End Property
    Je vais pouvoir avancer sur ces sujets désormais grâce à vous, encore merci. J'ai tout de même quelque chose qui me taraude :

    La property "Let" ci-dessus attend deux arguments (numVoy et ligneVoy), du coup avec cette manière d'écrire la property Let (que j'apparente pas mal à une fonction finalement vu son fonctionnement) je me serais attendu à plutôt écrire le code de la manière suivante dans mon module principal :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Sub test()
     
    Dim premierPaquetVoyages As New paquetVoyage
     
    For i = 2 To 6
     
     
        premierPaquetVoyages.addItemToPaquet(CStr(Cells(i, 2).value), CStr(Cells(i, 3).value))
     
     
    Next i
     
    End Sub
    Mais, Excel me dit qu'il attend un "=" et m'oblige à écrire le code de cette manière pour que ça fonctionne :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    Sub test()
     
    Dim premierPaquetVoyages As New paquetVoyage
     
    For i = 2 To 6
     
     
        premierPaquetVoyages.addItemToPaquet(CStr(Cells(i, 2).value)) = CStr(Cells(i, 3).value)
     
     
    Next i
     
    End Sub
    et du coup dans ce formalisme je ne comprends pas comment ça fonctionne derrière car la property utilisée dans le module principal semble n'avoir besoin que d'un argument (le numVoy) pour fonctionner alors que dans sa définition dans le module de classe, cette property Let attend deux arguments "numVoy" et "ligneVoy"

    Merci d'avance de vos réponses et bonne journée

    Guillaume

  7. #7
    Membre Expert Avatar de Thumb down
    Homme Profil pro
    Retraité
    Inscrit en
    Juin 2019
    Messages
    1 573
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Juin 2019
    Messages : 1 573
    Par défaut
    bonjour,
    un Property c'est comme une variable ça fonctionne à double sens!
    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
     
    Dim Dico As Object
    Property Let MaVariable(Key, Value)
    Dico(Key) = Value
    End Property
     
    Property Get MaVariable(Key)
    MaVariable = Dico(Key)
    End Property
     
    Sub test()
    Set Dico = CreateObject("Scripting.Dictionary")
    MaVariable("TOTO") = 1
    MaVariable("TOTO") = MaVariable("TOTO") + 1
    MsgBox MaVariable("TOTO")
    End Sub
    Édite:
    D'une manière générale une variable est appelé une propriété. Donc une propriété est une variable.
    Les property sont des morceaux de code qui ont pour objectif de protéger la classe des informations externes.

    Tu pourrais déclarer ton dictionnaire comme public et y avoir accès sans passer par une property.

    En fait une property permet de califier les données externes afin de protéger la classe d'intentions malveillantes.

    Un dictionnaire fonctionne avec une clé et un valeur dico(Key)=valeur,. Tu vois bien que dans ton ça la property fonctionne pareil.

    Si ta property n'est rien d'autre qu'un passe pla, je veux dire si elle ne qualifie pas les données, alors oui déclares ton dictionary en public.

  8. #8
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 19
    Par défaut
    Bonjour à tous,

    Tout d'abord, une bonne année à vous. Deuxièmement, merci Thumb down pour tes dernières réponses .

    Je me trouve à nouveau avec une incompréhension sur le fonctionnement des propriétés par rapport à ce que je cherche à faire dans cette discussion. Voici le tableau réel de données sur lequel je travaille (le précédent était un exemple simplifié pour vous poser mes premières questions) :

    Nom : photo1.PNG
Affichages : 539
Taille : 62,8 Ko

    Ce que je veux faire avec ce tableau :

    • Le parcourir
    • A chaque ligne, construire un objet "horaire" (l'objet qui va contenir des voyages) s'il n'existe pas déjà
    • A chaque ligne, construire un objet "voyage" (s'il n'existe pas déjà) dans l'horaire concerné


    Pour cela j'ai créé une classe cHoraire et une classe cVoy
    Pour le moment, la classe cVoy est trés simpliste, avec uniquement des variables publiques. Je me suis attardé uniquement sur le fonctionnement de la classe cHoraire qui est celle qui doit porter le fonctionnement de l'ajout des voyages à l'intérieur. Voici le code de la classe cHoraire :

    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
     
    Option Explicit
     
    Private mNomHoraire As String
    Private mListeVoyages As Object
     
    Private Sub Class_Initialize()
     
        Set mListeVoyages = CreateObject("Scripting.Dictionary")
     
    End Sub
    Private Sub Class_Terminate()
     
        Set mListeVoyages = Nothing
     
    End Sub
    Public Property Get nomHor() As String
     
        nomHor = mNomHoraire
     
    End Property
     
    Public Property Let nomHor(nomHor As String)
     
        mNomHoraire = nomHor
     
    End Property
     
    Public Property Get countTrip() As Integer
     
        mListeVoyages.count
     
    End Property
     
    Public Property Get tripIsInVsc(nomItemVoy As String) As Boolean
     
        If mListeVoyages.Exists(nomItemVoy) Then
            tripIsInVsc = True
        Else
            tripIsInVsc = False
        End If
     
    End Property
    Public Property Set addTripToVSC(numVoy As String, voy As cVoy)
     
        Set mListeVoyages(numVoy) = voy
     
    End Property
     
    Public Property Get getTrip(nomVoy As String) As cVoy
     
        getTrip = mListeVoyages(numVoy)
     
    End Property
    Voici, cette fois, le module principal, dans lequel je vais parcourir mon tableau et construire les objets :

    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
     
    '[PARCOURIR LE TABLEAU DE DONNEES]
    With Range(nomPlage)
     
        'Attention, avec un "tableau", il faut commencer à 1 et pas à 2 car les en-têtes ne sont pas comptées dans les lignes
        For i = 1 To .Rows.count
     
            numVoyage = CStr(.Cells(i, "A").Value)
            nomPoint = CStr(.Cells(i, "B").Value)
            heurePoint = CStr(.Cells(i, "C").Value)
            nomHoraire = CStr(.Cells(i, "I").Value)
            idDesserte = CStr(.Cells(i, "M").Value)
            jourVoyage = CStr(.Cells(i, "L").Value)
            codeVoyage = numVoyage & "|" & idDesserte
     
     
            '[CREATION HORAIRE]
            If Not dictHoraires.Exists(nomHoraire) Then
     
                nouvelHoraire = nomHoraire 'l'id de l'horaire est unique et suffit à l'identification d'un nouvel objet cHoraire
                Set nouvelHoraire = New cHoraire
                Set dictHoraires(nomHoraire) = nouvelHoraire
     
            End If
     
     
            '[CREATION VOYAGE]
            If dictHoraires(nomHoraire).tripIsInVsc(codeVoyage & "_" & nomHoraire) = False Then
     
                nouveauVoyage = codeVoyage & "_" & nomHoraire 'Pour identifier un voyage, il est préférable de lui créer un code unique sur la base de sa desserte commerciale
                Set nouveauVoyage = New cVoy
                dictHoraires(nomHoraire).addTripToVSC (codeVoyage) = nouveauVoyage
     
            End If
     
        Next i
     
    End With
    Le "dictHoraires" est un dictionnaire qui est déclaré en début de module de la manière suivante :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Dim dictHoraires As New Scripting.Dictionary
    Le problème que je rencontre se situe au niveau de la création du voyage :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
            '[CREATION VOYAGE]
            If dictHoraires(nomHoraire).tripIsInVsc(codeVoyage & "_" & nomHoraire) = False Then
     
                nouveauVoyage = codeVoyage & "_" & nomHoraire 'Pour identifier un voyage, il est préférable de lui créer un code unique sur la base de sa desserte commerciale
                Set nouveauVoyage = New cVoy
                dictHoraires(nomHoraire).addTripToVSC(codeVoyage) = nouveauVoyage
     
            End If
    Quand le code arrive sur la ligne "dictHoraires(nomHoraire).addTripToVSC(codeVoyage) = nouveauVoyage", il plante et me renvoie le message d'erreur suivant :

    Nom : photo2.PNG
Affichages : 517
Taille : 4,3 Ko

    Je n'arrive pas à comprendre ce qui ne fonctionne pas. J'ai aussi essayé d'écrire la ligne de la manière suivante : "Set dictHoraires(nomHoraire).addTripToVSC(codeVoyage) = nouveauVoyage" mais ça ne fonctionne pas non plus.

    Avez-vous des idées ?

    Merci beaucoup par avance

    Guillaume

  9. #9
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 508
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 508
    Par défaut
    Citation Envoyé par Thumb down Voir le message
    un Property c'est comme une variable ça fonctionne à double sens!
    Faux !!

    Rien n'interdit a une classe de définir des propriétés en lecture seule !
    Ce qui en soit, n'est pas une mauvaise chose puisque cela permet d'apporter des garanties, encore faut-il prendre du recul et sortir des sentiers battus.

    Par exemple, une classe représentant une personne:
    Une personne à un nom, un prénom, une date de naissance et par conséquent, un âge.

    Si le nom et le prénom peuvent être changés (pour X ou Y raison administrative), la date de naissance ne l'est pas, ni l'âge qui en découle (c'est calculé).
    Problèmes:
    Comment garantir que la date de naissance est en lecture seule ?
    Comment initialiser cette dernière sans passer par une propriété en lecture / écriture ?
    Avec un langage objet moderne, c'est le(s) constructeur(s) avec paramètres qui s'en charge, concept que VBA ne prend pas en charge (le seul constructeur disponible n'accepte aucun paramètre).
    Il n'y a pas 36 solutions, il faut définir une pseudo constructeur (que l'on nommera Create, et que l'on equiperas des paramètres qui vont bien), ainsi qu'une fonction qui sera en charge d'instancier l'objet. Fonction que, par soucis d'organisation et de lisibilité, nous allons ranger dans un module standard dédié, que l'on peut nommer par exemple: Factory.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    '// Module: Factory
    Public Function Create_Personne(ByVal Nom As String, ByVal Prenom As String, ByVal DateNaissance As Date) As Personne
            '// Instanciation d'une nouvelle personne
        Dim Personne As Personne
        Set Personne = New Personne
     
            '// Appel du pseudo constructeur pour initialiser les variables membre
            '// On se contente de transmettre les paramètres au pseudo constructeur
        Personne.Create Nom, Prenom, DateNaissance
     
            '// On retourne l'instance créée
        Set Create_Personne = Personne
    End Function
    Maintenant la classe Personne:
    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
    '// Class Personne
     
        '// On déclare les variables membres en privé, il n'y a aucune raison que le reste du monde y aie accès
    Private mNom As String
    Private mPrenom As String
    Private mDateNaissance As Date
     
    '// Pseudo Constructeur
    Friend Sub Create(ByVal Nom As String, ByVal Prenom As String, ByVal DateNaissance As Date)
            '// Rien de sorcier, on initialise les variables membre avec les paramètres
        mNom = Nom
        mPrenom = Prenom
        mDate Naissance = DateNaissance
    End Sub
     
    '// Propriétés
        '// Nom (Lecture / Ecriture)
    Public Property Get Nom() As String
        Nom = mNom
    End Property
     
    Public Property Let Nom(ByVal Value As String)
        mNom = Value
    End Property
     
        '// Prenom (Lecture / Ecriture)
    Public Property Get Prenom() As String
        Prenom = mPrenom
    End Property
     
    Public Property Let Prenom(ByVal Value As String)
        mPrenom = Prenom
    End Property
     
        '// DateNaissance en Lecture Seule
    Public Property Get DateNaissance() As Date
        DateNaissance = mDateNaissance
    End Property
     
        '// Age en Lecture Seule
    Public Property Get Age() As integer
        Age = DateDiff("yyyy", mDateNaissance, Now)
    End Property
    Utilisation de tout ce petit monde:
    On declare une variable de Type Personne, et on l'instancie via la fonction Create_Personne dans le module Factory.
    Par soucis de lisibilité, on fera précéder l'appel de la fonction par le nom du module:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    Public Sub Test()
            '// Instanciation d'une nouvelle personne
        Dim Personne As Personne
        Set Personne = Factory.Create_Personne("Lagaffe", "Gaston", DateSerial(1985, 9, 14))
     
        Debug.Print Personne.Prenom
        Debug.Print Personne.Age
     
        Personne.Prenom = "Fantasio"        '// Ok, on peut changer le prenom
        Personne.DateNaissance = DateSerial(1970, 3, 21)        '// Ko, la date de naissance est en lecture seule
    End Sub
    Dernier point concernant l'utilisation du mot clef Friend:
    Ce dernier indique que la fonction membre ne peut être appelée que dans le projet où la classe est définie.
    Ce qui, dans la cadre des applications multi projets, permet d'enforcer l'utilisation du module Factory.

  10. #10
    Membre Expert
    Profil pro
    Inscrit en
    Juillet 2006
    Messages
    1 508
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 508
    Par défaut
    Citation Envoyé par Sup93400 Voir le message
    Ce que je veux faire avec ce tableau :

    • Le parcourir
    • A chaque ligne, construire un objet "horaire" (l'objet qui va contenir des voyages) s'il n'existe pas déjà
    • A chaque ligne, construire un objet "voyage" (s'il n'existe pas déjà) dans l'horaire concerné
    Je pense qu'il y a une erreur de conception.
    Les horaires (départ / arrivée) sont des caractéristiques d'un voyage, et non l'inverse.

  11. #11
    Membre averti
    Homme Profil pro
    Étudiant
    Inscrit en
    Janvier 2016
    Messages
    19
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 32
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2016
    Messages : 19
    Par défaut
    Citation Envoyé par deedolith Voir le message
    Je pense qu'il y a une erreur de conception.
    Les horaires (départ / arrivée) sont des caractéristiques d'un voyage, et non l'inverse.
    Bonjour deedolith, c'est vrai que les noms portent à confusion mais non il n'y a pas d'erreur de conception, je te re explique un peu mieux mes données pour te donner toutes les billes. Admettons le tableau de données ci-dessous :

    Nom : photo1.PNG
Affichages : 502
Taille : 37,5 Ko

    Dans ce fichier, on voit :

    • La colonne "C" qui représente les horaires des points de voyage. Je n'ai pas commencé à travailler sur cette partie mais en effet lorsque le code s'occupera de cette colonne, il construira bien une liste d'horaire de point de voyage à l'intérieur d'un objet voyage car comme tu le mentionnes, un voyage contient des points horaire mais non l'inverse
    • La colonne "I" par contre, elle, est la colonne affichant l'id de l'objet "horaire" contenant les voyages. C'est perturbant mais sur le logiciel sur lequel je travaille pour mon projet et duquel j'extraie ces données et un logiciel dans lequel l'objet macro qui contient les voyages s'appelle aussi "horaire". Donc ici, ce que tu vois dans la colonne "I" ceux sont des noms de contenant d'horaire. Et donc lorsque le code parcours cette colonne, il doit créer un nouvel objet cHoraire pour chaque nouvelle valeur trouvée dans cette colonne


    Est-ce déjà plus clair pour toi ?

    Alors, par rapport à hier j'ai remarqué que si j'écrivais ma property comme ceci je n'avais plus de message d'erreur de la part de VBA :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Public Property Let addTripToVSC(numVoy, voy)
     
       Set mListeVoyages(numVoy) = voy
     
    End Property
    La différence par rapport à hier c'est que j'ai retiré les types de données sur "numVoy" et "voy" dans les variables passées à la property. Mais pourquoi donc avais-je besoin de faire cela pour que ça fonctionne ?


    Mais maintenant j'ai un problème sur une autre property :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    Public Property Get getTrip(numVoy) As cVoy
     
      getTrip = mListeVoyages(numVoy)
     
    End Property
    J'aimerais utiliser cette property dans mon module principal afin de récupérer un voyage dans mon horaire construit. Pour rappel, je mais ci-dessous tout le code qui parcourt le tableau de données :

    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
    '[PARCOURIR LE TABLEAU DE DONNEES]
    With Range(nomPlage)
     
        'Attention, avec un "tableau", il faut commencer à 1 et pas à 2 car les en-têtes ne sont pas comptées dans les lignes
        For i = 1 To .Rows.count
     
            numVoyage = CStr(.Cells(i, "A").Value)
            nomPoint = CStr(.Cells(i, "B").Value)
            heurePoint = CStr(.Cells(i, "C").Value)
            nomHoraire = CStr(.Cells(i, "I").Value)
            idDesserte = CStr(.Cells(i, "M").Value)
            jourVoyage = CStr(.Cells(i, "L").Value)
            codeVoyage = numVoyage & "|" & idDesserte
     
     
            '[CONTROLE A CHAQUE LIGNE]
            If manchette1 = "" And manchette2 = "" Then
                manchette1 = CStr(.Cells(i, "N").Value)
                manchette2 = CStr(.Cells(i, "O").Value)
            End If
     
            '[PRESENCE POINT VIDE]
            If presencePointVide = False Then
                If nomPoint = "" Then
                    logPointVide = "La ligne " & i & " est sans lieu"
                    presencePointVide = True
                End If
            End If
     
     
     
            '[CREATION HORAIRE]
            If Not dictHoraires.Exists(nomHoraire) Then
     
                nouvelHoraire = nomHoraire 'l'id de l'horaire est unique et suffit à l'identification d'un nouvel objet cHoraire
                Set nouvelHoraire = New cHoraire
                Set dictHoraires(nomHoraire) = nouvelHoraire
     
            End If
     
     
            '[CREATION VOYAGE]
            If dictHoraires(nomHoraire).tripIsInVsc(codeVoyage & "_" & nomHoraire) = False Then
     
                nouveauVoyage = codeVoyage & "_" & nomHoraire 'Pour identifier un voyage, il est préférable de lui créer un code unique sur la base de sa desserte commerciale
                Set nouveauVoyage = New cVoy
                nouveauVoyage.numero = numVoyage
                nouveauVoyage.direction = CStr(.Cells(i, "D").Value)
                dictHoraires(nomHoraire).addTripToVSC(codeVoyage) = nouveauVoyage
     
            End If
     
            Dim test As New cVoy
     
            '[TEST]
            test = dictHoraires(nomHoraire).getTrip(codeVoyage)
     
     
        Next i
     
    End With
    C'est au moment de faire la ligne : "test = dictHoraires(nomHoraire).getTrip(codeVoyage)" que j'ai un message d'erreur de VBA :


    Nom : photo2.PNG
Affichages : 515
Taille : 4,0 Ko

    Est-ce que vous auriez des idées de pourquoi je n'arrive pas à récupérer un objet voyage une fois qu'il est construit dans mon objet cHoraire ?

    Merci d'avance

    Guillaume

  12. #12
    Rédacteur/Modérateur

    Avatar de Jean-Philippe André
    Homme Profil pro
    Architecte Power Platform, ex-Développeur VBA/C#/VB.Net
    Inscrit en
    Juillet 2007
    Messages
    14 682
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 41
    Localisation : Canada

    Informations professionnelles :
    Activité : Architecte Power Platform, ex-Développeur VBA/C#/VB.Net
    Secteur : Finance

    Informations forums :
    Inscription : Juillet 2007
    Messages : 14 682
    Par défaut
    Salut,

    GetTrip retourne un objet, donc à minima un Set serait de bon aloi
    Cycle de vie d'un bon programme :
    1/ ça fonctionne 2/ ça s'optimise 3/ ça se refactorise

    Pas de question technique par MP, je ne réponds pas

    Mes ouvrages :
    Migrer les applications VBA Access et VBA Excel vers la Power Platform
    Apprendre à programmer avec Access 2016, Access 2019 et 2021

    Apprendre à programmer avec VBA Excel
    Prise en main de Dynamics 365 Business Central

    Coffrets disponibles de mes ouvrages : https://www.editions-eni.fr/jean-philippe-andre
    Pensez à consulter la FAQ Excel et la FAQ Access

    Derniers tutos
    Excel et les paramètres régionaux
    Les fichiers Excel binaires : xlsb,

    Autres tutos

Discussions similaires

  1. Réponses: 4
    Dernier message: 08/02/2008, 13h01
  2. Réponses: 1
    Dernier message: 03/04/2007, 12h02
  3. Réponses: 3
    Dernier message: 09/01/2007, 09h44
  4. PB de passage d'argument dasn une classe
    Par Naelhem dans le forum C++
    Réponses: 13
    Dernier message: 26/10/2006, 20h03
  5. [VB.NET] passage d'arguments d'une classe(form1) à une autre
    Par zouhib dans le forum Windows Forms
    Réponses: 5
    Dernier message: 05/05/2006, 16h54

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