Code VBA sur formulaire incorrect

Bonjour,

Je suis nouvelle sur ce forum...pardonnez moi si je ne poste pas au bon endroit...

Je suis en train de créer une petite base de données pour mon entreprise, et mon responsable souhaite que je mette en place un formulaire, plus "visuel" qu'un gros tableau Excel.

Novice en codage VBA, je me suis lancée dans la création d'un formulaire sur Visual Basic, mais malheureusement mon code ne fonctionne pas...pourriez-vous m'aider et identifier d'ou vient le problème??

Je mets en copie mon fichier Excel et ci-dessous mon code.

Merci par avance de votre aide

Option Explicit

Dim Ws As Worksheet

'Pour le formulaire

Private Sub UserForm_Initialize()

Dim J As Long

Dim I As Integer

Set Ws = Sheets("Informations personnelles") 'Correspond au nom de l'onglet dans le fichier Excel

With Me.ComboBox1

For J = 2 To Ws.Range("D" & Rows.Count).End(xlUp).Row

.AddItem Ws.Range("D" & J)

Next J

End With

For I = 0 To 13

Me.Controls("TextBox" & I).Visible = True

Next I

End Sub

'Pour la liste déroulante Nom

Private Sub ComboBox1_Change()

Dim Ligne As Long

Dim I As Integer

If Me.ComboBox1.ListIndex = -1 Then Exit Sub

Ligne = Me.ComboBox1.ListIndex + 2

ComboBox1 = Ws.Cells(Ligne, "D")

For I = 1 To 13

Me.Controls("TextBox" & I) = Ws.Cells(Ligne, I + 2)

Next I

End Sub

'Pour le bouton Nouveau salarié

Private Sub CommandButton1_Click()

Dim L As Integer

If MsgBox("Confirmez-vous l'insertion de ce nouveau salarié ?", vbYesNo, "Demande de confirmation d'ajout") = vbYes Then

L = Sheets("Informations personnelles").Range("a65536").End(xlUp).Row + 1 'Pour placer le nouvel enregistrement à la première ligne de tableau non vide

Range("D" & L).Value = ComboBox1

Range("E" & L).Value = TextBox1

Range("F" & L).Value = TextBox2

Range("J" & L).Value = TextBox3

Range("I" & L).Value = TextBox4

Range("K" & L).Value = TextBox5

Range("N" & L).Value = TextBox6

Range("O" & L).Value = TextBox7

Range("L" & L).Value = TextBox8

Range("M" & L).Value = TextBox9

Range("P" & L).Value = TextBox10

Range("Q" & L).Value = TextBox11

Range("G" & L).Value = TextBox12

Range("H" & L).Value = TextBox13

End If

End Sub

'Pour le bouton Modifier

Private Sub CommandButton2_Click()

Dim Ligne As Long

Dim I As Integer

If MsgBox("Confirmez-vous la modification de ce salarié ?", vbYesNo, "Demande de confirmation de modification") = vbYes Then

If Me.ComboBox1.ListIndex = -1 Then Exit Sub

Ligne = Me.ComboBox1.ListIndex + 2

Ws.Cells(Ligne, "D") = ComboBox1

For I = 1 To 13

If Me.Controls("TextBox" & I).Visible = True Then

Ws.Cells(Ligne, I + 2) = Me.Controls("TextBox" & I)

End If

Next I

End If

End Sub

'Pour le bouton Quitter

Private Sub CommandButton3_Click()

Unload Me

End Sub

up

Bonjour

voila une petite modife a toi de voir

A+

Maurice

Private Sub UserForm_Initialize()
    Dim J As Long
    Dim I As Integer

    Set Ws = Sheets("Informations personnelles") 'Correspond au nom de l'onglet dans le fichier Excel
    With Me.ComboBox1
        For J = 6 To Ws.Range("D" & Rows.Count).End(xlUp).Row ' a voir
            .AddItem Ws.Range("D" & J)
        Next J
    End With
    For I = 1 To 13 ' a voir
        Me.Controls("TextBox" & I).Visible = True
    Next I
End Sub

'Pour la liste d?roulante Nom
Private Sub ComboBox1_Change()
Dim Ligne As Long
Dim I As Integer
    If Me.ComboBox1.ListIndex = -1 Then Exit Sub
    Ligne = Me.ComboBox1.ListIndex + 6 ' A voir
    ComboBox1 = Ws.Cells(Ligne, "D")
    For I = 1 To 13
        Me.Controls("TextBox" & I) = Ws.Cells(Ligne, I + 2)
    Next I
End Sub

Bonjour,

Tu essaies de rendre visible un TextBox0 qui n'existe pas !

Au demeurant, si tu n'as pas mis la propriété Visible de tes TextBox à False, il n'y a aucune raison que le Userform s'ouvre avec des Textbox masqués ! Et si tu l'as fait, ce serait vraiment du vice de les masquer pour les démasquer à l'initialisation !

Ceci pour te dire que ce type de commande n'a rien à faire dans une Initialize : tu définis les propriétés par défaut des contrôles, celles qu'ils auront à l'ouverture, à chaque fois, et tu réserves l'initialisation à ce qui ne peut être défini par défaut.

AddItem n'est pas ce qu'il y a de mieux... Utilise List pour affecter ta liste à la Combo...

Tu utilises un tableau Excel, c'est bien à condition de s'en servir , un tel tableau donne lieu à insertion automatique d'un nom par Excel, ce nom correspond à la partie données (hors en-tête), et il est utilisable en VBA à l'instar d'un nom de plage.

Tu peux donc définir ta liste à partir du tableau en le redimensionnant à 1 colonne, liste que tu affectes à la Combo.

Aucun besoin de la feuille que tu peux ignorer. Et tu peux éviter de la mettre en variable module (ce qui n'est pas à priori une très bonne idée...)

Bilan des suggestions :

Private Sub UserForm_Initialize()
    Dim Lst
    Lst = [tblInfosemployé].Resize(, 1).Value
    ComboBox1.List = Lst
End Sub

Tu peux tester cela, ça fonctionne !

Petite dernière remarque : place le code que tu cites dans un post sous balise Code, il en sera plus lisible et mieux lu... Je ne cache pas que le plus souvent je ne lis pas le code lâché en vrac dans un post, ce qui est dommage pour le tien qui est quasi parfaitement indenté, tout à fait à ma convenance sur ce point).

Nb- Je n'ai pas lu le reste...

Cordialement.

Bonjour

voila une petite modife a toi de voir

A+

Maurice

Bonjour Maurice,

Merci de ton aide. Toutefois, la ligne suivante fait planter le formulaire

ComboBox1 = Ws.Cells(Ligne, "D")

Je ne comprends pas pourquoi...

Bonjour,

Tu essaies de rendre visible un TextBox0 qui n'existe pas !

Au demeurant, si tu n'as pas mis la propriété Visible de tes TextBox à False, il n'y a aucune raison que le Userform s'ouvre avec des Textbox masqués ! Et si tu l'as fait, ce serait vraiment du vice de les masquer pour les démasquer à l'initialisation !

Ceci pour te dire que ce type de commande n'a rien à faire dans une Initialize : tu définis les propriétés par défaut des contrôles, celles qu'ils auront à l'ouverture, à chaque fois, et tu réserves l'initialisation à ce qui ne peut être défini par défaut.

AddItem n'est pas ce qu'il y a de mieux... Utilise List pour affecter ta liste à la Combo...

Tu utilises un tableau Excel, c'est bien à condition de s'en servir , un tel tableau donne lieu à insertion automatique d'un nom par Excel, ce nom correspond à la partie données (hors en-tête), et il est utilisable en VBA à l'instar d'un nom de plage.

Tu peux donc définir ta liste à partir du tableau en le redimensionnant à 1 colonne, liste que tu affectes à la Combo.

Aucun besoin de la feuille que tu peux ignorer. Et tu peux éviter de la mettre en variable module (ce qui n'est pas à priori une très bonne idée...)

Bilan des suggestions :

Private Sub UserForm_Initialize()
    Dim Lst
    Lst = [tblInfosemployé].Resize(, 1).Value
    ComboBox1.List = Lst
End Sub

Tu peux tester cela, ça fonctionne !

Petite dernière remarque : place le code que tu cites dans un post sous balise Code, il en sera plus lisible et mieux lu... Je ne cache pas que le plus souvent je ne lis pas le code lâché en vrac dans un post, ce qui est dommage pour le tien qui est quasi parfaitement indenté, tout à fait à ma convenance sur ce point).

Nb- Je n'ai pas lu le reste...

Cordialement.

Bonjour,

Merci beaucoup pour ton explication. Je ne suis pas sûre d'avoir tout saisi, mais je m'accroche

Toutefois, le code que tu me proposes ne me permet pas d'afficher les informations de la personne sélectionnée dans le formulaire...ou alors j'ai mal compris...

Bonjour

tu enlever ce code car il sert a rien

'ComboBox1 = Ws.Cells(Ligne, "D")

A+

Maurice

Re,

Je ne t'ai fournis que l'Initialize... lequel se borne à alimenter ta Combo, le reste vient après.

Un petit complément sur l'Initialize :

Private Sub UserForm_Initialize()
    Dim Lst
    Lst = [tblInfosemployé].Resize(, 1).Value
    ComboBox1.List = Lst
    MultiPage1.Value = 0
End Sub

La dernière ligne est utile pour s'assurer que le Userform s'ouvre sur la première page, il s'ouvre sinon sur celle qu'on a laissé en premier plan dans l'éditeur et il est facile d'avoir cliqué...

Pour la Combo :

Private Sub ComboBox1_Change()
    Dim i%
    LnS = ComboBox1.ListIndex + 1
    If LnS > 0 Then
        With [tblInfosemployé]
            For i = 1 To 13
                Controls("TextBox" & i).Value = .Cells(LnS, i + 1)
            Next i
        End With
    Else
        RéinitCtrl
    End If
End Sub

Mais pour tester, il te faut renuméroter tes TextBox dans l'ordre des colonnes (NB- décalage de 1 : TextBox1 à 13 pour colonnes 2 à 14 du tableau, je dis du tableau, pas de la feuille !)

LnS est la ligne salarié sélectionnée, déclarée niveau module.

RéinitCtrl est une proc. d'effacement des TextBox. Ici l'effacement intervient si tu effaces la combo...

Dim LnS As Long

Sub RéinitCtrl()
    Dim i%
    For i = 1 To 13
        Controls("TextBox" & i).Value = ""
    Next i
    LnS = 0
End Sub

A suivre...

Un immense merci MFerrand!!

Il m'a fallut du temps mais j'ai fini par y arriver!

Par contre, une dernière question si je peux abuser

Concernant mon bouton "modifier le salarié existant", mon code plate sur la ligne suivante :

Private Sub CommandButton2_Click()

Dim Ligne As Long

Dim I As Integer

If MsgBox("Confirmez-vous la modification de ce salarié ?", vbYesNo, "Demande de confirmation de modification") = vbYes Then

If Me.ComboBox1.ListIndex = -1 Then Exit Sub

Ligne = Me.ComboBox1.ListIndex + 2

Ws.Cells(Ligne, "D") = ComboBox1

For I = 1 To 13

If Me.Controls("TextBox" & I).Visible = True Then

Ws.Cells(Ligne, I + 2) = Me.Controls("TextBox" & I)

End If

Next I

End If

End Sub

Pourrais-tu m'éclairer?

Tu aurais dû attendre un petit peu plus car je te propose de procéder autrement, ainis que je l'avais déjà suggéré...

Pour l'erreur, il faut indiquer quelle erreur.

Je te signale aussi que si tu utilises le même fichier ton tableau commence ligne 6 en ce qui concerne les données !

Raison de plus pour utiliser le tableau, partie données dont la numérotation de lignes commencera à 1 ! (adressage relatif qui ne changera pas quelle que soit la position du tableau)

NB- Je réitère aussi mon incitation à te faire utiliser les balises Code !

Pardon je ne suis pas sûre de te suivre quand tu dis que tu proposais de procéder autrement

Je ne voulais pas t'embêter plus, j’espérais un peu m'en sortir toute seule...car pour le reste du formulaire, tout fonctionne...si ce n'est les deux boutons de contrôle

Je reprends pour ce qui des ajouts et modifs.

Tu as pu noter que la proc. CoùboBox1_Change que j'ai proposée initilise la variable module LnS à .ListIndex+1 qui correspond à une numérotation de ligne dans le tableau.

La proc. RéinitCtrl remet cette variable à 0.

Elle a donc une valeur >0 lorsque tu as sélectionné un salarié et que ses données ont été affectées aux TextBox, et vaut 0 si rien dans la Combo ou une saisie de nouveau salarié.

Qu'il s'agit d'ajout ou de modification, l'insertion des données est identique, seule la ligne diffère, la ligne qui suit les données du tableau en cas ajout, la ligne figurant en LnS en cas de modif. mais inutile d'avoir 2 procédures d'affectation :

Sub ValidationInfos()
    Dim Lgn As Range, i%
    Set Lgn = [tblInfosemployé].Rows(LnS)
    Lgn.Cells(1, 1) = ComboBox1.Value
    For i = 1 To 13
        With Controls("TextBox" & i)
            If .Value <> "" Then
                Select Case i
                    Case 5, 6, 8, 9, 11, 13
                        If IsDate(.Value) Then
                            Lgn.Cells(1, i + 1) = CDate(.Value)
                        Else
                            Lgn.Cells(1, i + 1) = .Value
                        End If
                    Case Else
                        Lgn.Cells(1, i + 1) = .Value
                End Select
            End If
        End With
    Next i
    ComboBox1.Value = ""
End Sub

Ma préférence serait allée à la constitution d'un tableau des données de la ligne à servir, affecté directement à la ligne voulue, mais tu as un peu trop de dates à contrôler lors de l'affectation... Donc on procède un peu autrement : on affecte la ligne d'insertion à une variable plage Lgn, et on sert ensuite les cellules de la ligne 1 de cette plage ! La valeur de la Combo ira en col. 1. Pour les TextBox, les valeurs des 1 à 13 iront dans les colonnes 2 à 14, mais on sépare le traitement de ceux susceptibles de contenir des dates (tu peux voir ça dans le code). Les dates doivent toujours être converties en données Date au sortir de TextBox qui ne contiennent par définition que du texte, pour éviter les surprises éventuelles d'inversions mois/jour (résultant d'une conversion sauvage par VBA, utilisant le format américain, la conversion explicite force à utiliser les paramètres FR).

Le changement de valeur de la Combo (mise à "") provoquera l'effacement des TextBox et la remise de LnS à 0.

Mais il convient pour un ajout que LnS qui est alors à 0 soit initialisée pour la nouvelle ligne :

Private Sub CommandButton1_Click()
    If LnS > 0 Then
        MsgBox "Le salarié affiché est déjà dans la base !", vbInformation, "Erreur"
        Exit Sub
    End If
    If MsgBox("Confirmez-vous l'insertion de ce nouveau salarié ?", vbYesNo, _
     "Demande de confirmation d'ajout") = vbYes Then
        LnS = [tblInfosemployé].Rows.Count + 1
        ValidationInfos
        RéinitLst
    End If
End Sub

Ce que va faire ta proc. bouton, qui vérifie avant que l'on n'est pas en mode modif (si LnS>0), qui initialise LnS (nb de lignes du tableau + 1), lance la validation, et à l'issue lance une réinitialisation de la liste de la Combo, après tri du tableau :

Sub RéinitLst()
    Dim Lst
    With [tblInfosemployé]
        .Sort key1:=.Cells(1, 1), order1:=xlAscending, Header:=xlYes
        Lst = .Resize(, 1).Value
    End With
    With ComboBox1
        .Clear: .List = Lst
    End With
End Sub

Pour la modif, c'est symétrique :

Private Sub CommandButton2_Click()
    If LnS = 0 Then
        MsgBox "Le salarié affiché n'est pas dans la base !", vbInformation, "Erreur"
        Exit Sub
    End If
    If MsgBox("Confirmez-vous la modification de ce salarié ?", vbYesNo, _
     "Demande de confirmation de modification") = vbYes Then
        ValidationInfos
    End If
End Sub

Vérification qu'on est bien en mode modif., validation identique, mais on ne réinitialise pas la Combo. En principe les modifs ne touchent pas le nom (à toi de voir par la suite...)

Cordialement.

Si je le fais c'est que cela ne m'embête nullement !

En proposant des éléments qui dérogeaient à l'orientation de ton code initial, il me fallait fournir les compléments...

Pour ton erreur, je ne peux voir ce qu'il en était si tu ne donnes pas le numéro d'erreur... Cela aurait pu écrire ailleurs que sur la bonne ligne sans provoquer d'erreur fatale (qui provoque un arrêt de l'exécution).

Je pense avoir a peu près compris ce que tu as fait, en revanche il reste un point bloquant : l'ajout d'un nouveau salarié se fait sur la première ligne non vide, or du coup il se positionne un peu n'importe ou.

Existe t-il un moyen de lui demander de placer un nouveau salarié en dernière ligne du tableau? Ou plus directement par ordre alphabétique, mais ça je n'y crois pas trop (ça serait le must, la cerise sur le gâteau )

J'espère que l'ajout ne se fait pas sur une ligne non vide !

Ce qui est prévu : ajout en fin de tableau, sur un ligne vide donc, tableau retrié, ComboBox réinitialisée pour qu'on retrouve le nouveau salarié dans la liste à son rang alphabétique.

Cela ne se passe pas ainsi ?

Bonjour!

Je ne devais plus avoir les yeux en face des trous hier...car ce matin ça fonctionne

Merci encore pour ton aide précieuse! Je passe le post en résolu.

Bonne journée.

Sandrine

Bonjour,

Bonne continuation... Tu peux te pencher sur ce code, qui reste somme toute réduit à l'essentiel et permet d'en mémoriser le mécanisme...

Les points clés :

- Si tableau Excel il est nommé, on utilise le nom, si pas tableau Excel on nomme la première colonne de la base (en dynamique, nom s'adaptant aux variations de taille), et on se retrouve dans les même conditions avec un nom à utiliser.

La référence à un nom de plage permet de se libérer de référence à la feuille (un souci en moins...), adressage plus rapide et plus facile à déterminer (nb- et le fait que la plage nommée ne couvre qu'une colonne au lieu de toutes ne limite pas mais au contraire offre plus de souplesse, .Offset et .Resize permettent toutes les possibilités de dimensionnement).

- Affectation quand on le peut (évaluation des difficultés qui pourraient compliquer cette méthode (notamment les problèmes de dates ou autres problèmes de conversion) au moyen d'un tableau auquel on affecte les données et qu'on affecte ensuite globalement à la ligne, en principe la méthode la plus rapide.

- Pour les dates, retenir qu'il faut toujours les convertir lors de l'affectation à une cellule, mais dans ton cas en passant par l'affectation à un tableau une première conversion n'empêchait pas VBA de reconvertir ensuite sans qu'on puisse l'empêcher... Dans un tel cas, une solution est à la fois de convertir en Date et convertir la date en nombre (Long), lequel ne peut plus être reconverti sauvagement, mais dans ce cas Excel n'assure plus le format de cellule date de façon automatique, il faut aller l'établir.

Bien que sur ce dernier point, j'aurais dû penser qu'un Tableau Excel en s'étendant étend les formats de cellule, et que l'on n'aurait peut-être pas eu à rétablir les formats, et dans ce cas l'utilisation d'un tableau aurait été gagnante... A voir à l'occasion.

A un prochaine, et bonne journée.

Merci pour tes conseils, que j'archive précieusement pour les réutiliser si besoin

Bonne journée!

Sandrine

Rechercher des sujets similaires à "code vba formulaire incorrect"