Partage
  • Partager sur Facebook
  • Partager sur Twitter

[ VBA] Appeler une macro dans Userform

Erreur "Objet Requis"

    10 novembre 2017 à 14:57:11

    Bonjour !

    Après avoir fini la version Bêta de mon fichier (un autre de mes sujets pour lequel je remercie l'intervenant d'ailleurs), j'ai aiméliorer les codes et j'essaie d'ajouter quelques petites fonctionnalités.

    J'utilise des Userform et ListBox rempli grâce à une fonction. Que je met dans "Private Sub UserForm_Initialize()". Tout fonctionne bien.

    Sauf que je dois réutiliser la même fonction dans une autre ListBox et là, je ne sais pas comment appeler la fonction (que j'ai mise dans un module), depuis "initialize"? J'ai cherché sur google, mais il semble que cette erreur arrive pour n'importe quoi?

    Pour le code de la userform:

    Private Sub UserForm_Initialize()
    
    Call ListeDesSalaries
    
    End Sub


    Pour la fonction dans le module 3:

    Sub ListeDesSalaries()
    
    Dim i As Integer
    Dim n As Integer
    
    n = Worksheets.Count - 1
    
        For i = 4 To n
            ListBoxSalaries.AddItem Worksheets(i).Name
        Next i
    
    End Sub

    Sachant que tout fonctionne si je mets dans le "initialize":

    Private Sub UserForm_Initialize()
    
    Dim i As Integer
    Dim n As Integer
    
    n = Worksheets.Count - 1
    
        For i = 4 To n
            ListBoxSalaries.AddItem Worksheets(i).Name
        Next i
    
    
    
    End Sub

    Merci !

    Vincent


    -
    Edité par Vb.pix 10 novembre 2017 à 14:57:27

    • Partager sur Facebook
    • Partager sur Twitter
      14 novembre 2017 à 12:55:17

      Salut,

      Normalement, ca devrais fonctionner.
      Quel message d'erreur obtiens-tu ?

      Notes additionnelles:
      - N'utilise pas les objets contextuels tel que ActiveWorkbook, ActiveSheet, Selection, Worksheets, Range, Cells.
      La valeur de ces objets dépend des action utilisateurs et sont par nature chaotiques.
      En tant que programeur, tu ne veux pas les utiliser.
      Préfère référencer explicitement ce dont tu as besoin.

      - Avant de remplir une listbox, ce serais peut-etre une bonne idée de la vider.

      - Voit pour l'opportunité d'utiliser une fonction générique, elle sera plus polyvalente et plus réutilisable.

      - L'appel de fonctions via le mot clef Call est obsolête.

      • Partager sur Facebook
      • Partager sur Twitter
        15 novembre 2017 à 9:04:15

        Bonjour !

        Merci pour ta réponse !

        J'ai modifié une chose et jusqu'ici ça fonctionne: J'ai passé la fonction de remplissage en Public function qui renvoi le tableau des feuilles. J'appelle cette fonction par ListeDesSalaries = ListeSalaries()

        Pour tes petites notes additionnelles j'aimerai des infos complémentaires :D Je commence à apprendre par internet et rien n'est à jours (sujets de forum etc, comme si les gens avaient arrêté de coder !!)

        Je galère pour trouver chaque info (typiquement, je voudrais un tuto pour gérer les bordures de cellules, avec toutes les possibilités que j'ai: C'est impossible ! (Je galère même pour faire une recherche sur ocr là !))

        - Si je n'utilise pas d'objets contextuels, comment je "référence explicitement"?? 

        Mes fonctions principales aujourd'hui sont de copier/coller des cellules, on d'en supprimer. Je les sélectionne avec Range à chaque fois (même si le Range, c'est ma fonction qui me le donne, et pas l'utilisateur).

        - Vider la listbox: je prend note ! Très bonne remarque !

        - Une fonction générique pour récupérer le nom des pages?

        - J'ai appeler via "Call" pour que ce soit explicite pour moi quand je code, pour comprendre. Il est supprimé par la suite.

        Merci beaucoup !

        Vincent

        • Partager sur Facebook
        • Partager sur Twitter
          15 novembre 2017 à 12:39:34

          Concernant les objets contextuels:
          Ce sont les objets dit currament actifs, ils reflètent le docuement avec lequel l'utilisateur est en train de travailler.
          Un simple click suffit à les changer.

          Si tu as une macro qui  utilise outrageusement ces objet, et prend un peut de temps, ouvrir un autre classeur ou selectionner une autre feuille, une cellule ou un graph fera partir la macro en sucette.

          La solution est de referencer explicitement. Exemples:

          '// Le classeur contenant le code:
          Set wb = ThisWorkbook
          
          '// La premiere feuille du classeur:
          Set wb = ThisWorkbook
          Set ws = wb.Worksheets(1)
          
          '// La plage A5:G10 de la premiere feuille:
          Set wb = ThisWorkbook
          Set ws = wb.Worksheets(1)
          Set rng = ws.range("A5:G10")
          
          PS: J'ai omis intentionellement les déclarations de variables pour ne pas surcharger.
          • Partager sur Facebook
          • Partager sur Twitter
            15 novembre 2017 à 15:40:11

            Merci pour ton info.

            Je m'attaque à une partie du code, je vais tenter d'utiliser ces méthodes pour essayer, et je reprendrais le code qui fonctionne actuellement plus tard, quand je serais plus sur de mon coup.

            Justement, là, je bloque, je comprends même pas le départ (C'est nouveau hein, ne me frappez pas :D)

            Cela fonctionne: (Affichage du nom du classeur)

            Dim Wb As Workbook
            Dim Ws As Worksheets
            
            Set Wb = ThisWorkbook
            
            MsgBox Wb.Name




            Cela fonctionne:

            Dim Wb As Workbook
            Dim Ws As Worksheet
            
            Set Wb = ThisWorkbook
            Set Ws = Worksheets("FSE - xxxx")
            
            MsgBox Ws.Name



            Mais moi je veux afficher le nom de la feuille en cours?!

            Tu aurais un tuto d'explication sous le bras? (Je n'ai rien trouvé sur OCR?)

            Vinc'

            -
            Edité par Vb.pix 15 novembre 2017 à 15:53:20

            • Partager sur Facebook
            • Partager sur Twitter
              16 novembre 2017 à 10:34:03

              Vb.pix a écrit:

              Mais moi je veux afficher le nom de la feuille en cours?!

              "la feuille en cours", donc l'objet ActiveSheet, mais il va faloir être précis à propos du classeur concerné:
              - Est-ce la feuille en cours du classeur courrant ?
              - Est-ce la feuille en cours du classeur contenant le code ?

              Dans le premier cas, tu utiliseras (ou référenceras) ActiveWorkbook.ActiveSheet (ou plus simplement ActiveSheet).
              Dans le second, tu utiliseras ThisWorkbook.ActiveSheet.

              Mais encore une fois, ces objets sont dangereux, ne les utilises que si tu n'as pas d'autre solution.

              • Partager sur Facebook
              • Partager sur Twitter
                16 novembre 2017 à 11:59:24

                Je vais essayé.

                Pas d'inquiétude, je ne l'utilise que pour essayer. Etre sur d'avoir bien compris cette histoire (Surtout qu'au final, l'utilisateur ne toucheras jamais à rien, tout sera importé.

                Par contre je suis sur le code pour faire la liste des pages dans la ListBox du début du sujet. Et je n'arrive pas à la mettre dans un module. L'objectif est d'appeler la macro avec en paramètre le nom de la listbox et de la remplir direct dans la macro.

                Cela fonctionne si je mets dans l'userform_Initialize:

                Private Sub UserForm_Initialize()
                
                Dim i As Integer
                Dim n As Integer
                
                    n = Worksheets.Count
                
                    For i = 1 To n
                        If Left(Worksheets(i).Name, 3) = "FSE" Then
                            ListBoxSalaries.AddItem Worksheets(i).Name
                        End If
                    Next i
                
                End Sub

                Mais dès que je mets dans un module. Tout plante.

                Je pense qu'il faut déclarer ListBoxSalaries As MSForm.ListBox en public? Mais avec quelle ligne de commande?

                • Partager sur Facebook
                • Partager sur Twitter
                  16 novembre 2017 à 12:18:35

                  On va éviter les variables globales .... (evil devil !!)

                  Tu peux écrire une fonction avec des paramètres.
                  Préfère également utiliser la boucle for ... each quand tu itères sur des collections:

                  Public Sub fillListBoxWithWorksheetsName(ByRef lb as MsForm.ListBox)
                      Dim ws As Excel.Worksheet
                  
                      lb.Clear
                      For Each ws In thisWorkbook.Worksheets
                          If(Left(ws.Name, 3) = "FSE") Then
                              lb.AddItem ws.Name
                          End If
                      Next
                  End Sub
                  • Partager sur Facebook
                  • Partager sur Twitter
                    16 novembre 2017 à 13:21:09

                    Salut !

                    Alors. Je pense avoir compris, je vais voir pour le mettre en place quand j'aurais fini de me battre avec ces p*t*in de date ! Je lui fourni "01/02/2017", il me le sort dans toutes les MsgBox que je mets pour tester, mais dès qu'il s'agit de l'intégrer dans la cellule, il inverse le jour et le mois !!!

                    Passons.

                    Quand j'utilise ton code de cette façon:

                    Public Sub GenererListeSalaries(ByRef lb As MsForm.ListBox)

                    Public Sub GenererListeSalaries(ByRef lb As MsForm.ListBox)
                    
                        Dim ws As Excel.Worksheet
                     
                        lb.Clear
                        For Each ws In ThisWorkbook.Worksheets
                            If (Left(ws.Name, 3) = "FSE") Then
                                lb.AddItem ws.Name
                            End If
                        Next
                    End Sub

                    Il me met en erreur "Type défini par l'utilisateur non défini".

                    J'appelle la macro via cette ligne:

                    GenererListeSalaries (ListBoxSalaries.Name)

                    Un lien vers une explication de ces objets? Je ne connais pas mais peut être que ce n'est pas la bonne info que je met pour appeler la macro?

                    Vincent

                    Merci !

                    Vincent

                    -
                    Edité par Vb.pix 16 novembre 2017 à 14:07:29

                    • Partager sur Facebook
                    • Partager sur Twitter
                      16 novembre 2017 à 15:32:23

                      Premier point,  lorsque tu as ce message d'erreur, verifie le type des variables, tu peux également compiler ton projet pour cela (menu: Débogage ==> Compiler)

                      L'intellisence peux également venir en aide (saisie semi-automatique) pour eviter les fautes de frappe.
                      En l'occurence, MSForms.ListBox en lieux et place de MSForm.ListBox (y'a un "s" en plus).
                      Faute de ma part certes, mais ca ne te dispence pas de verifier de ton coté (inconveniants du copier / coller bête et mechant).

                      Second point, la fonction attend un objet ListBox (type: MSForms.ListBox) en paramètre, hors tu lui refiles le nom de l'objet (type: String), ca ne peut pas fonctionner ...

                      • Partager sur Facebook
                      • Partager sur Twitter
                        16 novembre 2017 à 17:17:34

                        Salut !

                        Merci pour ta réponse, qui d'ailleurs dès la première ligne m'est très utile !

                        Concernant le "S", je l'avais vu ;) mais le problème subsistait.

                        Incomprehénsible car tu m'as dit qu'on appelait plus avec Call. Pourtant, c'est la seule fonction qui fonctionne: Call GenererListeSalaries(ListBoxSalaries)...

                        J'en apprends plus sur les control des objets. Très interessant pour créer une Userform de toute pièce: J'en ai 3 qui se ressemble... :D - Peux-tu créer une Userform dans un module? Ou je dois forcément créer la Userform avec le graphique?

                        Vincent

                        -
                        Edité par Vb.pix 16 novembre 2017 à 17:31:53

                        • Partager sur Facebook
                        • Partager sur Twitter
                          16 novembre 2017 à 21:17:05

                          Vb.pix a écrit:

                          Incomprehénsible car tu m'as dit qu'on appelait plus avec Call. Pourtant, c'est la seule fonction qui fonctionne: Call GenererListeSalaries(ListBoxSalaries)...

                          Retire les parenthèses, elles ne sont utiles que lorsque tu appelles un fonction qui retourne une valeur.

                          Vb.pix a écrit:

                          :D - Peux-tu créer une Userform dans un module? Ou je dois forcément créer la Userform avec le graphique?

                          Non, ce n'est pas possible.
                          On peux cependant crée un formulaire par code, mais c'est particulièrement casse-tête, et pourquoi se fair ch*** quand on a un outils graphique WYSIWIG sous la main ?

                          • Partager sur Facebook
                          • Partager sur Twitter
                            17 novembre 2017 à 8:20:18

                            Merci pour ta réponse !

                            Je dois les mettre si j'ai 2 paramètres? ou simplement des virgules entre les paramètres sans parenthèses? C'est pour cela que je bloquais.

                            D'ailleurs je ne comprends pas car sur une autre macro, je fais

                            GenererTableauFse (NomFeuilleCreation) ' Fonctionne
                            
                            GenererTableauFse NomFeuilleCreation ' Ne fonctionne pas...




                            Deedolith a écrit:

                            Non, ce n'est pas possible.
                            On peux cependant crée un formulaire par code, mais c'est particulièrement casse-tête, et pourquoi se fair ch*** quand on a un outils graphique WYSIWIG sous la main ?


                            Merci pour ta réponse.

                            En fait j'ai 4 fois la même Userform, à peu de chose près (une case à cocher). J'ai 4 macros:

                            - J'affiche la fiche d'un salarié,

                            - Je supprime la fiche d'un salarié,

                            - J'édite un récapitulatif d'un salarié.

                            - Je calcul des VLEP

                            Les 4 macros font appel à 3 userform qui liste les salariés (et donc la fonction qui liste les feuilles ;)). Mon objectif est d'en avoir plus qu'une avec gestion dynamique du titre et de l'action quand "ok" - chose que j'ai déjà fait pour la fenetre d'affichage liste salarié et calcul VLEP...

                            J'ai également 2 fonctions qui vont chercher un fichier pour import... Et actuellement 2 userforms qui font donc la même chose... Je vais retaper le code pour n'en avoir plus qu'une.

                            J'ai actuellement 6 Userform, l'objectif est de n'en avoir plus que 2... Ce sera beaucoup plus propre et compréhensible, et moins lourd :D

                            Encore merci pour tes infos !

                            Vincent

                            -
                            Edité par Vb.pix 17 novembre 2017 à 8:35:09

                            • Partager sur Facebook
                            • Partager sur Twitter

                            [ VBA] Appeler une macro dans Userform

                            × Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
                            × Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
                            • Editeur
                            • Markdown