Se connecter avec
S'enregistrer | Connectez-vous

Intégrer une liste de choix dans une macro

Dernière réponse : dans Programmation

Bonjour,

Je travaille sur une macro qui me permet de copier certaines lignes d'une base Excel à partir de 1 ou plusieurs critères. Le critère principal me servira à créer autant d'onglets que de valeurs choisies pour ce critère et le ou les critères secondaires précisent quels enregistrements seront extraits.
Mon problème est que je n'arrive pas à faire apparaitre une boite de dialogue qui propose les différentes valeurs du critère principal choisi (et des autres non plus d'ailleurs mais chaque chose en son temps).
Je pense que je dois utiliser un Userform si j'ai bien compris tout ce que j'ai pu lire sur ce site mais je ne sais pas comment intégrer ce Userform dans la macro que j'ai déjà écrite.

J'espère que je suis assez claire dans ma demande.
Merci de bien vouloir m'aider.

NAM

Autres pages sur : integrer liste choix macro

Lassé par la pub ? Créez un compte
Expert Programmation

Salut,

C'est effectivement un userform qu'il faut faire apparaître.
Maintenant, tes recherches seront mieux orientées ;) 

Un bête appel à la méthode Show() devrait suffire pour ça.

Bonjour zeb,

Merci pour l'info. J'ai déjà fait un peu le ménage dans ma macro avec tout ce que j'ai vu ici (option explicit...) mais je n'arrive toujours pas à comprendre comment je fais apparaitre cette fichue boite de dialogue. En fait, mon problème est de savoir où je déclare mon Userform, dans ma procédure ou ailleurs et je l'appelle ensuite ?
C'est vraiment pas clair pour moi.

voici la macro déjà existante :
  1. Option Explicit
  2.  
  3. Sub Extraction_base()
  4.  
  5. Dim Base As Worksheet
  6. Dim paravb As Worksheet
  7.  
  8. Set Base = Worksheets("Base")
  9.  
  10. Dim val_critère_princ, s, nb_crit_sec, ligne, b, c, i, j, k, l, m, t, p, test, colonne, Index, lstrow, lstcol, nbchamps, col_critère_princ, col_critère_sec As Integer
  11. Dim chemin As String
  12. Dim var_temp_5, Message, Message2, Titre, Message3, Titre3, Message4, Titre4, Message5, Titre2, Titre5, Default, MyValue, MyValue2, Resultat
  13.  
  14. ' Définit le message.
  15. 'Message = "Précisez le chemin pour atteindre le dossier de traitement"
  16. 'Titre = "Chemin" ' Définit le titre.
  17. ' Affiche le message, le titre et la valeur par défaut.
  18. 'MyValue = InputBox(Message, Title, Default)
  19.  
  20. ' Définit le message.
  21. 'Message2 = "Précisez le nom du fichier à traiter - Ne pas oublier l'extension .xls"
  22. 'Titre2 = "Fichier" ' Définit le titre.
  23. ' Affiche le message, le titre et la valeur par défaut.
  24. 'MyValue2 = InputBox(Message2, Titre2, Default)
  25.  
  26. ' chemin = MyValue
  27. ' fichier = MyValue2
  28.  
  29. ' Set fs = Application.FileSearch
  30. 'With fs
  31. ' .LookIn = chemin
  32. ' .Filename = fichier
  33. ' .MatchTextExactly = True
  34.  
  35. ' If .Execute > 0 Then
  36.  
  37. 'Workbooks.Open Filename:=MyValue & "\" & MyValue2
  38.  
  39. 'End If
  40.  
  41.  
  42. Dim Msg, Style, Title, Help, Ctxt, Response, MyString
  43. Msg = "N'oubliez pas de cocher dans la 1ère ligne de votre fichier les cases correspondant aux colonnes que vous voulez extraire. Si vous ne l'avez pas encore fait, cliquez sur Cancel"
  44. Style = vbOKCancel
  45. Title = "Attention"
  46. Help = "DEMO.HLP" ' Définit le fichier d'aide.
  47. Ctxt = 1000 ' Définit le contexte de
  48. ' la rubrique.
  49. ' Affiche le message.
  50. Response = MsgBox(Msg, Style, Title, Help, Ctxt)
  51. If Response = 2 Then
  52. Exit Sub
  53. End If
  54.  
  55. lstrow = Base.Range("A65536").End(xlUp).Row
  56.  
  57. lstcol = Base.Range("IF1").End(xlUp).Column
  58.  
  59. nbchamps = 0
  60.  
  61. For t = 1 To 256
  62. If Base.Cells(1, t) <> "" Then
  63. nbchamps = nbchamps + 1
  64. End If
  65. Next
  66.  
  67. 'créer un nouvel onglet "paravb"
  68. Set paravb = Sheets.Add(Type:=xlWorksheet)
  69. Sheets("Feuil1").Select
  70. Sheets("Feuil1").Name = "paravb"
  71.  
  72. Set paravb = Worksheets("paravb")
  73.  
  74. 'Choix du critère principal
  75. 'Définit le message.
  76. Message3 = "Précisez le numéro de colonne du critère principal qui servira à la création des onglets"
  77. Titre3 = "Critère principal" ' Définit le titre.
  78. ' Affiche le message, le titre et la valeur par défaut.
  79. Resultat = InputBox(Message3, Titre3, Default)
  80. col_critère_princ = Resultat * 1
  81. paravb.Cells(1, 1) = "Critère principal"
  82. paravb.Cells(2, 1) = Base.Cells(2, col_critère_princ)
  83.  
  84. 'Liste des différentes valeurs du critère principal
  85. b = 4
  86. i = 0
  87. paravb.Cells(3, 1) = Base.Cells(3, col_critère_princ)
  88. For i = 4 To 76
  89. c = 0
  90. test = 0
  91. For c = 1 To b - 1
  92. If Base.Cells(i, col_critère_princ) = paravb.Cells(c, 1) Then
  93. test = test + 1
  94. End If
  95. Next
  96. If test = 0 Then
  97. paravb.Cells(b, 1) = Base.Cells(i, col_critère_princ)
  98. b = b + 1
  99. End If
  100. Next
  101.  
  102.  
  103. Base.Activate
  104.  
  105. 'Choix des critères secondaires
  106. 'Définit le message.
  107. Message4 = "Combien de critères secondaires souhaitez-vous prendre en compte pour cette extraction ?"
  108. Titre4 = "Nb critères secondaires" ' Définit le titre.
  109. ' Affiche le message, le titre et la valeur par défaut.
  110. nb_crit_sec = InputBox(Message4, Titre4, Default)
  111.  
  112. For s = 1 To nb_crit_sec
  113. Message5 = "Précisez le numéro de colonne du critère secondaire n° " & s
  114. Titre5 = "Critère secondaire n° " & s ' Définit le titre.
  115. ' Affiche le message, le titre et la valeur par défaut.
  116. var_temp_5 = InputBox(Message5, Titre5, Default)
  117. col_critère_sec = var_temp_5 * 1
  118. paravb.Cells(1, s + 1) = "Critère secondaire " & s
  119. paravb.Cells(2, s + 1) = Base.Cells(2, col_critère_sec)
  120.  
  121. 'Liste des différentes valeurs des critères secondaires
  122. b = 4
  123. i = 0
  124. paravb.Cells(3, s + 1) = Base.Cells(3, col_critère_sec)
  125. For i = 4 To lstrow
  126. c = 0
  127. test = 0
  128. For c = 1 To b - 1
  129. If Base.Cells(i, col_critère_sec) = paravb.Cells(c, s + 1) Then
  130. test = test + 1
  131. End If
  132. Next
  133. If test = 0 Then
  134. paravb.Cells(b, s + 1) = Base.Cells(i, col_critère_sec)
  135. b = b + 1
  136. End If
  137. Next
  138. Next
  139.  
  140. 'Définir les valeurs des différents critères sélectionnés
  141.  
  142. Dim f As Range
  143.  
  144. 'ListBox1.Clear
  145. 'For Each f In paravb.Range("a1")
  146. ' If f.Value = "" Then Exit For
  147. 'ListBox1.AddItem f.Value
  148. 'Next
  149.  
  150. 'boucle For à mettre en place pour chaque valeur (v) sélectionnées du critère principal - pour l'instant exemple avec la seule valeur 75
  151. val_critère_princ = "75"
  152.  
  153. i = 0
  154. m = 1
  155. l = 2
  156.  
  157. Dim CP1 As Worksheet
  158.  
  159. Set CP1 = Sheets.Add(Type:=xlWorksheet)
  160. Sheets("Feuil2").Select
  161. Sheets("Feuil2").Name = paravb.Cells(2, 1) & " = " & val_critère_princ
  162.  
  163.  
  164.  
  165. Set CP1 = Worksheets(paravb.Cells(2, 1) & " = " & val_critère_princ)
  166.  
  167. 'quand la boucle for sera mise en place:
  168. 'Dim CP&v as worksheet
  169. 'CP&v=worksheets(paravb.Cells(2, 1) & " = " & val_critère_princ)
  170.  
  171. paravb.Activate
  172.  
  173. 'Boucle de remplissage onglet
  174.  
  175. For i = 3 To lstrow + 3
  176.  
  177. If Base.Cells(i, 1) <> "" Then
  178.  
  179. If Base.Cells(i, col_critère_princ).Text = val_critère_princ Then
  180.  
  181. j = 1
  182. k = 1
  183.  
  184. For m = 1 To lstcol
  185.  
  186. Do While Base.Cells(2, j) <> ""
  187.  
  188. If Base.Cells(1, j) <> "" Then
  189.  
  190. 'Titre
  191. CP1.Cells(1, k) = Base.Cells(2, j)
  192.  
  193. 'Remplissage cellules
  194. CP1.Cells(l, k) = Base.Cells(i, j)
  195. k = k + 1
  196.  
  197. End If
  198.  
  199. j = j + 1
  200.  
  201. Exit Do
  202.  
  203. Loop
  204.  
  205. Next
  206.  
  207. End If
  208.  
  209. End If
  210.  
  211. l = l + 1
  212. Next
  213.  
  214. 'Fin de boucle de remplissage onglet
  215.  
  216. 'Mise en forme 1ère ligne
  217. Rows("1:1").Select
  218. Selection.Font.Bold = True
  219.  
  220. Cells.Select
  221. Cells.EntireColumn.AutoFit
  222.  
  223.  
  224. End Sub


Merci beaucoup.

NMS31
Expert Programmation

Salut,


Indente correctement ton code s'il te plaît.

Ligne 10. Tu ne définis qu'un seul entier, la dernière variable. Les variables précédentes sont non typées
Et oui, il faut écrire :
  1. Dim val_critère_princ as Integer, s As Integer ....

Note que le type Integer (-32768 -> 32767) n'est pas assez grand pour contenir un numéro de ligne (0 -> 65536)
  1. ... lstrow As Long, lstcol As Long ...


Ligne 14 à 39. Ne serait-ce que par égard pour tes lecteurs, vire les trucs inutiles quand tu les publies.

Ligne 42 à 48. Ohlala!!! Relis l'aide sur MsgBox(). Les paramètres facultatifs sont à ne pas utiliser si tu n'en as pas besoin ! Vire les trucs sur l'aide (fichier, contexte).

Ligne 50 à 53. 2 !? :pfff:  Tu as utilisé vbOkCancel pour définir ta boîte. C'est bien. Maintenant, vérifie la réponse avec vbOk et vbCancel.
Astuce : Dans ce cas particulier, ça marche. Mais ne te fie pas au retour vbCancel. Il peut y avoir d'autre façon d'annuler une boîte de dialogue. Pense au complément de l'annulation.
Je te propose donc d'écrire :
  1. If Response <> vbOk Then Exit Sub


Ligne 217 Et si tu écrivais Rows(1) ? ;) 

Dernières lignes. Ne sélectionne rien qui n'ait pas à être sélectionné, si c'est juste pour singer l'enregistreur de macro. Truc.Select suivi de Selection.Machin s'écrit Truc.Machin.

Bon, c'est pas si mal tout ça. Sauf que ces critiques acerbes sur le code que tu nous proposes ne font pas avancer ton problème vers une solution.
Mais c'est surtout, que je n'ai pas compris le rapport entre tes histoires de boîtes de message (MsgBox, InputBox) présentes dans ton code, et ce fameux UserForm.
Tu l'as déjà créé ? Comment s'appelle-t-il ?

Salut,

Merci pour toutes ces remarques que j'intègre tout de suite à mon code.
Pour ce qui est de mon userform, j'ai déjà créé quelque chose que je dois intégrer dans ce code au niveau de la ligne 141 à la place de celles déjà existantes (142 à 148).

voici ce que j'ai écrit mais sans conviction car je ne connais pas du tout les userforms :
  1. Private Sub Tous_Click()
  2. Dim i As Integer
  3.  
  4. For i = 0 To ListBox1.ListCount - 1
  5. ListBox1.Selected(i) = True
  6. Next
  7.  
  8. End Sub
  9.  
  10. Private Sub Aucun_Click()
  11. Dim i As Integer
  12.  
  13. For i = 0 To ListBox1.ListCount - 1
  14. ListBox1.Selected(i) = False
  15. Next
  16.  
  17. End Sub
  18.  
  19. Private Sub Valider_Click()
  20.  
  21. End Sub
  22.  
  23. Private Sub Annuler_Click()
  24.  
  25. End Sub
  26.  
  27. Private Sub ListBox1_Click()
  28. Dim c As Range
  29. For Each c In paravb.Range("a3:a9")
  30. 'If c.Value = "" Then Exit For
  31. ListBox1.AddItem c.Value
  32. Next
  33.  
  34. End Sub


Merci beaucoup pour ton aide.

NMS31
Expert Programmation

Bon, tu m'agaces, toi (*) :fou:  :fou:  :fou: 
Vire-moi le code mort de tes publications. Je ne peux pas avoir à lire les lignes 19 à 25 ou la ligne 30.
Sinon, je pers trop de temps pour rien, je m'énerve, je fais des messages pleins de " :fou:  " et pendant ce temps, je n'aide plus personne

:fou:  :fou:  :fou: 

______
(*) Ce n'est pas pour ça que je vais t'abandonner, rassure toi
Expert Programmation

Donc, ligne 141, tu appelles ton userform :
  1. le_userform_de_NMS31.Show


Evidemment, il est vide. Il aurait fallut le charger.
Donc il faut une fonction pour charger les données.

Fais une procédure dans ton userform pour charger les données.
(Fais signe si t'as besoin d'aide, mais réfléchis-y quand même)
ENsuite, on mettra l'appel à cette procédure à la ligne 140½ ;) 


Enfin, on verra le bouton validation.

Bon, j'ai trouvé la fonction load qui devrait répondre en partie à mon problème mais j'ai toujours un souci, ma listbox est vide.

  1. Private Sub Tous_Click()
  2. Dim i As Integer
  3.  
  4. For i = 0 To ListBox1.ListCount - 1
  5. ListBox1.Selected(i) = True
  6. Next
  7.  
  8. End Sub
  9.  
  10. Private Sub Aucun_Click()
  11. Dim i As Integer
  12.  
  13. For i = 0 To ListBox1.ListCount - 1
  14. ListBox1.Selected(i) = False
  15. Next
  16.  
  17. End Sub
  18.  
  19. Private Sub Valider_Click()
  20.  
  21. End Sub
  22.  
  23. Private Sub Annuler_Click()
  24.  
  25. End Sub
  26.  
  27. Private Sub ListBox1_Click()
  28.  
  29. ListBox1.AddItem "75"
  30. ListBox1.AddItem "77"
  31. ListBox1.AddItem "C3"
  32. ListBox1.AddItem "C4"
  33. ListBox1.Show
  34.  
  35. End Sub
  36.  
  37. Private Sub UserForm_click()
  38. Load ListBox1
  39. Load Tous
  40. Load Aucun
  41. Load Valider
  42. Load Annuler
  43.  
  44. ListBox1.Show
  45. Tous.Show
  46. Aucun.Show
  47. Valider.Show
  48. Annuler.Show
  49.  
  50. End Sub


En fait, j'ai plusieurs questions:
- j'ai cru comprendre que l'événement Initialize devrait plus correspondre à mon Userform que Click
- je voudrais que ma listbox présente les 4 valeurs que je lui indique dans des cases à cocher (après, je verrai comment remplacer ces 4 valeurs par les x valeurs possibles du critère principal choisi auparavant mais ça, ce sera après) et pour l'instant, elle ignore complètement ma demande.

Merci pour ton aide.

Oup's je corrige tout de suite mon code :D 

  1. Private Sub Tous_Click()
  2. Dim i As Integer
  3.  
  4. For i = 0 To ListBox1.ListCount - 1
  5. ListBox1.Selected(i) = True
  6. Next
  7.  
  8. End Sub
  9.  
  10. Private Sub Aucun_Click()
  11. Dim i As Integer
  12.  
  13. For i = 0 To ListBox1.ListCount - 1
  14. ListBox1.Selected(i) = False
  15. Next
  16.  
  17. End Sub
  18.  
  19. Private Sub ListBox1_Click()
  20.  
  21. ListBox1.AddItem "75"
  22. ListBox1.AddItem "77"
  23. ListBox1.AddItem "C3"
  24. ListBox1.AddItem "C4"
  25. ListBox1.Show
  26.  
  27. End Sub
  28.  
  29. Private Sub UserForm_click()
  30. Load ListBox1
  31. Load Tous
  32. Load Aucun
  33. Load Valider
  34. Load Annuler
  35.  
  36. ListBox1.Show
  37. Tous.Show
  38. Aucun.Show
  39. Valider.Show
  40. Annuler.Show
  41.  
  42. End Sub
Expert Programmation

Et l'indentation bordel !

Bon, moi, j'imaginais plutôt une fonction publique (<> Private) qui se nommerait Chargement, et qu'il suffirait d'appeler avant d'afficher le UserForm :
  1. Public Sub Chargement
  2. ListBox1.AddItem "75"
  3. ListBox1.AddItem "77"
  4. ListBox1.AddItem "C3"
  5. ListBox1.AddItem "C4"
  6. End Sub


  1. le_userform_de_NMS31.Chargement
  2. le_userform_de_NMS31.Show

Désolée, je ne comprend pas. J'ai défini la fonction de la façon suivante:
  1. Public Sub Tous_Click()
  2. Dim ListBox1 As listbox
  3.  
  4. Dim i As Integer
  5.  
  6. For i = 0 To ListBox1.ListCount - 1
  7. ListBox1.Selected(i) = True
  8. Next
  9.  
  10. End Sub
  11.  
  12. Public Sub Aucun_Click()
  13. Dim ListBox1 As listbox
  14.  
  15. Dim i As Integer
  16.  
  17. For i = 0 To ListBox1.ListCount - 1
  18. ListBox1.Selected(i) = False
  19. Next
  20.  
  21. End Sub
  22.  
  23.  
  24. Public Sub Annuler_Click()
  25. Dim Mon_UserForm As UserForm
  26.  
  27. Mon_UserForm.Close
  28.  
  29. End Sub
  30.  
  31. Public Sub Mon_UserForm_Initialize()
  32.  
  33. Dim ListBox1 As listbox
  34. Dim Tous As CommandButton
  35. Dim Aucun As CommandButton
  36. Dim Valider As CommandButton
  37. Dim Annuler As CommandButton
  38.  
  39. Load ListBox1
  40. Load Tous
  41. Load Aucun
  42. Load Valider
  43. Load Annuler
  44.  
  45. ListBox1.Show
  46. Tous.Show
  47. Aucun.Show
  48. Valider.Show
  49. Annuler.Show
  50.  
  51. End Sub
  52.  
  53. Public Sub Chargement()
  54.  
  55. Dim ListBox1 As listbox
  56.  
  57. ListBox1.AddItem "75"
  58. ListBox1.AddItem "77"
  59. ListBox1.AddItem "C3"
  60. ListBox1.AddItem "C4"
  61.  
  62. End Sub


Ce n'est pas ça le code de mon Userform ?
Expert Programmation

M'enfin, qu'est-ce que c'est que ce bordel de userform dynamique ? :ouch:  :ouch:  :ouch:  :ouch:  :ouch: 

  • 1°) Efface tout ça : le userform, le code, tout.
  • 2°) Créé un userform tout neuf (bouton droit dans la fenêtre Explorateur de projet [Ctrl+R]/Insertion/Userform)
  • 3°) Ajoute une zone de liste (listbox) et deux boutons de commande (commandbutton) à partir de la boîte à outils
  • 3°-Bis) Change éventuellement les noms de tes 3 objets.
  • 4°) Double-clic sur un des boutons. Le code suivant s'affiche :
    1. Private Sub CommandButton1_Click()
    2.  
    3. End Sub

  • 5°) Ajoutes-y au milieu le code suivant :
    1. Unload Me
    Ce sera ton bouton "Annuler". Le mot Me se rapporte à l'objet lui-même dans le code, c'est à dire à ton userform.
  • 6°) Ajoute le code de chargement donné précédemment.
  • 7°) Dans le code de ThisWorkbook, écris la fonction suivante :
    1. Sub AppelUserForm
    2. userform1.Chargement
    3. userform1.Show
    4. End Sub


  • 8°) Analyse et comprends le problème et sa solution.

    Ca marche toujours pas.
    J'ai bien tout effacé et créé un nouveau userform avec une listbox et 2 commandbuttons.
    J'ai double-cliqué sur 1 boutton que j'ai appelé "Annuler" et écrit le code:
    1. Private Sub Annuler_Click()
    2. Unload Me
    3. End Sub


    J'ai rajouté à la suite le code de chargement :
    1. Public Sub Chargement()
    2. ListBox1.AddItem "75"
    3. ListBox1.AddItem "77"
    4. ListBox1.AddItem "C3"
    5. ListBox1.AddItem "C4"
    6. End Sub


    Dans mon module 1 où j'ai tout le reste de ma macro (j'ai essayé dans ThisWorkbook mais ça ne marche pas non plus et je n'ai rien dedans), j'ai rajouté à la suite de ma macro (donc après le End Sub):
    1. Sub AppelUserForm
    2. userform1.Chargement
    3. userform.Show
    4. End Sub


    J'ai toujours la même erreur 91.
    Dans le dernier code, ce n'est pas userform1 que je dois utiliser pour Show si c'est userform1 que je charge ?

    Je suis vraiment désolée mais je ne comprends pas du tout le fonctionnement. Je ne parviens pas à comprendre la logique.

    Merci encore pour ton aide précieuse.
    Expert Programmation

    Citation :
    Dans le dernier code, ce n'est pas userform1 que je dois utiliser pour Show si c'est userform1 que je charge ?
    Si évidemment, c'est une coquille. Et tu as fais toi-même la correction, j'espère. ;) 

    A quelle ligne exactement as-tu cette erreur 91 ?

    En fait, j'ai d'abord eu l'erreur 424 "objet requis" dans la fonction AppelUserForm. j'ai donc déclaré UserForm1 comme UserForm.
    J'ai maintenant l'erreur 91 au niveau de la ligne 3 du code :

    1. Sub AppelUserForm
    2. Dim UserForm1 as UserForm
    3. UserForm1.Chargement
    4. UserForm1.Show
    5. End Sub


    Merci.
    Expert Programmation

    Non, non, non.

    L'instruction Dim UserForm1 as UserForm déclare un userform. Toi, tu veux le userform que tu as créé.

    Mais quel type de module as-tu créé ????
    Pour être sûr que l'objet est vu par le module, charge-le explicitement :
    1. Sub AppelUserForm
    2. Load UserForm1
    3. userform1.ChargementDesDonnees
    4. userform.Show
    5. End Sub


    Observe ainsi que ton formulaire est chargé (Load) en mémoire ici et déchargé (Unload) de la mémoire dans le clic sur Annuler.
    Il y a une certaine cohérence. :) 

    Bonjour zeb,

    Alors, j'ai modifié le code comme tu me l'as indiqué. j'ai maintenant l'erreur 424 "objet requis" sur la ligne 3.

    J'ai créé un module "normal", quand j'ai créé une nouvelle macro, Excel a automatiquement créé ce module.

    Est-ce que le code du formulaire se limite à :
    1. Private Sub Annuler_Click()
    2. Unload Me
    3. End Sub
    4.  
    5. Public Sub Chargement()
    6. ListBox1.AddItem "75"
    7. ListBox1.AddItem "77"
    8. ListBox1.AddItem "C3"
    9. ListBox1.AddItem "C4"
    10. End Sub


    Je ne dois pas déclarer ou "expliquer" les autres boutons ?

    Ce code du formulaire, je le laisse en dehors du module ?

    Je creuse la question de l'objet requis.

    Merci encore.

    Lassé par la pub ? Créez un compte