[VBA Excel] Boucle sur CheckBox ?

Résolu
Bonjour à tous !

Voilà j'ai un petit problème avec les CheckBox (cases à cocher). J'ai créé un Userform sur Excel avec 52 CheckBox numérotées de 1 à 52 respectivement aux semaines (CheckBox1 -> S01, ... , CheckBox52 -> S52), et j'ai ajouté un bouton "Sélectionner tout" pour pouvoir toutes les sélectionner automatiquement. Mon problème est le suivant : je n'arrive pas à programmer une boucle sur les CheckBox pour que ça marche... J'ai essayé le code suivant :

Dim i As Integer
For i = 0 To 52
CheckBox.i.Value = True
Next i

mais ça ne marche pas. J'ai même essayé d'utiliser des crochets, des parenthèses ou des accolades, mais rien n'y fait... (CheckBox[i], CheckBox(i) ...). Il me met un message d'erreur à chaque fois.
Je voudrais donc vous demander si vous savez comment créer une boucle avec les CheckBox, sachant que ce bouton "Sélectionner tout" n'est que le 1er (et le plus simple) de mes soucis...
Merci infiniment !

Salim
Configuration: Windows XP
Internet Explorer 6.0
Office 2003

22 réponses

Résumé de la discussion

Le problème porte sur l'automatisation d'une sélection globale de 52 CheckBox dans un UserForm Excel, la tentative de boucle For i = 0 To 52 provoquant des erreurs d'accès aux objets. Des solutions recommandent de parcourir la collection des contrôles et de tester le préfixe du nom pour n'agir que sur CheckBox, puis les cocher en mettant Value à True. Une autre approche consiste à placer les CheckBox dans une Frame et à boucler sur les contrôles de ce cadre, ce qui évite d’altérer les objets hors cadre. En pratique, la solution retenue consiste à utiliser For Each ole In UserForm1.Controls et à vérifier Left$(ole.Name, 8) = "CheckBox" puis ole.Value = True, une méthode efficace et adaptable.

Bobot (l’IA à votre service)
  1. Bonjour,

    Oui, bien sur ! Excel (plutot VBA) ne possède pas de collection à proprement parlé ! Contrairement à VB...

    Tout les problèmes que vous rencontrez viennent de là ! IL est donc impossible d'attribuer un numéro dans une collection d'un type particulier d'objet. LA seule collection qu'il connaisse (Excel) est l'Userform1... Tous les objets dans une Userform sont dans une seule collection (quelque soit le type)... Ainsi les checkbox ou Label et autre sont indexés les l'un à la suite des autres sans distinction.

    LA "ruse" pour se ballader dans un seul type d'objet est d'utiliser par exemple le début du nom générique. Par exemple pour mettre toutes les CheckBox cochées (TRUE), il suffit de regarder si le début du nom commence par checkBox et ensuite de passer en revue chaque objet...

    Concrètement, mettez quelques CheckBox dans une Userform1 et un bouton.

    Derrière le bouton mettez le code suivant :

    =

    Private Sub CommandButton1_Click()

    Dim ole1 As Control
    For Each ole1 In UserForm1.Controls
    If Left$(ole1.Name, 8) = "CheckBox" Then ole1.Value = True
    Next

    End Sub

    =

    et quand vous cliquez sur le bouton, tous les checkbox seront cochées... Bien sur le principe est exploitable pour d'autres objets...

    ICI j'utilise le début du Nom (Name) de l'objet, mais on pourrait utiliser une autre propriété. GroupName est ici fait pour cela...
    1. Effectivement je n'avais pas pensé à cette solution à vrai dire assez élégante.
      Merci de l'info (je garde ça sous le coude, on ne sait jamais)
    2. @sncfOui effectivement...

      J'AI été un peu radicale en disant qu'il n'y avait que l'userform... EN fait on peut aussi utiliser les FRAME qui possèdent aussi la collection CONTROLS... Ainsi on peut passer en revue que dedans... Ce qui encore plus élégant... Avec : For Each ole1 In Frame1.Controls

      Enfin, tu auras compris le principe, je pense...
  2. Bonjour à tous,

    Je profite du sujet " checkbox" pour essayer de trouver uen solution à mon problème:

    Un de mes UserForm contient 2 Listes modifiables ( "ComboBox1 & ComboBox2") , lorsque l'utilisateur choisit un groupe client dans ComboBox1, n'apparraissent dans ComboBox2 que les clients faisant parti du groupe sélectionné dans ComboBox1. ( classique jusque là )

    Sous ces deux ComboBox je souhaite faire apparaître (et disparaître) des "CheckBox" correspondant aux clients figurant dans ComboBox2 , afin de laisser le choix à l'utilisateur d'afficher les clients qu'il veut.

    Exemple : ComboBox1.Value = Groupe Axson

    ==> ComboBox2 = {Axson Fr, Axson All, Axson Bel, Axson Esp...}

    CheckBox1 : Axson Fr
    CheckBox2 : Axson All
    CheckBox3 : Axson Bel
    .
    .
    .
    .
    .
    .
    .
    .

    Vous avez compris l'idée ? Cela est-il possible en définissant par exemple 10 checkBox que je sais comment faire apparaître et disparaître du UserForm mais en mettant la propriété "Caption" en variable ainsi que d'autres propriétés probablement....

    Merci pour votre aide
    1. Bonjour Yonel,

      Je n'ai pas de solution pour ton soucis mais en revanche, je pense que tu en as pour le mien...

      J'ai ouvert un post où je parle de list contionnées. Et c'est exactement ce que tu viens de décrire.

      Peux-tu m'aider sur le sujet?

      D'avance merci
  3. Salut,

    Bizarre ce comportement, en effet. Et si tu click qu'une seule fois et que tu attends un moment ? que ce passe-t-il ? Car en toute logique (si on peut dire) le fait de cliquer plusieurs fois ne peut pas avoir plus d'effet qu'une fois si tu utilise l'évenement "click"...

    A moins que tu utilises (autre peut-être possibilité) les propriétés "GetFocus" et autre "Truc avec focus", qui ferait que le premier click mettrait uniquement le focus sur l'userform avant que le deuxième valide réellement le clique sur le bouton. Mais ceci se voit facilement en regardant si l'userform où tu cliques a barre active ou pas...

    Sinon, pour poster un message, il suffit de cliquer sur "Forum programmation" juste au-dessous des ces messages, puis sur la nouvelle page (la page générale) de choisir le lien "Nouveau message"... et le reste suit...
    1. Bonjour Us,

      Bah ce n'est pas si grave, ça peut rester comme ça en attendant, après tout, ce n'est pas pour moi que e l'ai fabriqué (je plaisante).

      Merci pour la marche à suivre pour les sujets, j'entreprends dans les prochaines semaines un -petit- travail de création et je vais certainement avoir besoin de toutes les ressources disponibles sur VBA (par exemple -si je ne trouve pas par moi-même- comment lancer depuis une CheckBox des minis vidéos issues d'un tutoriel qui enregistre ce qui se passe à l'écran pour le restituer de manière formative).

      En tous cas, un grand merci, et n'hésitez pas à me contacter si besoin

      Phil

      Aider les autres c'est s'aider soi-même
  4. dans le code de fermeture ou du bouton de ton deuxième userform,

    'pour décocher le CheckBox
    UserForm1.CheckBox1.Value = False
    
    'pour désactiver (griser) le CheckBox
    UserForm1.CheckBox1.Enabled = False
    
    1. Bonjour à vb,
      Bonjour à tous,

      Un grand merci, c'était tout simple mais fallait-il encore y penser !

      Un autre petit "hic" dans ma programmation :
      - quand je clique sur le CommandButton destiné à effacer la Combobox sur lequel il est implanté, un clic ne suffit pas, il faut deux voire trois clics pour qu'il fonctionne.

      Est-ce évitable? Je pense que oui mais hésite à compléter ma macro (peur de surcharger)

      D'avance merci
    2. @PhilippeSalut,

      Sous quel événement as-tu mis ton code ?

      Si tu utilises "CommandButton1_DblClick" il faut 2 click pour que le code se lance... (normal)
      Normalement (le plus souvent) on utilise un seul click avec l'évenement "CommandButton1_Click"

      C'est peut-être l'origine de ton problème...

      Exemple :

      Private Sub CommandButton1_Click()
      MsgBox "un click"
      End Sub
      
      Private Sub CommandButton1_DblClick(ByVal Cancel As MSForms.ReturnBoolean)
      MsgBox "un double click !"
      End Sub

    3. @usBonsoir Us,

      Merci pour ton post. J'ai controlé (sait-on jamais) mais je n'ai pas demandé le DblClick pour valider.

      Mon problème ressemble plus à une sorte de bug qu'à une insertion (meme par inadvertance) de commande. A l'origine, mon petit programme fonctionnait parfaitement. Ce soucis n'est apparu que depuis que j'y ai ajouté les codes pour desactiver les checkbox.

      Un détail qui peut avoir son importance, l'appel de certains userform (qui renferment l'aide de mon petit programme) se fait sur différentes combobox. Je m'explique car j'ai du mal à me comprendre (on est bien partis lol) ; je donne les noms par défaut volontairement ce sera plus simple :

      Userform1 contient : 1 label (explication) ; 3 Checkbox (qui conditionnent pour 2 d'entre elles l'ouverture d'une combobox d'erreur (qui, lorsqu'on la ferme, décoche et désactive la Checkbox qui venait de l'appeler) et pour le dernier un fonctionnement normal (la case s'active quand elle est sélectionnée) ; 2 CommandButton (un pour OK (qui ferme Userform1 et ouvre Userform2) et l'autre pour AIDE (qui ouvre le Userform d'aide) ;

      C'est au niveau des deux Combobox d'erreur (car elles sont différentes) que réside mon soucis, je dois cliquer 2 voire 3 fois sur le CommandButton (nommé OK - j'avais pas plus d'imagination) pour revenir au Userform d'origine.

      Je ne sais pas si tout ceci est compréhensible, au cas où je peux toujours détailler les aspects sombres de mon explication.

      En tous cas, un grand merci pour ton aide, j'apprécie et espère pouvoir à mon tour apporter prochainement la mienne.

      Phil

      P.S. : Où faut-il aller pour créer un topic?
  5. Bonjour à tous,
    C'est mon premier post ici
    J'ai une petite question toute bête (j'espère qu'elle n'a pas trouvé de réponse ailleurs)
    J'ai créé des checkbox sur un userform et des scripts qui s'exécutent lorsqu'on les active. Ex : un autre userform s'ouvre en indiquant que l'utilisateur s'est trompé en activant cette checkbox.
    Je voudrais qu'en fermant ce nouveau userform, la checkbox activée par erreur se désactive automatiquement.
    Y'a-t-il un code pour ça?
    D'avance merci vous me rendriez un GRAND service
    1. USERFORM1.SHOW = Charge et lance l'useform1

      USERFORM1.LOAD = Charge l'userform1 (mais ne l'affiche pas)
      USERFORM1.HIDE = Cache l'userform1 (elle reste en mémoire à condition qu'elle soit chargée)

      UNLOAD USERFROM1 = Décharge l'Userform1 ! donc ferme l'userform (elle n'est plus visible)

      En général , on l'utilise cette dernière derrière un bouton où l'on code :

      Unload Me

      Voilà un peu de vocabulaire... :-);
      1. Merci infiniment les gars !!
        J'ai opté pour la solution de sncf, qui marche très bien, parce que je m'étais déjà engagé sur cette voie, mais la solution de Us m'a l'air d'être très ingénieuse aussi.
        En tous cas, j'ai réussi à faire ce que je voulais, merci à vous ! ;)
        Deux toutes petites questions pour la route :
        1. comment faire appel au Userform à partir des macros ?
        2. en cliquant sur OK, le Userform va me générer le programme que je veux, mais je voudrais que le Userform se ferme automatiquement juste après. Comment faire ?

        Salim

        EDIT : j'ai trouvé la solution pour la 1re question ;) je suis allé sur les modules, j'ai tapé :

        Sub UserForm()
        UserForm1.Show
        End Sub

        et ça m'a créé une macro pour afficher mon Userform

        EDIT bis : de même, j'ai trouvé la solution pour la 2e question (décidément, je suis chaud aujourd'hui lol). Cette fois-ci, il faut mettre à la fin du Private Sub du bouton Valider : Userform1.Hide... Simplement ;)
        Merci encore de votre gentillesse, de votre compétence et de votre patience :)
        A bientôt

        Salim
        1. Salim, regarde les réponses postées à la suite...
        2. @usUi ui j'ai bien vu :)
          Je préfère nettement Unload à Hide, par contre je garde mon Show, je l'aime bien lol
          Merci pour ces précisions très instructives :)

          Salim
        3. @usOui, le plus souvent on utilise SHOW et UNLOAD ! mais dès que tu utilises plusieurs USERFORM, tu trouveras plus élégant de seulement cacher les Userform, c'est plus avantageux (enfin plus simple pour coder)... En effet, comme cela tu peux toujours lire les données entrées sans avoir à les mettre dans des variables auxiliaires... Voilà, A+
        4. @salim2103Salim je suis d'accord avec us
          Pour fermer le formulaire il faut etre sur que 'on a plus besoin des données contenues dans ce dernier sinon c'est galère
      2. J'étais justement en train de t'écrire que la 2e solution ne marchait pas... Elle aurait eu le mérite d'être plus rapide... Dommage !
        Je vais m'atteler à la 1re, qui doit forcément marcher ;)
        1. solutions pour résoudre ton problème
          Solution 1

          Suppression de l’étiquette Label1 ( en fait je l’ai seulement déplacé sous S02)
          Redimensionnement de la Chekbox1 (elle masquait tout ce que tu pouvais écrire dans caption)
          Caption = S01
          Alignment = 0 –fmAlignmentLeft
          TextAlign = fmTextAlignRight
          En redimensionnant légèrement en hauteur tu obtiens le résultat souhaité et tu supprimes du même coup la moitié des controles (toutes les Labels)

          1. C'est envoyé ;)
            Le but de ce Userform est de simplifier l'utilisation d'un programme VBA. L'utilisateur pourra choisir les semaines qu'il veut sur le Userform, et ce dernier s'occupera d'exécuter le programmes pour ces semaines. Le bouton Sélectionner tout n'est qu'un début comme je disais dans mon 1er post
            1. Pour y voir plus clair, peux tu m'envoyer ton formulaire (exporter CTRL+E pour générer un fichier frm). Je t'envoie un message privé pour t'indiquer mon adresse e mail
              1. Pour être clair, chaque semaine i est concernée par une CheckBox numérotée i (CheckBox25 pour la semaine 25 par exemple), et chaque CheckBox i est accompagnée par un Label du même numéro i (Label25 pour la CheckBox25, dont le libellé est "S25").
                Donc la semaine 25 est indiquée par une case à cocher juste à coté d'une étiquette "S25". Forcément, les Label font aussi partie de la Frame...
                C'est clair j'espère :) Sinon n'hésite pas à me demander
                1. Quelle est l'utilité de mettre une étiquette pour indiquer S01 alors que dans les propriétés de checkbox tu as caption qui te mertmet de le faire (en plus ça fit moitié moins de controles)
                  1. Ben c'est pour celui qui va utiliser le Userform, s'il ne sait pas quelle CheckBox concerne quelle semaine (car il aura à cocher certaines ou toutes les cases...), le Userform en lui-même n'a pas lieu d'exister...
                  2. @salim2103OK lmais la propriété "Caption" de la chockbox te permet justement de la faire (c'est en fait une étiquette intégrée à la checkbox) d'ou ma question
                    Pourquoi ne pas utiliser cette propriété de chaque checkbox et supprimer toutes ces étiquettes devenue inutiles
                  3. @sncfJ'ai modifié la propriété Caption mais le nom n'apparait pas sur le Userform. C'est normal ??
                  4. @salim2103Pour y voir plus clair, peux tu m'envoyer ton formulaire (exporter dans le menu fichier du visual basic editor (CTRL+E) pour générer un fichier frm). Je t'envoie un message privé pour t'indiquer mon adresse e mail
                2. Je ne comprend pas, ta première case à cocher s'appelle comment et ta première étiquette s'appelle comment et quel est le libellé
                  Les etiquettes sont elles égalemnt dans le frame1 ?
                  1. Aïe ! J'ai un petit problème encore... Sur mon Userform, il n'y a pas que des CheckBox, mais aussi des Label (Intitulés) pour indiquer justement que telle semaine est concernée par telle case à cocher... Ces label sont numérotés de la même manière que les CheckBox. Donc quand j'exécute ton programme, il me change le nom des Label (les Label passent de "S01", "S02"... à "True").
                    Que de problèmes !! lol
                    J'ai essayé de sortir les Label de la Frame mais la Frame reste toujours au premier plan... Et j'ai aussi essayé d'utiliser Userform1.Frame1(i).Value = True, mais il me met un message d'erreur...
                    1. Super !! Merci beaucoup sncf ;) Ca a l'air de marcher.
                      Je vais essayer ça tout de suite sur mon projet et voir si ça peut arranger mes soucis. Je te rend la réponse dès que les tests seront faits.
                      Merci encore ! :)
                      1. Ca marche toujours pas... Je pense que ça vient du "Me" dont je comprend pas le sens.
                        En plus, la réponse à xjl m'intéresse beaucoup également.
                        Merci d'avance ;)
                        1. remplace Me par userform1 (le nom de ton formulaire)
                      2. Désolé, je vous coupe, mais est-ce que quelqu'un sait pourquoi ce code là ne fonctionne pas:

                        For Each CheckBox In Sheets(1).CheckBoxes
                        CheckBox.Value = True
                        Next CheckBox

                        J'ai l'impression qu'il ne trouve pas les CheckBox dans la collection et je ne comprends pas pourquoi, mais si quelqu'un arrive à faire fonctionner ce code, ça résoudra le problème...
                        1. Toutes mes excuses
                          voici le bon code

                          Dim i As Integer
                          For i = 0 To 51
                          Me.Frame1(i) = True
                          Next i
                          • 1
                          • 2