Intégrer une liste de choix dans une macro

NMS31

Nouveau membre
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
 

zeb

Modérateur
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.
 

NMS31

Nouveau membre
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 :
Code:
Option Explicit

Sub Extraction_base()
 
Dim Base As Worksheet
Dim paravb As Worksheet

Set Base = Worksheets("Base")

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
Dim chemin As String
Dim var_temp_5, Message, Message2, Titre, Message3, Titre3, Message4, Titre4, Message5, Titre2, Titre5, Default, MyValue, MyValue2, Resultat

' Définit le message.
'Message = "Précisez le chemin pour atteindre le dossier de traitement"
'Titre = "Chemin"    ' Définit le titre.
' Affiche le message, le titre et la valeur par défaut.
'MyValue = InputBox(Message, Title, Default)

' Définit le message.
'Message2 = "Précisez le nom du fichier à traiter - Ne pas oublier l'extension .xls"
'Titre2 = "Fichier"    ' Définit le titre.
' Affiche le message, le titre et la valeur par défaut.
'MyValue2 = InputBox(Message2, Titre2, Default)
  
 '   chemin = MyValue
 '   fichier = MyValue2
    
 ' Set fs = Application.FileSearch
'With fs
  '  .LookIn = chemin
 '   .Filename = fichier
  '  .MatchTextExactly = True

  '  If .Execute > 0 Then
        
    'Workbooks.Open Filename:=MyValue & "\" & MyValue2
    
    'End If


Dim Msg, Style, Title, Help, Ctxt, Response, MyString
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"
Style = vbOKCancel
Title = "Attention"
Help = "DEMO.HLP"    ' Définit le fichier d'aide.
Ctxt = 1000    ' Définit le contexte de
                ' la rubrique.
' Affiche le message.
Response = MsgBox(Msg, Style, Title, Help, Ctxt)
If Response = 2 Then
Exit Sub
End If

lstrow = Base.Range("A65536").End(xlUp).Row

lstcol = Base.Range("IF1").End(xlUp).Column

nbchamps = 0

For t = 1 To 256
If Base.Cells(1, t) <> "" Then
nbchamps = nbchamps + 1
End If
Next

'créer un nouvel onglet "paravb"
Set paravb = Sheets.Add(Type:=xlWorksheet)
Sheets("Feuil1").Select
    Sheets("Feuil1").Name = "paravb"
    
Set paravb = Worksheets("paravb")

'Choix du critère principal
'Définit le message.
Message3 = "Précisez le numéro de colonne du critère principal qui servira à la création des onglets"
Titre3 = "Critère principal"    ' Définit le titre.
' Affiche le message, le titre et la valeur par défaut.
Resultat = InputBox(Message3, Titre3, Default)
col_critère_princ = Resultat * 1
paravb.Cells(1, 1) = "Critère principal"
paravb.Cells(2, 1) = Base.Cells(2, col_critère_princ)

'Liste des différentes valeurs du critère principal
b = 4
i = 0
paravb.Cells(3, 1) = Base.Cells(3, col_critère_princ)
For i = 4 To 76
c = 0
test = 0
For c = 1 To b - 1
If Base.Cells(i, col_critère_princ) = paravb.Cells(c, 1) Then
test = test + 1
End If
Next
If test = 0 Then
paravb.Cells(b, 1) = Base.Cells(i, col_critère_princ)
b = b + 1
End If
Next


Base.Activate

'Choix des critères secondaires
'Définit le message.
Message4 = "Combien de critères secondaires souhaitez-vous prendre en compte pour cette extraction ?"
Titre4 = "Nb critères secondaires"    ' Définit le titre.
' Affiche le message, le titre et la valeur par défaut.
nb_crit_sec = InputBox(Message4, Titre4, Default)

For s = 1 To nb_crit_sec
Message5 = "Précisez le numéro de colonne du critère secondaire n° " & s
Titre5 = "Critère secondaire n° " & s ' Définit le titre.
' Affiche le message, le titre et la valeur par défaut.
var_temp_5 = InputBox(Message5, Titre5, Default)
col_critère_sec = var_temp_5 * 1
paravb.Cells(1, s + 1) = "Critère secondaire " & s
paravb.Cells(2, s + 1) = Base.Cells(2, col_critère_sec)

'Liste des différentes valeurs des critères secondaires
b = 4
i = 0
paravb.Cells(3, s + 1) = Base.Cells(3, col_critère_sec)
For i = 4 To lstrow
c = 0
test = 0
For c = 1 To b - 1
If Base.Cells(i, col_critère_sec) = paravb.Cells(c, s + 1) Then
test = test + 1
End If
Next
If test = 0 Then
paravb.Cells(b, s + 1) = Base.Cells(i, col_critère_sec)
b = b + 1
End If
Next
Next

'Définir les valeurs des différents critères sélectionnés

Dim f As Range

'ListBox1.Clear
'For Each f In paravb.Range("a1")
 ' If f.Value = "" Then Exit For
  'ListBox1.AddItem f.Value
'Next

'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
val_critère_princ = "75"

i = 0
m = 1
l = 2

Dim CP1 As Worksheet

Set CP1 = Sheets.Add(Type:=xlWorksheet)
Sheets("Feuil2").Select
    Sheets("Feuil2").Name = paravb.Cells(2, 1) & " = " & val_critère_princ
   


Set CP1 = Worksheets(paravb.Cells(2, 1) & " = " & val_critère_princ)

'quand la boucle for sera mise en place:
'Dim CP&v as worksheet
'CP&v=worksheets(paravb.Cells(2, 1) & " = " & val_critère_princ)

paravb.Activate

'Boucle de remplissage onglet

For i = 3 To lstrow + 3

If Base.Cells(i, 1) <> "" Then

If Base.Cells(i, col_critère_princ).Text = val_critère_princ Then

j = 1
k = 1

For m = 1 To lstcol

Do While Base.Cells(2, j) <> ""

If Base.Cells(1, j) <> "" Then

'Titre
CP1.Cells(1, k) = Base.Cells(2, j)

'Remplissage cellules
CP1.Cells(l, k) = Base.Cells(i, j)
k = k + 1

End If

j = j + 1

Exit Do

Loop

Next

End If

End If

l = l + 1
Next

'Fin de boucle de remplissage onglet

'Mise en forme 1ère ligne
Rows("1:1").Select
    Selection.Font.Bold = True
    
Cells.Select
    Cells.EntireColumn.AutoFit


End Sub

Merci beaucoup.

NMS31
 

zeb

Modérateur
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 :
Code:
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)
Code:
... 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 :
Code:
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 ?
 

NMS31

Nouveau membre
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 :
Code:
Private Sub Tous_Click()
Dim i As Integer

For i = 0 To ListBox1.ListCount - 1
  ListBox1.Selected(i) = True
Next

End Sub

Private Sub Aucun_Click()
Dim i As Integer

For i = 0 To ListBox1.ListCount - 1
  ListBox1.Selected(i) = False
Next

End Sub

Private Sub Valider_Click()

End Sub

Private Sub Annuler_Click()

End Sub

Private Sub ListBox1_Click()
Dim c As Range
For Each c In paravb.Range("a3:a9")
 'If c.Value = "" Then Exit For
  ListBox1.AddItem c.Value
Next

End Sub

Merci beaucoup pour ton aide.

NMS31
 

zeb

Modérateur
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
 

zeb

Modérateur
Donc, ligne 141, tu appelles ton userform :
Code:
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.
 

NMS31

Nouveau membre
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.

Code:
Private Sub Tous_Click()
Dim i As Integer

For i = 0 To ListBox1.ListCount - 1
  ListBox1.Selected(i) = True
Next

End Sub

Private Sub Aucun_Click()
Dim i As Integer

For i = 0 To ListBox1.ListCount - 1
  ListBox1.Selected(i) = False
Next

End Sub

Private Sub Valider_Click()

End Sub

Private Sub Annuler_Click()

End Sub

Private Sub ListBox1_Click()

ListBox1.AddItem "75"
ListBox1.AddItem "77"
ListBox1.AddItem "C3"
ListBox1.AddItem "C4"
ListBox1.Show
    
End Sub

Private Sub UserForm_click()
Load ListBox1
Load Tous
Load Aucun
Load Valider
Load Annuler

ListBox1.Show
Tous.Show
Aucun.Show
Valider.Show
Annuler.Show

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.
 

NMS31

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

Code:
Private Sub Tous_Click()
Dim i As Integer

For i = 0 To ListBox1.ListCount - 1
  ListBox1.Selected(i) = True
Next

End Sub

Private Sub Aucun_Click()
Dim i As Integer

For i = 0 To ListBox1.ListCount - 1
  ListBox1.Selected(i) = False
Next

End Sub

Private Sub ListBox1_Click()

ListBox1.AddItem "75"
ListBox1.AddItem "77"
ListBox1.AddItem "C3"
ListBox1.AddItem "C4"
ListBox1.Show
   
End Sub

Private Sub UserForm_click()
Load ListBox1
Load Tous
Load Aucun
Load Valider
Load Annuler

ListBox1.Show
Tous.Show
Aucun.Show
Valider.Show
Annuler.Show

End Sub
 

zeb

Modérateur
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 :
Code:
Public Sub Chargement
    ListBox1.AddItem "75"
    ListBox1.AddItem "77"
    ListBox1.AddItem "C3"
    ListBox1.AddItem "C4"
End Sub

Code:
le_userform_de_NMS31.Chargement
le_userform_de_NMS31.Show
 

NMS31

Nouveau membre
Bonjour zeb,

Je patauge... :cry:
J'ai rajouté la fonction Chargement mais quand je l'appelle, j'ai une erreur d'exécution 91 - variable d'objet ou variable de bloc with non définie.

Merci pour ton aide.

NMS31
 

zeb

Modérateur
Salut,

Où cette fonction est-elle définie ?
La bonne réponse est : dans le code du userform, bien sûr.
 

NMS31

Nouveau membre
Désolée, je ne comprend pas. J'ai défini la fonction de la façon suivante:
Code:
Public Sub Tous_Click()
Dim ListBox1 As listbox

Dim i As Integer

For i = 0 To ListBox1.ListCount - 1
  ListBox1.Selected(i) = True
Next

End Sub

Public Sub Aucun_Click()
Dim ListBox1 As listbox

Dim i As Integer

For i = 0 To ListBox1.ListCount - 1
  ListBox1.Selected(i) = False
Next

End Sub


Public Sub Annuler_Click()
Dim Mon_UserForm As UserForm

Mon_UserForm.Close

End Sub

Public Sub Mon_UserForm_Initialize()

Dim ListBox1 As listbox
Dim Tous As CommandButton
Dim Aucun As CommandButton
Dim Valider As CommandButton
Dim Annuler As CommandButton

Load ListBox1
Load Tous
Load Aucun
Load Valider
Load Annuler

ListBox1.Show
Tous.Show
Aucun.Show
Valider.Show
Annuler.Show

End Sub

Public Sub Chargement()

Dim ListBox1 As listbox

ListBox1.AddItem "75"
    ListBox1.AddItem "77"
    ListBox1.AddItem "C3"
    ListBox1.AddItem "C4"

End Sub

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

zeb

Modérateur
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 :
Code:
Private Sub CommandButton1_Click()

End Sub
■ 5°) Ajoutes-y au milieu le code suivant :
Code:
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 :
Code:
Sub AppelUserForm
    userform1.Chargement
    userform1.Show
End Sub

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

NMS31

Nouveau membre
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:
Code:
Private Sub Annuler_Click()
Unload Me
End Sub

J'ai rajouté à la suite le code de chargement :
Code:
Public Sub Chargement()
    ListBox1.AddItem "75"
    ListBox1.AddItem "77"
    ListBox1.AddItem "C3"
    ListBox1.AddItem "C4"
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):
Code:
Sub AppelUserForm
    userform1.Chargement
    userform.Show
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.
 

zeb

Modérateur
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 ?
 

NMS31

Nouveau membre
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 :

Code:
Sub AppelUserForm
Dim UserForm1 as UserForm
    UserForm1.Chargement
    UserForm1.Show
End Sub

Merci.
 

zeb

Modérateur
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 :
Code:
Sub AppelUserForm
    Load UserForm1
    userform1.ChargementDesDonnees
    userform.Show
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. :)
 
Vous devez vous inscrire ou vous connecter pour répondre ici.
Derniers messages publiés
Statistiques globales
Discussions
730 134
Messages
6 718 055
Membres
1 586 393
Dernier membre
mathhh28
Partager cette page
Haut