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 :

Petit problème de compréhension sur des dictionnaires


Sujet :

Macros et VBA Excel

  1. #1
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 17
    Points : 9
    Points
    9
    Par défaut Petit problème de compréhension sur des dictionnaires
    Bonjour à tous et merci d'avoir pris quelques minutes de votre temps!

    Je sais.
    Je sais que lire un code qu'on a pas écrit c'est chiant.
    Je sais que lorsqu'on a qu'une partie des infos c'est chiant.


    La situation est simple: On a demandé au pauvre stagiaire de checker un super programme (qui ne fonctionne plus) fait il y a quelques temps par un Ingé info qui s'était perdu dans mon service.

    Pour l'instant j'essaye de comprendre comment il a fait, je commente entièrement le code mais là je bloque

    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
     
     
    Public Sub AddToDictionary(ByRef iSrcDictionary, _
                    ByVal iReference As String, _
                    ByVal iCategory As String, _
                    ByVal iDetails As String, _
                    Optional ByVal iAmount As Single = 0)
        Dim lAddFlag As Boolean
        Dim lTmpDico1, lTmpDico2
        Dim lAmount As Single
     
        lAddFlag = True
        lAmount = 0
     
        'Vérifie si la clé (ireference) existe dans le dictionnaire
        If iSrcDictionary.exists(iReference) Then
            'Alors on copie tous les éléments de la clé (ireference) dans un second dictionnaire
            Set lTmpDico1 = iSrcDictionary.Item(iReference)
            'Si icategory existe dans le dictionnaire temporaire alors
            If lTmpDico1.exists(iCategory) Then
                'On copie tous les éléments dans un troisième dictionnaire
                Set lTmpDico2 = lTmpDico1.Item(iCategory)
                ' Only keeps distinct values
                'Si idetails existe dans le troisième dictionnaire alors
                If lTmpDico2.exists(iDetails) Then
                    'On assigne à la variable lAmount la conversion en single
                    lAmount = CSng(lTmpDico2.Item(iDetails))
                    'On supprime idetails du troisième dictionnaire
                    lTmpDico2.Remove iDetails
                End If
                'On supprime icategory du second dictionnaire
                lTmpDico1.Remove iCategory
            Else
                'Si icategory n'existe pas dans le second dictionnaire temporaire
                'alors on créer un troisème dictionnaire
                Set lTmpDico2 = CreateObject("Scripting.Dictionary")
            End If
            'on supprime ireference de iDico
            iSrcDictionary.Remove iReference
        Else
            'Si iReference n'existe pas dans iDico alors on créer deux dictionnaires
            Set lTmpDico1 = CreateObject("Scripting.Dictionary")
            Set lTmpDico2 = CreateObject("Scripting.Dictionary")
        End If
     
        'Si lAddFlag est vrai alors
        If lAddFlag Then
            'On ajoute au troisième dictionnaire idetails et la somme de lAmount et iAmount
            lTmpDico2.Add iDetails, lAmount + iAmount
            'On ajoute au deuxième dictionnaire iCategory et le troisième dictionnaire(?)
            'On ajoute au premier dictionnaire ireference et le second dictionnaire(?)
            lTmpDico1.Add iCategory, lTmpDico2
            iSrcDictionary.Add iReference, lTmpDico1
     
            'On réinitialise les deux dictionnaires
            Set lTmpDico1 = Nothing
            Set lTmpDico2 = Nothing
        End If
    End Sub
    Je me suis renseigné sur les dictionnaires via les tutos developpez (toujours très bien faits d'ailleurs) et autres et donc je commence à piger comment cela fonctionne. Mon problème se situe sur ces deux lignes:

    lTmpDico1.Add iCategory, lTmpDico2
    iSrcDictionary.Add iReference, lTmpDico1

    Il me semble bien avoir lu qu'un dictionnaire ne peut pas en contenir un autre donc je comprends pas trop ce que font ces lignes. Je pense que cela rajoute les éléments des tableaux temporaires qui correspondent aux clés iCategory et iReference à iSrcDictionary mais j'en mettrais pas ma main à couper.

  2. #2
    Invité
    Invité(e)
    Par défaut
    Salut,
    Citation Envoyé par nhug1 Voir le message
    Il me semble bien avoir lu qu'un dictionnaire ne peut pas en contenir un autre donc je comprends pas trop ce que font ces lignes.
    On peut bien mettre un Object dans le Value (Item) d'un Dictionary .

    @+

  3. #3
    Invité
    Invité(e)
    Par défaut
    Bonsoir,
    Tu as n'as pas bien lu, c'est justement l'intérêt des collections ou le dictionnary, de pouvoir ce cascader.

    Excel par exemple est une class et une collection collectionne des classes, Excel dispose d'une collection de classeur, chaque classeur dispose d'une collection d'onglets, chaque onglets une collection de cellules.

    Une collection c'est également une classe.

    Une collection c'est comme un tableau don il serait possible de nommer chaque item key.
    Le key est une sorte de changement de rail qui aiguille vers tel ou tel éléments du tableau.

    collection permet de hiérarchisez ses élément rdurupt ->pays-> ville -> adresse.

  4. #4
    Inactif  

    Homme Profil pro
    cuisiniste
    Inscrit en
    Avril 2009
    Messages
    15 379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : cuisiniste
    Secteur : Bâtiment

    Informations forums :
    Inscription : Avril 2009
    Messages : 15 379
    Points : 12 075
    Points
    12 075
    Billets dans le blog
    8
    Par défaut heu
    bonjour
    c'est normal que cela fonctionne plus
    je nai pas vu cette forme d'ecriture depuis des années

    le dictionnaire est un object on le trouve dans la librairie scripting runtime

    cette ecriture ne fonctionnera plus jamais
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Set lTmpDico2 = lTmpDico1.Item(iCategory)
    car ecrit comme ca lTmpDico2 devient une variable contenant la valeur de l'item mais en aucun cas devient un dictionnaire

    donc effectivement tout le reste plante aussi

    pour alimenter un dictionnaire il faut le créer d'abords soit directement en activant les references scripting runtime
    et set mydictionary=newdictionary

    soit en late binding
    set my dictionnary=createobject("scripting.dictionary")

    et c'est qu'ensuite que l'on peut alimenter
    my dictionary.add truc,bidule

    ou
    directement my dictionary(truc)=bidule

    les dictionaires ont une cle,un item et rien d'autre pour chaque ligne

    donc toute la conception est a revoir

    ce code doit avoir quelques années quand meme a mon avis ou le createur a quelques années de retard en VBA
    mes fichiers dans les contributions:
    mail avec CDO en vba et mail avec CDO en vbs dans un HTA
    survol des bouton dans userform
    prendre un cliché d'un range

    si ton problème est résolu n'oublie pas de pointer : : ça peut servir aux autres
    et n'oublie pas de voter

  5. #5
    Invité
    Invité(e)
    Par défaut
    Bonjour,
    Pas vraiment d'acore, lTmpDico2 fait référence à l'objet contenu dans l'item, si c'est une sous collection elle récupères la branche de la sous collection!

    La véritable question est de savoir précisément quel rôle à le pauvre stagiaire dans tous ça!

    Checker les points litigieux ou s'approprier l'application? La proposition 2 est quasi impossible.

    Il faut répertoriés les fonctions bloquante et réécrire tout ou partie des méthode litigeuse de façon a contourner le problème tout en restituant le contexte!

    Pour résoudre ton problème il faut approprié les méthodes de débogage. Te positionner dans la sub principale et faire du pas a pas, notes que ton programme vas rencontrer de multiples méthodes si tu appuis sur majuscule et F8, tu exécute la méthode du'un seule coup.

    Tu check ok ko et tu continu. Si le problème ce pose sur un sous sub tu place un point d'arrêt et fais la même chose dans la sous sub pour trouver l'endroit exacte de l'erreur. Attention l'erreur peut venir d'une mauvaise initialisation dz variable dans la méthode appelante.

    Quand tu as trouvé l'endroit exacte soit c'est facile de corriger soit tu réécrire la méthode.
    Dernière modification par Invité ; 25/11/2015 à 08h13.

  6. #6
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 17
    Points : 9
    Points
    9
    Par défaut
    Merci pour toutes vos réponses, je vais tâcher de répondre précisément:

    1°) Je me suis mal exprimé. Ce programme va chercher des données dans deux classeurs excel différents et essayer de matcher le plus de données possible. Le problème actuel vient des deux fichiers sources (extractions d'une base de données), qui ne sont plus formatés de la même manière (les noms de certaines données à tout simplement changé) . Le programme fonctionne très bien, il est rapide et tout.

    2°) Pour ce qui est de " Set lTmpDico2 = lTmpDico1.Item(iCategory) " Cette écriture m'avait également paru bizarre mais ça fonctionne comme sur des roulettes ici (Excel 14.0 avec application.version) et je crois savoir pourquoi:
    Si on part du principe que le dictionnaire (iSrcdictionnay) est vide au départ lorsqu'on initialise la sub, la première clé sera forcément absente de iSrcdictionary. On passe au else et là on créer les deux dictionnaires. Non?

    3°) Le code a été fait il y a 2-3 ans effectivement mais cette sub n'est qu'une fonction parmis... tant d'autres dans ce programme, je ne me prononcerais pas sur la conception en tant que telle, vous êtes meilleurs juges!

    4°) Quel est le rôle du stagiaire? De commenter entièrement le code pour mes collègues et de l'adapter pour les nouvelles données. Pour l'instant j'ai commenté 50% du code en suivant le cheminement du programme. Je bute de temps en temps. Je vais sur developpez.net. J'apprends. Je ne bute plus.

    5°) par rapport à mon problème de base:

    c'est noté, on peut mettre un object dans un dictionnaire. Donc si je comprends bien (je me permet de reposer une partie du code avec de nouveaux commentaires):

    Encore une fois merci de m'avoir accordé votre attention les amis!

    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
     
     
    'Présupposé: Le dictionnaire sur lequel s'effectue addtodictionnary est vide au départ (je crois que ça rend tout plus logique)
    'But de la sub: Cette sub a pour but de vérifier les données avant de les ajouter à un dictionnaire pour éviter les doublons etc
     
     'Imaginons que c'est la première fois que l'on veut ajouter quelque chose au dictionnaire. Il est vide donc la condition du IF n'est pas remplie. On passe au ELSE.
     If iSrcDictionary.exists(iReference) Then
            Set lTmpDico1 = iSrcDictionary.Item(iReference)
            'Si icategory existe dans le dictionnaire temporaire alors
            If lTmpDico1.exists(iCategory) Then
                'On copie tous les éléments dans un troisième dictionnaire
                Set lTmpDico2 = lTmpDico1.Item(iCategory)
                ' Only keeps distinct values
                'Si idetails existe dans le troisième dictionnaire alors
                If lTmpDico2.exists(iDetails) Then
                    'On assigne à la variable lAmount la conversion en single
                    lAmount = CSng(lTmpDico2.Item(iDetails))
                    'On supprime idetails du troisième dictionnaire
                    lTmpDico2.Remove iDetails
                End If
                'On supprime icategory du second dictionnaire
                lTmpDico1.Remove iCategory
            Else
                'Si icategory n'existe pas dans le second dictionnaire temporaire
                'alors on créer un troisème dictionnaire
                Set lTmpDico2 = CreateObject("Scripting.Dictionary")
            End If
            'on supprime ireference de iDico
            iSrcDictionary.Remove iReference
        Else
            'Si iReference n'existe pas dans iDico alors on créer deux dictionnaires
            'Donc plus de problème quant à l'initialisation des dictionnaires
            Set lTmpDico1 = CreateObject("Scripting.Dictionary")
            Set lTmpDico2 = CreateObject("Scripting.Dictionary")
        End If
     
        'Si lAddFlag est toujours vrai comme déclaré plus haut
        If lAddFlag Then
            '*On ajoute au troisième dictionnaire idetails en clé et la somme des deux en Item
            lTmpDico2.Add iDetails, lAmount + iAmount
            '*On ajoute au deuxième dictionnaire iCategory en clé le troisième dictionnaire en item       
            lTmpDico1.Add iCategory, lTmpDico2
            '*On ajoute au dictionnaire ireference en clé et dico1 en item 
            iSrcDictionary.Add iReference, lTmpDico1
     
            'On réinitialise les deux dictionnaires
            Set lTmpDico1 = Nothing
            Set lTmpDico2 = Nothing
        End If

  7. #7
    Invité
    Invité(e)
    Par défaut
    bonjour,
    tu parle que certain format de donné ont changés, quel sont ces changement?
    par exemple la nom de la colonne toto est devenu titi?

    dans ce cas il est possible de faire un switch
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    DicoTranslat.add "titi","toto"
    et dans ton code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Set lTmpDico2 = lTmpDico1.Item(DicoTranslat("toto"))
    et la ton tu minimise les modifications dans ton code!

    de quel ordre son les modification de format de données?

  8. #8
    Futur Membre du Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2014
    Messages
    17
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 33
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Étudiant
    Secteur : Finance

    Informations forums :
    Inscription : Mai 2014
    Messages : 17
    Points : 9
    Points
    9
    Par défaut
    hello rdurupt!

    Je sais pas si ça te parle mais je travaille avec Business Object et on a changé d'univers, j'ai dû refaire toutes les requêtes pour les extractions et il se trouve que je ne peux pas avoir exactement les mêmes données qu'avant dans les extractions (du moins 15-20%).

    Le nombre de colonnes (ajout de certaines, suppression d'autres), leurs entêtes ainsi que la forme des données également. Dans les faits cela peut être assez mineur ( france devient "territory-FR") par exemple. J'ai déjà créé une petite routine qui se charge de changer ça.

    Pour te répondre plus clairement, je suis en mesure d'adapter 50% des choses qui ont changé et pour voir l'étendue des dégâts (ou l'absence de dégâts) il faut que j'aille au bout du code pour comprendre tout ce qui a changé.

    Je suis en mesure de faire tourner le programme avec les extractions de l'année dernière, tout roule nickel.

    Mon problème principal est que je viens de passer du stade "je-suis-un-noob-d'école-de-commerce" à "j'arrive-à-comprendre-un-peu-VBA"

    Donc là en l'occurence, je découvre comment on peut utiliser les dictionnaires de manière un peu plus fine.

    est-ce que vous êtes d'accord avec mes commentaires dans le code où j'ai loupé un truc?

Discussions similaires

  1. Réponses: 5
    Dernier message: 11/10/2012, 12h53
  2. [MySQL] Problème de requête sur des dates
    Par dahu29 dans le forum Langage SQL
    Réponses: 3
    Dernier message: 14/03/2006, 13h08
  3. Problème d'id sur des sous formulaires.
    Par antier dans le forum Access
    Réponses: 4
    Dernier message: 07/01/2006, 16h53
  4. Petit problème de conception sur access
    Par coooookinette dans le forum Modélisation
    Réponses: 3
    Dernier message: 18/12/2005, 18h24
  5. Problème de *pointeur sur des char
    Par Spartan03 dans le forum C++
    Réponses: 2
    Dernier message: 18/09/2005, 14h20

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