Création dynamique de boutons

Création dynamique de boutons - VB/VBA/VBS - Programmation

Marsh Posté le 21-09-2010 à 16:45:33    

Bonjour,
 
Dans le code VBA Excel suivant, je suit face à un problème :
 
Lorsque j'exécute la fonction AjouterBT, je peux observer que l'évènement est chargé dans ma fenêtre d'exécution.
 
Cependant, le clic sur le bouton créé n'a pas d'action.
 
Si maintenant j'exécute la fonction InitBouton, le clic affiche bien le nom du bouton !
 
Module

Code :
  1. Option Explicit
  2. Public Collect As Collection
  3. Sub AjouterBT()
  4. Dim tObject As Object
  5.    
  6. Worksheets.Add
  7. 'Ajout du bouton
  8. Set tObject = ActiveSheet.OLEObjects.Add(ClassType:="Forms.Commandbutton.1", _
  9.     Link:=False, _
  10.     DisplayAsIcon:=False, _
  11.     Left:=1, _
  12.     Top:=50, _
  13.     Width:=72, _
  14.     Height:=24)
  15. tObject.name = "BTest"
  16. tObject.Object.Caption = "Test"
  17. 'Destruction du pointeur
  18. Set tObject = Nothing
  19. 'Chargement de l'évènement
  20. Call InitBouton
  21. Debug.Print "Vérif création OK : " & Collect.Item(1).GroupBoutons.name
  22. End Sub
  23. Public Sub InitBouton()
  24. Dim Obj As OLEObject
  25. Dim Cl As Classe1
  26.    
  27. Set Cl = Nothing
  28. Set Collect = New Collection
  29. 'boucle sur les objets de la active
  30. For Each Obj In ActiveSheet.OLEObjects
  31.     'verifie s'il s'agit d'un bouton
  32.     If TypeOf Obj.Object Is MSForms.CommandButton Then
  33.         Set Cl = New Classe1
  34.         Set Cl.GroupBoutons = Obj.Object
  35.         Collect.Add Cl
  36.         Debug.Print "Bouton ajouté : " & Obj.name
  37.     End If
  38. Next Obj
  39. End Sub
  40. Sub BoutonClick(name As String)
  41. Cells(1, 1).Value = name
  42. End Sub


 
Module de classe 'Classe1'

Code :
  1. Option Explicit
  2. Public WithEvents GroupBoutons As MSForms.CommandButton
  3. Private Sub GroupBoutons_Click()
  4.     Call BoutonClick(GroupBoutons.name)
  5. End Sub


 
Comment ce fait-il que ma collection reste en mémoire si je lance la fonction InitBouton séparément et pas lorsqu'elle est appelée par la fonction AjouterBT ?!?

Reply

Marsh Posté le 21-09-2010 à 16:45:33   

Reply

Marsh Posté le 21-09-2010 à 17:33:23    

Peut-être que Excel n'a pas le temps de gérer la création car on ne lui redonne pas la main.
Donc, peut-être qu'il faudait ajouter ceci avant Set tObject = Nothing

Call wait_secondes(1)


Et ajouter une procédure qui redonne un peu la main au système

Private Sub wait_secondes(Secondes As Integer)  
Dim Début As Long, Fin As Long, Chrono As Long  
    Debut = Timer  
    Fin = Debut + Secondes  
    Do Until Timer >= Fin  
        DoEvents  
    Loop  
End Sub  


Message édité par olivthill le 21-09-2010 à 17:34:52
Reply

Marsh Posté le 21-09-2010 à 17:51:33    

Non, j'ai essayé de rajouter un wait mais sans succès.

Reply

Marsh Posté le 22-09-2010 à 09:40:45    

Un wait comme celui décrit http://msdn.microsoft.com/en-us/li [...] e.11).aspx ?
 
Je préconiserais plutôt des DoEvents, voir http://support.microsoft.com/?scid [...] 8&x=6&y=16 .
 

Reply

Marsh Posté le 22-09-2010 à 14:43:16    

Actuellement, je ne pense pas que le problème vienne de la création de l'objet.
 
Effectivement, je vérifie la bonne création d'un objet dans ma collection par un debug.print en ligne 23 qui prouve que la collection collect de type public contient bien le bouton.
 
Cependant, dès que je quitte la procédure AjouterBT(), la collection est détruite ! alors qu'une collection public devrait être conservée...
 
L'exécution indépendante de la fonction InitBouton() après l'ajout du bouton permet de voir que le code fonctionne correctement, car la collection n'est pas détruite.
 
Pour moi, il semblerait qu'il s'agisse d'un bug (Excel 2003 SP3). Si on peut me confirmer que c'est bien le cas ?  
Dans ce cas, quelle solution utiliser pour lier sur un bouton créé dynamiquement (en dehors de l'utilisation de la librairie VBIDE qui permet d'insérer par la macro du code source mais qui ne constitue pas de la programmation structurée selon moi) ?

Reply

Marsh Posté le 22-09-2010 à 15:00:28    

Il y a deux lignes qui m'étonnent un peu :

Citation :

6. Dim tObject As Object

Je l'aurais mis en ligne 4 pour avoir un objet global.
 

Citation :

20. Set tObject = Nothing

Je n'aurais pas supprimer la référence qui vient d'être crée.
 
Mais cela n'a peut-être rien à voir.

Reply

Marsh Posté le 22-09-2010 à 16:22:41    

En fait, il s'agit uniquement d'un pointeur dont le but est de rendre plus simple l'utilisation de l'objet pour l'initialisé. Ce pointeur n'a pas besoin d'avoir une dimension public car je retrouve le pointeur en parcourant les objets de la feuille qui n'en contient qu'un seul de type bouton.
 
Etant donné que la feuille aura elle aussi un pointeur sur cet objet (créé automatiquement), la destruction du pointeur ne supprime pas le bouton (il reste au moins un pointeur sur l'objet). Comme il est d'usage de supprimer les pointeurs dès qu'ils deviennent inutiles, je le fais.

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed