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 :

Module de classe - Intercepter les événements d'un ActiveX sans passer par UserForm


Sujet :

Macros et VBA Excel

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Futur Membre du Club
    Homme Profil pro
    Organisateur conseil
    Inscrit en
    Août 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Organisateur conseil

    Informations forums :
    Inscription : Août 2016
    Messages : 6
    Par défaut Module de classe - Intercepter les événements d'un ActiveX sans passer par UserForm
    Bonjour à tous,

    J’ai créé un module de classe pour manipuler et paramétrer une ListBox réutilisable dans chacune de mes feuilles.
    Je n’utilise pas de UserForm, mais un ActiveX OLEObject, pour avoir plus de propriétés de mise en forme.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    MaFeuille.OLEObjects.Add(ClassType:="Forms.ListBox.1")
    Tout fonctionne parfaitement bien, au petit détail près que je ne sais pas comment intercepter les événements de l’objet.
    Il me faudrait au moins détecter le clic…

    J’ai pas mal cherché, mais toutes les solutions passent par les événements des UserForm, ce que je ne souhaite pas.

    Qui saurait me proposer une piste ?

    Guiral

  2. #2
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut
    Bonjour
    Fais cette petite expérience (même pas besoin d'un module de classe):
    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
    Private Sub CommandButton1_Click()
      With ActiveSheet.OLEObjects.Add(ClassType:="Forms.ListBox.1")
        .Name = "toto"
      End With
    End Sub
     
    Private Sub CommandButton2_Click()
      toto.Activate 'très important la première fois
      For i = 1 To 10
        toto.AddItem i
      Next
    End Sub
    Private Sub toto_Click()
      MsgBox toto.ListIndex
    End Sub
    1) la ligne qui dit toto.activate est loin d'être ici superflue
    2) tu as ta solution, mais : quel est le besoin de créer ce contrôle dynamiquement ? (je le vois mal). Dis-nous

  3. #3
    Futur Membre du Club
    Homme Profil pro
    Organisateur conseil
    Inscrit en
    Août 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Organisateur conseil

    Informations forums :
    Inscription : Août 2016
    Messages : 6
    Par défaut
    Bonjour Unparia,

    Merci pour ta solution, ça fonctionne effectivement très bien dans le module de la feuille active.
    J’ai testé comme ceci, c’est nickel :

    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
     
    Private Sub Création_ListBox_Dans_Feuille_Courante()
     
        Dim i As Variant
     
        With ActiveSheet.OLEObjects.Add(ClassType:="Forms.ListBox.1")
            .Name = "ListBoxTest"
            For i = 1 To 10
                .Object.AddItem i
            Next i
            .Activate
        End With
     
    End Sub
     
    Private Sub ListBoxTest_Click()
      MsgBox ListBoxTest.ListIndex
    End Sub
    En revanche, je ne parviens pas à affecter le bouton dans mon module de classe.
    Ci-dessous le code, épuré de tout ce qui ne nous intéresse pas :

    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
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
     
    Private clLstRef As OLEObject
     
    Private Sub class_Initialize()
    '
    ' Initialise la liste déroulante en vérifiant si l'objet existe  dans la feuille active (Worksheet_SelectionChange)
    ' Si oui, on le réutilise, si non on le crée.
    ' L'objet est de type "Forms.ListBox" son nom sera "lstRéférentiel"
    ' Une fois créé, il ne sera pas supprimé de façon à être réutilisé plus rapidement.
    ' Déclaré global au module de classe de la feuille permet de maintenir l'instance active pour tous les événements.
    '
    ' =======================================================================================
     
        ' Tente d'affecter l'objet s'il existe.
        ' Si oui, sortie inconditionnelle,
        ' Si non, débranchement sur erreur pour création de l'objet et initialisation de ses valeurs
        On Error GoTo class_Initialize_CreerListe
        Set clLstRef = ActiveSheet.OLEObjects("lstRéférentiel")
        GoTo class_Initialize_Exit
     
    ' Création de l'objet Forms.ListBox
    class_Initialize_CreerListe:
     
        Err.Clear
        On Error GoTo class_Initialize_Err
     
        ' La liste n'existe pas, on la crée, avec des valeurs par défaut
        Set clLstRef = ActiveSheet.OLEObjects.Add(ClassType:="Forms.ListBox.1")
        clLstRef.Name = "lstRéférentiel"
     
        ' Charge les valeurs initiales de paramètrage de la liste
        With clLstRef
    		' ...
    		' valeurs 
    		' ...
        End With
     
    class_Initialize_Exit:
        Exit Sub
     
    class_Initialize_Err:
        MsgBox Error$, , "Erreur n° " & Err
        Resume class_Initialize_Exit
     
    End Sub
     
    Private Sub class_Terminate()
    End Sub
     
    Public Sub Affiche(paramètres...)
    ' Affiche la liste déroulante en regard du curseur actif (ActiveCell) dans la feuille active
    ' =======================================================================================
     
        ' Affecte les valeurs calculées en fonction de la cellule active
        With clLstRef
    		' ...
    		' valeurs 
    		' ...
     		.Visible = True
            .Activate
        End With
     
    End Sub
     
    Public Sub Masque()
    ' Masque la liste dans la feuille active
    ' =======================================================================================
     
        With clLstRef
            .ListFillRange = ""
            .LinkedCell = ""
            .Visible = False
        End With
     
    End Sub
    Pour ne pas être trop long, je reviens dans un autre message pour détailler les raisons de ce choix de passer par un module de classe.

    Amicalement,

    Guiral

  4. #4
    Futur Membre du Club
    Homme Profil pro
    Organisateur conseil
    Inscrit en
    Août 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Organisateur conseil

    Informations forums :
    Inscription : Août 2016
    Messages : 6
    Par défaut
    A la question de savoir pourquoi vouloir manipuler une ListBox dynamiquement :

    Parce que je suis confronté à la demande d’utilisateurs ayant besoin de saisir un nombre de données élémentaires parfois très importants.
    Pour exemple, l’un de mes derniers projets mettait en œuvre plus de 700 données unitaires, faisant appel à plus de 50 référentiels distincts.
    Avec naturellement, interactions conditionnelles entre ces données, faisant parfois appel à des référentiels hiérarchiques, multi-colonnes, etc.

    Dans ces conditions, enfermer l’utilisateur dans une succession de fiches de saisies à répétition (UserForm) devient une contrainte perçue comme très lourde.
    Avec de plus (encore une fois…) le sentiment que la technique impose ses propres règles au détriment des besoins du métier : C’est rebutant…
    Pour moi, ce n’est pas mieux, puisque cela m’oblige à consacrer la plus grande partie de mon code à la gestion d’innombrables contrôles au détriment de l’attention portée aux données.
    Données qui sont pourtant l’essentiel du but poursuivi.

    J’ai donc trouvé la solution en organisant les données dans les feuilles comme dans un grand formulaire, où l’utilisateur peut naviguer où et comme il le souhaite.
    Il peut de plus me demander de restructurer les lignes, sections et colonnes à volonté, de manière à ce que leur présentation corresponde au plus près de sa vision métier à lui.
    Selon les besoins, je peux même lui offrir des feuilles sous formes de tables, sans limitation du nombre de lignes.
    De mon côté, les choses deviennent beaucoup plus simples : Je n’utilise plus qu’une seule ListBox que je réadapte dynamiquement à la donnée de la cellule active (ou de la colonne, s’il s’agit d’un tableau)

    J’ai donc créé un module ordinaire, dans lequel je vérifie toute les conditions requises (positions, dimensions, plages référentielles mono ou multi-colonnes, contrôles de saisie, etc.) en fonction de la cellule active.
    Certes, cela me fait beaucoup de choses à vérifier dans Worksheet_SelectionChange, mais bien construit, avec des Range correctement nommés, ça se gère très correctement.

    L’étape suivante consisterait à abandonner les paramètres, procédures et fonctions du module standard, au profit d’un paramétrage par propriétés et méthodes dans un module de classe.
    Pour l’utilisateur, ça ne changerait rien, puisque tout fonctionne déjà très bien.
    Mais pour moi, ça me permettrait d’être encore plus performant dans la gestion et maintenance de mon code, devenu plus fonctionnel et quelque part, plus élégant.

    Voili-voilou…

    Amicalement,

    Guiral.

  5. #5
    Expert confirmé
    Homme Profil pro
    aucune
    Inscrit en
    Avril 2016
    Messages
    7 563
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 84
    Localisation : France, Pyrénées Atlantiques (Aquitaine)

    Informations professionnelles :
    Activité : aucune

    Informations forums :
    Inscription : Avril 2016
    Messages : 7 563
    Par défaut
    Je n’utilise plus qu’une seule ListBox que je réadapte dynamiquement
    J'entends bien et approuve. Une seule (que l'on déplace et recharge en tant que souhaité) est plus intelligent.
    Mais pourquoi, alors, la créer dynamiquement et non en mode création ? En jouant avec sa propriété Visible on ne l'affiche que lorsque voulu et avec les propriétés que l'on veut, quant on le veut.
    Et pourquoi une Classe pour une seule ListBox ? Un simple module suffirait, si l'on veut y placer son code. Il suffirait d'y mettre des procédures Private appelées par une procédure Public (celle appelée depuis la feuille concernée) et de lui passer le(s) paramètre(s) nécessaires. Et cela éviterait d'avoir à déclarer dans la classe les évènements de ce type de contrôle (surtout pour UN SEUL) et certaines de ses propriétés.

  6. #6
    Membre chevronné
    Homme Profil pro
    Ingénieur Industrialisation
    Inscrit en
    Mai 2015
    Messages
    222
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 35
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur Industrialisation
    Secteur : Industrie

    Informations forums :
    Inscription : Mai 2015
    Messages : 222
    Par défaut
    Intéresse-toi aux déclarations "WithEvents"

  7. #7
    Futur Membre du Club
    Homme Profil pro
    Organisateur conseil
    Inscrit en
    Août 2016
    Messages
    6
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Organisateur conseil

    Informations forums :
    Inscription : Août 2016
    Messages : 6
    Par défaut
    Citation Envoyé par unparia Voir le message
    … En jouant avec sa propriété Visible on ne l'affiche que lorsque voulu et avec les propriétés que l'on veut, quand on le veut.
    C’est ce que je fais.
    Je l’ai même précisé en commentaire en tête du code.
    Sur ajout d’une nouvelle feuille, le programme crée une seule et unique fois la ListBox qui n’existe pas encore.
    Ensuite, elle reste persistante et on joue exclusivement avec .Visible True et False.

    Citation Envoyé par unparia Voir le message
    Et pourquoi une Classe pour une seule ListBox ?
    Parce qu’il faut bien commencer par quelque chose.
    Si je sais faire pour un objet, je saurai pour tous les autres, que je pourrais ensuite grouper dans une collection dédiée.

    Citation Envoyé par unparia Voir le message
    Un simple module suffirait, si l'on veut y placer son code.
    Exact, c’est ce que j’ai actuellement : Ca fonctionne très bien.

    Citation Envoyé par unparia Voir le message
    Et cela éviterait d'avoir à déclarer dans la classe les évènements de ce type de contrôle (surtout pour UN SEUL) et certaines de ses propriétés.
    Un seul contrôle aujourd’hui, autant que voulus demain…
    Avec non pas les propriétés du contrôle (ça ne serait effectivement d’aucun intérêt), mais mes propriétés à moi : mises en forme, contrôles de saisie, tests sur valeurs, types de données, affichages d’aides contextuelles, etc.

    Cela dit, il est effectivement possible que je renonce à terme à cette idée de module de classe.
    Seulement pour le savoir, je veux expérimenter.

    Et pour l’instant, ce qui me préoccupe, même si c’est idiot, c’est ce point purement technique d’interception du clic dans l’objet…

    Amicalement,

    Guiral.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Associer les propriétés d'un workbook sans passer par la méthode open
    Par c.piette dans le forum Macros et VBA Excel
    Réponses: 9
    Dernier message: 29/04/2015, 17h04
  2. Intercepter les événements souris
    Par FredericB dans le forum Composants FMX
    Réponses: 2
    Dernier message: 09/06/2013, 07h23
  3. Réponses: 14
    Dernier message: 25/11/2007, 18h32
  4. [Xlib] Intercepter les évènements
    Par Laurent Gomila dans le forum Linux
    Réponses: 67
    Dernier message: 25/07/2007, 11h00
  5. [fenetre à onglets] Intercepter les événements des panels
    Par Regis.C dans le forum Agents de placement/Fenêtres
    Réponses: 6
    Dernier message: 14/04/2005, 10h50

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