Petite assistance d'appoint utilisation modules de service OutIdx

david84

XLDnaute Barbatruc
Bonjour,

Je viens de tester la version du Dictionnaire arborescent fourni par l'ami Dranreb dans cette discussion.

Dans ce fil, le but était de proposer un outil permettant de produire des listes déroulantes en cascade.
Ayant détecté quelques bugs, autant en faire part au créateur de cet outil afin qu'il puisse y apporter lui-même les solutions adéquates.

Voici quelques bugs relevés :
- la sélection issue de la liste de validation ne s'affiche pas lorsque la colonne traitée comporte des dates ou nombres (sélectionner la cellule D10 en orange de l'onglet "liste_déroulante") : cela est dû au fait que dans la Sub Cascade la variable Z est actuellement en String

- bug à la ligne
Code:
 Target.Validation.Add xlValidateList, Formula1:=Join(DicArb(C).Keys, ",")
de la Sub Worksheet_SelectionChange lorsque la liste de validation est vide (sélectionner la cellule C12 en rougede l'onglet "liste_déroulante") : cela peut arriver lorsque la plage de données comporte des cellules vides

- si je sélectionne la cellule D13 en vert et que je choisi l'autre item (sw2 3906) je pense qu'il faudrait effacer le contenu de la cellule en E13 (comme cela est le cas pour les cellules des colonnes A, B, C et D : par ex choisir en C14 france télécom à la place de orange pour le constater) afin d'obliger l'utilisateur à modifier le contenu de E13 qui n'est alors plus correct.

2 remarques également en passant même si cela n'a rien à voir avec l'utilisation du module de classe :
- lorsque le fichier plante il faut repasser "manuellement" Application.EnableEvents = True. Peut-être gérer cela dans le cadre d'une gestion d'erreur afin que l'utilisateur ne se retrouve pas avec un fichier qui ne répond plus
- rendre plus simple l'adaptation du fichier à une plage de cellule comportant plus ou moins de colonnes que les 5 pour lesquelles les macros sont faites afin de ne pas avoir besoin d'aller chercher dans le code pour l'adapter.

A+
 

Pièces jointes

  • ValidDicArb2_tests.xls
    106 KB · Affichages: 36

Dranreb

XLDnaute Barbatruc
Re : Petite assistance d'appoint utilisation modules de service OutIdx

Bonjour.

Au premier examen, les modules de service ne sont pas les plus récents.
Pour limiter la difficulté des adaptations, j'ai un module de classe ListesLiées permettant de limiter considérablement le code applicatif.
Les validations ne seraient plus modifiées mais prises d'une feuille supplémentaire où elles seraient connues par des noms et rectifiées en conséquence des choix effectués. (P.S. d'ailleurs je ne sais pas trop ce qui ce qui se passe avec Target.Validation.Add xlValidateList, Formula1:=Join(DicArb(C).Keys, ",") lorsqu'il y a des dates parmi les clés ! Ça se passe déja mal quand il n'y en a qu'une et qu'elle est vide ! Alors autant ne plus changer les validations, mais seulement le contenu des listes)
Mais il autorise le renseignement des listes déroulantes dans n'importe quel ordre. Est-ce gênant ou au contraire mieux ?
Je peux écrire un module ListesCasc si tu veux pour faire le pendant du ComboBoxCasc pour les Userform, mais ce dernier ne m'a plus jamais été demandé depuis qu'il y a le ComboBoxLiés. Qui peut le plus peut le moins après tout.

Ça ne plante plus à la C12 en mettant :
VB:
Z = Join(DicArb(C).Keys, ",")
    If Z = "" Then
      Target.Validation.Add Type:=xlValidateTextLength, AlertStyle:=xlValidAlertStop, _
        Operator:=xlBetween, Formula1:="0", Formula2:="0"
    Else
      Target.Validation.Add xlValidateList, Formula1:=Z: End If

Pour le bogue de l'effacement qui ne se faisait pas de la cellule de la dernière colonne, je propose cette réécriture de la procédure Cascade :
VB:
Private Sub Cascade()
Dim C As Long, V As Variant, IlExiste As Boolean
If DicArb(1) Is Nothing Then
'   ClésDicoNonString = True
   Set DicArb(1) = DictionnArbo(Feuil1.[A2].Resize(Feuil1.UsedRange.Rows.Count - 1, 5))
'   ClésDicoNonString = False
   End If
For C = 1 To 5
   Me.Cells(LCou, C).Validation.Delete
   V = Me.Cells(LCou, C).Value
   IlExiste = Not DicArb(C) Is Nothing
   If IlExiste Then IlExiste = DicArb(C).Exists(V)
   If IlExiste Then
      If DicArb(C).Count = 1 Then Me.Cells(LCou, C).Value = DicArb(C).Keys
      If C < 5 Then Set DicArb(C + 1) = DicArb(C)(V)
   Else
      Me.Cells(LCou, C).ClearContents
      If C < 5 Then Set DicArb(C + 1) = Nothing
      End If
   Next C
End Sub
Les 2 instructions en commentaires ne deviendront nécessaires qu'avec le nouveau module MDictionnArbo
Si tout marche suffisamment mieux comme ça, d'accord. Mais je n'ai vraiment plus très confiance en la spécification de listes en dur comme ça avec un Join, surtout si on veut en plus que ce puisse aussi être n'importe quoi d'autre que des String…
Quelle suite veux tu que je donne maintenant ?

Enfin je le joins toujours comme il est. Continue les tests.
 

Pièces jointes

  • ValidDicArbDavid84.xls
    157.5 KB · Affichages: 34
Dernière édition:

david84

XLDnaute Barbatruc
Re : Petite assistance d'appoint utilisation modules de service OutIdx

Bonsoir,

en attendant de te relire plus tranquillement demain, un petit retour de test avant d'aller me coucher : concernant le plantage en C12 le correctif semble convenir.

Par contre je trouve le nouveau code de la Sub Cascade moins intéressant que le précédent car tu perds l'aspect dynamique qui permet de renseigner la ou les cellules suivantes si tu n'as qu'un choix possible existant. Avec le nouveau code tu es obligé de sélectionner l'item de la liste même s'il est unique alors qu'avec le précédent code la cellule est incrémentée automatiquement.

Concernant ce bogue de l'effacement qui ne se faisait pas de la cellule de la dernière colonne l'insertion de
Code:
  Application.EnableEvents = False
  
  If Target.Column < 5 Then _
  Range(Cells(Target.Row, Target.Column + 1), Cells(Target.Row, 5)).ClearContents

  Cascade
  'InfoAssociée
  Application.EnableEvents = True
dans la Sub Worksheet_Change semble pallier le problème mais c'est une solution "bourrin" en attendant d'étudier plus attentivement la procédure.

Pour le reste je verrai demain.
A+
 

Dranreb

XLDnaute Barbatruc
Re : Petite assistance d'appoint utilisation modules de service OutIdx

Bonjour.

En revenant un peu en arrière, c'est à dire plus proche du code d'origine :
VB:
Private Sub Cascade()
Dim C As Long, V As Variant
If DicArb(1) Is Nothing Then
   ClésDicoNonString = True
   Set DicArb(1) = DictionnArbo(Feuil1.[A2].Resize(Feuil1.UsedRange.Rows.Count - 1, 5))
   ClésDicoNonString = False
   End If
For C = 1 To 5
   Me.Cells(LCou, C).Validation.Delete
   If DicArb(C) Is Nothing Then
      Me.Cells(LCou, C).ClearContents
      If C < 5 Then Set DicArb(C + 1) = Nothing
   Else
      If DicArb(C).Count = 1 Then Me.Cells(LCou, C).Value = DicArb(C).Keys
      V = Me.Cells(LCou, C).Value
      If DicArb(C).Exists(V) Then
         If C < 5 Then Set DicArb(C + 1) = DicArb(C)(V)
      Else
         Me.Cells(LCou, C).ClearContents
         If C < 5 Then Set DicArb(C + 1) = Nothing
         End If: End If: Next C
End Sub
Il était pas mal au fond le 1èr code. Le seul problème c'était que le Me.Cells(LCou, C).ClearContents devait être fait même si C = 5, il n'y avait que le Set DicArb(C + 1) = Nothing qui ne devait être fait que si C < 5
 

david84

XLDnaute Barbatruc
Re : Petite assistance d'appoint utilisation modules de service OutIdx

Bonjour,
La Sub Cascade du message précédent semble avoir quelques petits problème d'affinage...
je t'ai placé un nouveau fichier avec une autre petite base de données et ton code actualisé pour que tu puisses comprendre :
Clique en D3 et sélectionne le millésime 2000 dans la liste. Normalement lorsque tu sélectionnes 2000 E3 doit alors être vide puisque tu as différents choix existants. Hors ce n'est pas le cas.
C'est bizarre parce que sur l'autre base de données (celle du post 1) cela me semble fonctionner mais pas là.
Je vais y regarder de plus près de mon côté également dès que j'ai le temps.
A+
 

Pièces jointes

  • ValidDicArbDavid84_test.xls
    147.5 KB · Affichages: 31

Dranreb

XLDnaute Barbatruc
Re : Petite assistance d'appoint utilisation modules de service OutIdx

Ça se discute. Il y a plusieurs choix possible, d'accord, mais "Bouteille" préexistait dans la cellule et est compatible avec la nouvelle clé. D'autre contextes d'utilisation pourrait faire voir dommage que ce soit effacé. Mais ça peut peut être se résoudre aisément comme ça :
VB:
Private Sub Worksheet_Change(ByVal Target As Range)
If Target.Row < 3 Then Exit Sub
LCou = Target.Row
Application.EnableEvents = False
Cascade Target.Column
'InfoAssociée
Application.EnableEvents = True
End Sub
'

Private Sub Cascade(Optional ByVal CChg As Long = &H8FFFFFFF)
Dim C As Long, V As Variant
If DicArb(1) Is Nothing Then
   ClésDicoNonString = True
   Set DicArb(1) = DictionnArbo(Feuil1.[A2].Resize(Feuil1.UsedRange.Rows.Count - 1, 5))
   ClésDicoNonString = False
   End If
For C = 1 To 5
   Me.Cells(LCou, C).Validation.Delete
   If DicArb(C) Is Nothing Then
      Me.Cells(LCou, C).ClearContents
      If C < 5 Then Set DicArb(C + 1) = Nothing
   Else
      If DicArb(C).Count = 1 Then Me.Cells(LCou, C).Value = DicArb(C).Keys
      V = Me.Cells(LCou, C).Value
      If DicArb(C).Exists(V) Then
         If C < 5 Then
            Set DicArb(C + 1) = DicArb(C)(V)
            If C >= CChg And DicArb(C + 1).Count > 1 Then Me.Cells(LCou, C + 1).ClearContents
            End If
      Else
         Me.Cells(LCou, C).ClearContents
         If C < 5 Then Set DicArb(C + 1) = Nothing
         End If: End If: Next C
End Sub
Si on veut que les valeurs compatibles soient gardées il suffit de ne pas préciser de paramètre au Cascade.
 

david84

XLDnaute Barbatruc
Re : Petite assistance d'appoint utilisation modules de service OutIdx

Oui bien sûr que cela se discute et ce n'est que mon avis !
En l'état le code pose le problème suivant : lorsque je sélectionne une des cellules 2 à 5 de la ligne les valeurs des autres cellules sont effacées.
Mon idée est que la ou les cellules placées à la droite de celle sélectionnées soient vidées lorsque le dico.keys >1 mais uniquement si l'on change le contenu de la cellule sélectionnée (pas lors de sa sélection).
Mais c'est effectivement une bonne idée de laisser à l'utilisateur le fait de garder ou non une valeur affichée compatible.
A+
 

Dranreb

XLDnaute Barbatruc
Re : Petite assistance d'appoint utilisation modules de service OutIdx

Il n'y a de toute façon pas de paramètre à préciser dans la Worksheet_SelectionChange. Seulement dans la Worksheet_Change.
P.S. Zut ! Une erreur bête: corriger &H8FFFFFFF c'est un nombre négatif, tout le contraire de ce que je voulais !
VB:
Private Sub Cascade(Optional ByVal CChg As Long = &H7FFFFFFF)
 
Dernière édition:

david84

XLDnaute Barbatruc
Re : Petite assistance d'appoint utilisation modules de service OutIdx

Il n'y a de toute façon pas de paramètre à préciser dans la Worksheet_SelectionChange. Seulement dans la Worksheet_Change.
P.S. Zut ! Une erreur bête: corriger &H8FFFFFFF c'est un nombre négatif, tout le contraire de ce que je voulais !
VB:
Private Sub Cascade(Optional ByVal CChg As Long = &H7FFFFFFF)

J'ai fait quelques tests et cela semble concluant.
Je testerai de façon plus approfondie demain.
Une question toutefois : quel intérêt y a t-il à utiliser une valeur Hexadécimale et non une valeur décimale dans
Code:
ByVal CChg As Long = &H7FFFFFFF
? Et pourquoi une valeur si élevée ? Pourquoi un Long (tu me diras pourquoi pas après tout mais peut-être y-a-t-il une raison qui m'échappe) ?
A+
 

Dranreb

XLDnaute Barbatruc
Re : Petite assistance d'appoint utilisation modules de service OutIdx

Bof, il n'y a pas de raison spéciale, j'avais en tête l'idée d'un nombre plus élevé que… mais j'ai abrégé mentalement en … "tous les autres" ! L'exprimer en Hexadécimal aurait du me permettre de ne pas faire d'erreur…
Je prends toujours des Long pour les entiers, sauf s'ils sont attendus ou rendus d'un autre type par une fonction, une API etc. même si je ne sais plus si ce sont encore des images de registres CPU dans ceux à 64 bits.
 

david84

XLDnaute Barbatruc
Re : Petite assistance d'appoint utilisation modules de service OutIdx

Bonjour,
j'ai testé plus avant et tout semble fonctionner correctement.
C'est vraiment du beau travail.
Le problème c'est qu'en l'état l'utilisateur est obligé de modifier le code pour pouvoir l'adapter ce qui n'est pas évident.
Pourquoi ne pas intégrer ton DicoArbo dans un module de classe et de créer une méthode dans le genre DicoArbo.Liste(Plage des valeurs, colonne de la 1ère liste, colonne de la dernière liste, garder ou non les valeurs compatibles,etc.) ? Cela faciliterait la vie de l'utilisateur qui pourrait alors l'utiliser comme n'importe objet.

Code:
 j'ai un module de classe ListesLiées permettant de limiter considérablement le code applicatif.
Les validations ne seraient plus modifiées mais prises d'une feuille supplémentaire où elles seraient connues par des noms et rectifiées en conséquence des choix effectués.
...
Mais il autorise le renseignement des listes déroulantes dans n'importe quel ordre. Est-ce gênant ou au contraire mieux ?
Je ne sais pas il faudrait que je regarde cela. Il est disponible où ce module ?
A+
 

Dranreb

XLDnaute Barbatruc
Re : Petite assistance d'appoint utilisation modules de service OutIdx

Bonjour.
ListesLiées n'est pas vraiment fait pour être utilisé avec une boucle. Mais on peut dans une certaine mesure.
J'ai quelque problèmes de mise au point dessus en ce moment.
En fait je ne le conseille pas. Il serait beaucoup plus pratique d'utiliser un Userform qui s'afficherait à la sélection d'une cellule par exemple. On y gagnerait en premier la possibilité de frapper les 1ers caractères pour se positionner dans les listes au lieu de commencer par y chercher dès le début ce qu'on veut. Souvent ça suffit pour l'atteindre, d'ailleurs. Mais on pourrait aussi afficher dans un Label le nombre de cas trouvés selon les choix déjà effectués (dans n'importe quel ordre). Renoncer à valider une recherche qui ne pouvait aboutir sans être obligé d'effacer tous les choix effectués pour rien dans les cellules. Afficher, pour vérification, d'autres informations trouvées dans la base même si on n'a pas l'intention de les reproduire dans la feuille de saisie. Lorsqu'il reste peu de possibilités, choisir simplement directement celle qu'on veut dans une ListBox montrant tous les cas correspondant aux choix effectués. Beaucoup plus souple et riche de possibilités, en somme.
ComboBoxLiés est parfait pour programmer tout ça avec peu de code.
 

Pièces jointes

  • LstLiéesDavid84.xls
    212.5 KB · Affichages: 38

david84

XLDnaute Barbatruc
Re : Petite assistance d'appoint utilisation modules de service OutIdx

Bonjour,
je trouve cet outil performant.
Bon après il y a beaucoup de code et je suis loin d'avoir tout vu mais 2 remarques tout de même si tu cherches à le rendre plus facile d'utilisation (mais bon à toi de voir bien sûr):
- actuellement lorsque une ligne de liste est complète et que tu sélectionnes à nouveau une des cellules où il n'existe qu'un choix tu ne peut plus modifier cette ligne (ou bien il te faut sélectionner plusieurs cellules de la ligne et les effacer) : ce qui est tout à fait normal au demeurant !
Suggestion : dans ce cas de figure peut-être redonner la possibilité de sélectionner la liste complète pour relancer une nouvelle sélection comme cela l'utilisateur peut modifier cette ligne;

- actuellement il n'est pas possible de placer dans l'onglet "données" une plage comportant plus de colonnes et d'augmenter le nombre de listes dans l'onglet "liste de travail" sans créer auparavant manuellement celles-ci dans le gestionnaire de noms.
Cela plante à
Code:
LL.Add FLstTrv.Range("Liste" & C), C, Me.Cells(2, C)
de la Sub InitLLSiNécessaire
Suggestion :
- soit expliquer la procédure dans le fichier en plaçant par exemple une gestion d'erreur dans cette Sub avec apparition d'une MsgBox décrivant la procédure à suivre pour créer de nouvelles listes
- soit prévoir la création de listes créées dynamiquement
A+
 

Discussions similaires

Statistiques des forums

Discussions
311 735
Messages
2 082 024
Membres
101 873
dernier inscrit
excellllll