XL 2021 UserForm en guise de MsgBox qui ne fonctionne pas...

Boostez vos compétences Excel avec notre communauté !

Rejoignez Excel Downloads, le rendez-vous des passionnés où l'entraide fait la force. Apprenez, échangez, progressez – et tout ça gratuitement ! 👉 Inscrivez-vous maintenant !

Constantin

XLDnaute Occasionnel
Supporter XLD
Bonjour,
Dans le fichier joint, dans la feuille "départs", la macro2 chainée au bouton bleu est censée :
- Effacer dans "base de données" la ligne qui contient Nom20 Prénom Régis pour peu l'on soit positionné sur G13 dans "départs"
- Afficher un message d'information
- me repositionner dans la feuille "base de données"
Il doit y avoir un bug dans le code de macro2 car Effacer dans "base de données" la ligne qui contient Nom20 Prénom Régis ne s'exécute pas...
Il faut dire que la programmation avec UserForms n'est pas toute simple.
Si quelqu'un a une idée je suis preneur et aussi qu'il m'explique ce qui n'allait pas.
A bientôt ?
 

Pièces jointes

bonjour,
il me semble que tu essaies d'ingérer trop d'informations.

dessiner un userform c'est sommes toutes pas très compliqué il suffit avec la souris de cliker sur un contrôle et de le dimensionner sur le formulaire.

sélectionner une référence comme un WebBrowser c'est déjà plus compliqué.

de la a faire vivre ce formulaire pour en faire ce qu'on veut c'est encore autre chose.

si j'ai bien compris tu souhaites avoir une implantation qui reprend l'idée du msgbox mais un peu plus stylisé ?

déjà ton code fonctionnait il avant de tenter d'intégrer ce userform ?
 
Dernière édition:
Merci à tous,
fanfan38 ayant trouvé la solution pour l'effacement de la ligne de base de données. Par contre le MsgBox de fin d'action (quand il y a eu effacement des données) et le repositionnement sur la feuille base données ne s'exécutent plus. J'imagine que les codes du MsgBox et de l'appel de la cellule E4 dans base données ne sont pas à la bonne place.
Je joins le fichier réactualisé avec "Public rep As String"
A bientôt ?
 

Pièces jointes

Bonjour à tous,
Bon quoi dire... Quand vous travailler sur des formulaires à partir de module standards il faut passer par des propriétés. Sinon vous cassez l'encapsulation du formulaire.
Évitez aussi les variables publiques on le dit à chaque fois c'est source à problèmes, et difficilement gérable.
Troisième point votre formulaire ne doit faire qu'une chose renvoyer Vrai ou Faux exit les messages d'informations ce n'est pas son rôle. sinon vous brisez le SRP.
Quatrième point, donner des noms explicites a vos variables et procédures vous vous y retrouverez bien mieux.
Cinquième point, Toujours mettre "Otion Explicit" en tête de module. (Cela vous évitera pas mal de déconvenues.)
Partant de ces points nous pouvons modifier la classe de votre formulaire comme ceci.

VB:
Option Explicit

Private mReturnValue As VBA.VbMsgBoxResult
Private mLabelMessage As String

'// Retourne la valeur sélectionnée
Public Property Get returnValue() As VBA.VbMsgBoxResult
    returnValue = mReturnValue
End Property
Public Property Let returnValue(ByVal NewValue As VBA.VbMsgBoxResult)
    mReturnValue = NewValue
End Property

'// Met à jour le message d'information
Public Property Get LabelMessage() As String
    LabelMessage = mLabelMessage
End Property
Public Property Let LabelMessage(ByVal NewValue As String)
    Label2.Caption = NewValue
End Property

Private Sub CommandValid_Click()
    mReturnValue = vbYes
    Me.Hide '// On cache et on retourne au programme appelant.
End Sub

Private Sub CommandCancel_Click()
    mReturnValue = vbNo
    Me.Hide '// On cache et on retourne au programme appelant.
End Sub

Private Sub UserForm_Activate()
    Me.Caption = mLabelMessage
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    'vbFormControlMenu  0   L'utilisateur a choisi la commande Fermer dans le menu Système du formulaire utilisateur.
    'vbFormCode         1   L'instruction Unload est appelée à partir du code.
    'vbAppWindows       2   La session active de l'environnement d'exploitation Windows se termine.
    'vbAppTaskManager   3   Le Gestionnaire de tâches de Windows ferme l'application.
    Select Case CloseMode
        Case vbFormControlMenu
            Cancel = True
            mReturnValue = vbNo
            Me.Hide ' // On cache et on retourne au programme appelant.
    End Select
End Sub

Maintenant il reste à gérer tout cela dans votre procédure appelante (renommée en "EffacerLigneDépart")
Voici certains points à prendre en considération.
Évitez les Exit Sub, Fonction, et autres si ce n'est pas obligatoire (d'autres options s'offrent à vous.)
Regardez les commentaires pour les explications...
Code:
Sub EffacerLigneDepart()
    Call SauvegardeAutomatique '// Evitez d'utiliser Call cela ne sert que pour la les anciens codes.
 
    On Error GoTo FinR
 
    With sh_Data
 
        Dim L As Long
        L = Selection.Row                                       ' Ligne sélectionnée
     
        Dim Nom As String
        Nom = sh_Departs.Cells(L, "K")
     
        Dim Prénom As String
        Prénom = sh_Departs.Cells(L, "L")
     
        If Nom = vbNullString Or Prénom = vbNullString Then MsgBox "Sélectionnez un nom valide en colonne Nom de la feuille departs.": Exit Sub ' Verif si ligne valide
     
        With EXPORTATION
            '// On définit la propriété pour le message
            .LabelMessage = "Vous êtes sur le point d'effacer les donnée de : " & Nom & Space(1) & Prénom & vbNewLine & vbNewLine & _
                            "Voulez-Vous vraiment continuer ?"

            '// On affiche le formulaire
            .Show
            '// Sur click dans le formulaire on le cache et on arrive ici.
            Dim returnValue
            returnValue = .returnValue                          ' // On charge la valeur de retour
            Unload EXPORTATION                                  '// On ferme le formulaire
        End With
     
        Select Case returnValue                                 '// Sélection par rapporrt au choix sélectionné
            Case vbYes
                Dim DL As Long
                DL = .Cells(Rows.Count, "E").End(xlUp).Row      ' recherche dernière ligne des noms dans base de données
                Application.EnableEvents = False
                Dim Ligne As Long
                For Ligne = 4 To DL                             ' on parcourt toutes les lignes
                    If .Cells(Ligne, "E") = Nom And .Cells(Ligne, "F") = Prénom Then ' si Nom et Prénom trouvés, on efface
                        '// Ne voudrait-il pas mieux supprimer la ligne complète ?
                        .Range(.Cells(Ligne, "E"), .Cells(Ligne, "AA")).ClearContents
                    End If
                Next Ligne
            Case vbNo
                MsgBox "Action annulée par l'utilisateur", vbOKOnly, "Gestion des employés."

            Case vbCancel
                Dim problemMessage As String
                problemMessage = "Oupss... Nous avons rencontré une erreur en voulant supprimer les données de cette personne : " & _
                Nom & Space(1) & Prénom & "."
             
                MsgBox problemMessage, vbOKOnly Or vbCritical, "Gestion des employés."

        End Select
     
    End With


FinR:
    Application.EnableEvents = True
End Sub

Bonne programmation... Jean-Paul
 
Dernière édition:
Bonjour à tous,
Bon quoi dire... Quand vous travailler sur des formulaires à partir de module standards il faut passer par des propriétés. Sinon vous cassez l'encapsulation du formulaire.
Évitez aussi les variables publiques on le dit à chaque fois c'est source à problèmes, et difficilement gérable.
Troisième point votre formulaire ne doit faire qu'une chose renvoyer Vrai ou Faux exit les messages d'informations ce n'est pas son rôle. sinon vous brisez le SRP.
Quatrième point, donner des noms explicites a vos variables et procédures vous vous y retrouverez bien mieux.
Cinquième point, Toujours mettre "Otion Explicit" en tête de module. (Cela vous évitera pas mal de déconvenues.)
Partant de ces points nous pouvons modifier la classe de votre formulaire comme ceci.

VB:
Option Explicit

Private mReturnValue As VBA.VbMsgBoxResult
Private mLabelMessage As String

'// Retourne la valeur sélectionnée
Public Property Get returnValue() As VBA.VbMsgBoxResult
    returnValue = mReturnValue
End Property
Public Property Let returnValue(ByVal NewValue As VBA.VbMsgBoxResult)
    mReturnValue = NewValue
End Property

'// Met à jour le message d'information
Public Property Get LabelMessage() As String
    LabelMessage = mLabelMessage
End Property
Public Property Let LabelMessage(ByVal NewValue As String)
    Label2.Caption = NewValue
End Property

Private Sub CommandValid_Click()
    mReturnValue = vbYes
    Me.Hide '// On cache et on retourne au programme appelant.
End Sub

Private Sub CommandCancel_Click()
    mReturnValue = vbNo
    Me.Hide '// On cache et on retourne au programme appelant.
End Sub

Private Sub UserForm_Activate()
    Me.Caption = mLabelMessage
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    'vbFormControlMenu  0   L'utilisateur a choisi la commande Fermer dans le menu Système du formulaire utilisateur.
    'vbFormCode         1   L'instruction Unload est appelée à partir du code.
    'vbAppWindows       2   La session active de l'environnement d'exploitation Windows se termine.
    'vbAppTaskManager   3   Le Gestionnaire de tâches de Windows ferme l'application.
    Select Case CloseMode
        Case vbFormControlMenu
            Cancel = True
            mReturnValue = vbNo
            Me.Hide ' // On cache et on retourne au programme appelant.
    End Select
End Sub

Maintenant il reste à gérer tout cela dans votre procédure appelante (renommée en "EffacerLigneDépart")
Voici certains points à prendre en considération.
Évitez les Exit Sub, Fonction, et autres si ce n'est pas obligatoire (d'autres options s'offrent à vous.)
Regardez les commentaires pour les explications...
Code:
Sub EffacerLigneDepart()
    Call SauvegardeAutomatique '// Evitez d'utiliser Call cela ne sert que pour la les anciens codes.
 
    On Error GoTo FinR
 
    With sh_Data
 
        Dim L As Long
        L = Selection.Row                                       ' Ligne sélectionnée
    
        Dim Nom As String
        Nom = sh_Departs.Cells(L, "K")
    
        Dim Prénom As String
        Prénom = sh_Departs.Cells(L, "L")
    
        If Nom = vbNullString Or Prénom = vbNullString Then MsgBox "Sélectionnez un nom valide en colonne Nom de la feuille departs.": Exit Sub ' Verif si ligne valide
    
        With EXPORTATION
            '// On définit la propriété pour le message
            .LabelMessage = "Vous êtes sur le point d'effacer les donnée de : " & Nom & Space(1) & Prénom & vbNewLine & vbNewLine & _
                            "Voulez-Vous vraiment continuer ?"

            '// On affiche le formulaire
            .Show
            '// Sur click dans le formulaire on le cache et on arrive ici.
            Dim returnValue
            returnValue = .returnValue                          ' // On charge la valeur de retour
            Unload EXPORTATION                                  '// On ferme le formulaire
        End With
    
        Select Case returnValue                                 '// Sélection par rapporrt au choix sélectionné
            Case vbYes
                Dim DL As Long
                DL = .Cells(Rows.Count, "E").End(xlUp).Row      ' recherche dernière ligne des noms dans base de données
                Application.EnableEvents = False
                Dim Ligne As Long
                For Ligne = 4 To DL                             ' on parcourt toutes les lignes
                    If .Cells(Ligne, "E") = Nom And .Cells(Ligne, "F") = Prénom Then ' si Nom et Prénom trouvés, on efface
                        '// Ne voudrait-il pas mieux supprimer la ligne complète ?
                        .Range(.Cells(Ligne, "E"), .Cells(Ligne, "AA")).ClearContents
                    End If
                Next Ligne
            Case vbNo
                MsgBox "Action annulée par l'utilisateur", vbOKOnly, "Gestion des employés."

            Case vbCancel
                Dim problemMessage As String
                problemMessage = "Oupss... Nous avons rencontré une erreur en voulant supprimer les données de cette personne : " & _
                Nom & Space(1) & Prénom & "."
            
                MsgBox problemMessage, vbOKOnly Or vbCritical, "Gestion des employés."

        End Select
    
    End With


FinR:
    Application.EnableEvents = True
End Sub

Bonne programmation... Jean-Paul
Bonjour Jean-Paul,
Merci de vos commentaires et suggestions. Comme vous pouvez vous en rendre compte, je ne suis pas un pro d' Excel.
J'imagine que vous avez du tester vos formules sur mon fichier ? Peut-être en avez-vous gardé une copie. Si vous pouviez me l'envoyer, ce serait avec plaisir car là, je n'ai pas le niveau pour savoir ou et comment copier et remplacer tous mes codes.
Vous me dites d'éviter la fonction "Call macro"... Pourquoi ? Par quoi la remplacer (c'est quand même bien pratique)...
Je n'apprends que grâce à toutes les suggestions que le forum m'envoie,
Bien cordialement
 
Bonjour à tous,
Bon quoi dire... Quand vous travailler sur des formulaires à partir de module standards il faut passer par des propriétés. Sinon vous cassez l'encapsulation du formulaire.
Évitez aussi les variables publiques on le dit à chaque fois c'est source à problèmes, et difficilement gérable.
Troisième point votre formulaire ne doit faire qu'une chose renvoyer Vrai ou Faux exit les messages d'informations ce n'est pas son rôle. sinon vous brisez le SRP.
Quatrième point, donner des noms explicites a vos variables et procédures vous vous y retrouverez bien mieux.
Cinquième point, Toujours mettre "Otion Explicit" en tête de module. (Cela vous évitera pas mal de déconvenues.)
Partant de ces points nous pouvons modifier la classe de votre formulaire comme ceci.

VB:
Option Explicit

Private mReturnValue As VBA.VbMsgBoxResult
Private mLabelMessage As String

'// Retourne la valeur sélectionnée
Public Property Get returnValue() As VBA.VbMsgBoxResult
    returnValue = mReturnValue
End Property
Public Property Let returnValue(ByVal NewValue As VBA.VbMsgBoxResult)
    mReturnValue = NewValue
End Property

'// Met à jour le message d'information
Public Property Get LabelMessage() As String
    LabelMessage = mLabelMessage
End Property
Public Property Let LabelMessage(ByVal NewValue As String)
    Label2.Caption = NewValue
End Property

Private Sub CommandValid_Click()
    mReturnValue = vbYes
    Me.Hide '// On cache et on retourne au programme appelant.
End Sub

Private Sub CommandCancel_Click()
    mReturnValue = vbNo
    Me.Hide '// On cache et on retourne au programme appelant.
End Sub

Private Sub UserForm_Activate()
    Me.Caption = mLabelMessage
End Sub

Private Sub UserForm_QueryClose(Cancel As Integer, CloseMode As Integer)
    'vbFormControlMenu  0   L'utilisateur a choisi la commande Fermer dans le menu Système du formulaire utilisateur.
    'vbFormCode         1   L'instruction Unload est appelée à partir du code.
    'vbAppWindows       2   La session active de l'environnement d'exploitation Windows se termine.
    'vbAppTaskManager   3   Le Gestionnaire de tâches de Windows ferme l'application.
    Select Case CloseMode
        Case vbFormControlMenu
            Cancel = True
            mReturnValue = vbNo
            Me.Hide ' // On cache et on retourne au programme appelant.
    End Select
End Sub

Maintenant il reste à gérer tout cela dans votre procédure appelante (renommée en "EffacerLigneDépart")
Voici certains points à prendre en considération.
Évitez les Exit Sub, Fonction, et autres si ce n'est pas obligatoire (d'autres options s'offrent à vous.)
Regardez les commentaires pour les explications...
Code:
Sub EffacerLigneDepart()
    Call SauvegardeAutomatique '// Evitez d'utiliser Call cela ne sert que pour la les anciens codes.
 
    On Error GoTo FinR
 
    With sh_Data
 
        Dim L As Long
        L = Selection.Row                                       ' Ligne sélectionnée
    
        Dim Nom As String
        Nom = sh_Departs.Cells(L, "K")
    
        Dim Prénom As String
        Prénom = sh_Departs.Cells(L, "L")
    
        If Nom = vbNullString Or Prénom = vbNullString Then MsgBox "Sélectionnez un nom valide en colonne Nom de la feuille departs.": Exit Sub ' Verif si ligne valide
    
        With EXPORTATION
            '// On définit la propriété pour le message
            .LabelMessage = "Vous êtes sur le point d'effacer les donnée de : " & Nom & Space(1) & Prénom & vbNewLine & vbNewLine & _
                            "Voulez-Vous vraiment continuer ?"

            '// On affiche le formulaire
            .Show
            '// Sur click dans le formulaire on le cache et on arrive ici.
            Dim returnValue
            returnValue = .returnValue                          ' // On charge la valeur de retour
            Unload EXPORTATION                                  '// On ferme le formulaire
        End With
    
        Select Case returnValue                                 '// Sélection par rapporrt au choix sélectionné
            Case vbYes
                Dim DL As Long
                DL = .Cells(Rows.Count, "E").End(xlUp).Row      ' recherche dernière ligne des noms dans base de données
                Application.EnableEvents = False
                Dim Ligne As Long
                For Ligne = 4 To DL                             ' on parcourt toutes les lignes
                    If .Cells(Ligne, "E") = Nom And .Cells(Ligne, "F") = Prénom Then ' si Nom et Prénom trouvés, on efface
                        '// Ne voudrait-il pas mieux supprimer la ligne complète ?
                        .Range(.Cells(Ligne, "E"), .Cells(Ligne, "AA")).ClearContents
                    End If
                Next Ligne
            Case vbNo
                MsgBox "Action annulée par l'utilisateur", vbOKOnly, "Gestion des employés."

            Case vbCancel
                Dim problemMessage As String
                problemMessage = "Oupss... Nous avons rencontré une erreur en voulant supprimer les données de cette personne : " & _
                Nom & Space(1) & Prénom & "."
            
                MsgBox problemMessage, vbOKOnly Or vbCritical, "Gestion des employés."

        End Select
    
    End With


FinR:
    Application.EnableEvents = True
End Sub

Bonne programmation... Jean-Paul
Je précise par ailleurs que ce fichier anonymisé correspond à un programme utilisé par une association de jardiniers. Il est actuellement dépourvu de macros facilitant son exploitation et je suis chargé d'essayer de faire quelque chose. Je pars donc d'un existant dont je ne dois pas modifier la structure et la finalité (bilan de fin d'année) sauf à le rendre plus lisible et plus facile à utiliser pour des gens qui sont encore moins au fait d' Excel que moi (si c'est possible).
A bientôt ?
 
Re Constantin,

Ce que j'ai fait :
  • Au niveau des feuilles
    • J'ai renommé "Feuil1" => "sh_Data"
    • J'ai renommé "Feuil2" => "sh_Departs"
    • Sur "Feuil2" maintenant "sh_Departs" faites pointer le bouton "Effacer les données de départ" sur la procédure "EffacerLigneDepart()"
  • Dans le module m_Macro1_et_2
    • Supprimer la macro 2
    • Remplacer la par celle que je vous ai fournis "EffacerLigneDepart()" (C'est la deuxième)
  • Sur le formulaire
    • Supprimer tout le code de la classe
    • Remplacer le par le code fournis. (C'est le premier)
Voilà, c'est tout Normalement, tester en cliquant sur le bouton. (Bleu)
Pour répondre à votre question sur le Call il nous vient de bien loin "Quick Basic" si mes souvenirs sont bon il n'est utilisé que pour la compatibilité ascendante, des vieux programmes.
Donc au lieux de faire Call EffacerLigneDepart() vous faite simplement EffacerLigneDepart. Voilà pourquoi on demande à donner des noms explicite aux variables, Fonctions et procédures.

Petits points supplémentaires :
  • Pour vos tableaux passer avec des tableaux structurés cela vous facilitera le travail.
  • Chercher un ligne par le nom c'est aller au casse pipe. (Utiliser plutôt un identifiant unique pour chaque ligne et rechercher-le)
  • La boite de dialogue avec écriture en gras (Ça pique les yeux)
Si vous voulez à tout prix avoir des boites de dialogues personnalisées voici un module à mettre dans votre projet. Lisez bien l'entête pour pouvoir l'utiliser correctement.
 

Pièces jointes

Bonsoir,
Rien à voir avec la discussion en cours, juste une petite précision....
Pour répondre à votre question sur le Call il nous vient de bien loin "Quick Basic" si mes souvenirs sont bon il n'est utilisé que pour la compatibilité ascendante, des vieux programmes.
Donc au lieux de faire Call EffacerLigneDepart() vous faite simplement EffacerLigneDepart. Voilà pourquoi on demande à donner des noms explicite aux variables,
Du plus loin que je puisse me souvenir, le Call servait en général à la compilation du code....(compilation effectuée dès l'ouverture du fichier)
Et que cette instruction permettait un traitement plus rapide .... (l'appel à la procédure étant implicitement exécuté)
Mais je peux me tromper...
Bonne soirée
 
Merci de vos envois... qui me laissent un peu perplexe, je l'avoue. Ne vous en étonnez pas, mon niveau n'est pas brillant...
Je vais faire des tests pour essayer d'assimiler et surtout comprendre ce que cela peut changer en termes de résultats.
Vous parlez de vieux programmes. Pour info, je vais avoir 71 ans... Pas étonnant, alors...
 
Bonjour,
dans un module standard
VB:
Sub test()
MsgBox Message.Message("Message simple", vbOKOnly, "Titre")
MsgBox Message.Message("Confirmer ?", vbYesNo, "Confirmation")
MsgBox Message.Message("Attention !", vbExclamation + vbOKOnly, "Avertissement")
MsgBox Message.Message("Erreur critique", vbCritical + vbOKOnly, "Erreur")
MsgBox Message.Message("Question ?", vbQuestion + vbYesNoCancel, "Question")
MsgBox Message.Message("Information", vbInformation + vbOKOnly, "Information")
MsgBox Message.Message("Réessayer ?", vbRetryCancel + vbExclamation, "Nouvel essai")
MsgBox Message.Message("Annuler ou continuer ?", vbOKCancel + vbExclamation, "Choix")
MsgBox Message.Message("Oui ou Non ?", vbYesNo + vbQuestion, "Décision")
End Sub
 

Pièces jointes

- Navigue sans publicité
- Accède à Cléa, notre assistante IA experte Excel... et pas que...
- Profite de fonctionnalités exclusives
Ton soutien permet à Excel Downloads de rester 100% gratuit et de continuer à rassembler les passionnés d'Excel.
Je deviens Supporter XLD

Discussions similaires

Retour