Interroger resultat procédure dans UserForm

Résolu/Fermé
Atik - 7 oct. 2014 à 12:45
 Atik - 8 oct. 2014 à 10:03
Bonjour à tous,

Je travaille sur un petit programme en VBA sur Excel 2010 (je débute). Mon problème est le suivant :
J'ai une UserForm qui contient plusieurs champs de saisie. Je souhaite que le contenu des saisies aillent respectivement sur la ligne (NbLignes+1) des colonnes A, B, C, ... D'où le code :
Private Sub Patient_Change()
Sheets("2014").Select
Cells(NbLignes + 1, 2) = Patient.Text
End Sub
Je détermine la valeur de NbLignes dans une procédure :
Public Sub NombreLignes()
Sheets("2014").Select
NbLignes = WorksheetFunction.CountA(Range("A:A"))
End Sub
Et je souhaite que mon programme détermine la valeur NbLignes une bonne fois pour toute. J'ai donc placé cette procédure en dehors de mon code de UserForm. Mais il est alors impossible de faire appel à la variable NbLignes... Je cherche donc une solution de régler/contourner ce problème.

Merci pour vos réponses,

Guillaume

3 réponses

pijaku Messages postés 12263 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 4 janvier 2024 2 744
7 oct. 2014 à 13:36
Bonjour,

Plusieurs choix.
Soit tu as mis ta procédure NombreLignes dans un module standard.
=> déclare ta variable Public NbLignes en entête de ce module (et supprime sa déclaration de le module de l'Userform) :
Code du module :
Public NbLignes As Long

Public Sub NombreLignes()
Sheets("2014").Select
NbLignes = WorksheetFunction.CountA(Range("A:A"))
End Sub
Code de l'UserForm :
Private Sub Patient_Change()
Sheets("2014").Select
Cells(NbLignes + 1, 2) = Patient.Text
End Sub


Soit tu laisses ta procédure NombreLignes dans le module de l'UserForm :
Code de l'Userform
Dim NbLignes As Long

Public Sub NombreLignes()
Sheets("2014").Select
NbLignes = WorksheetFunction.CountA(Range("A:A"))
End Sub

Private Sub Patient_Change()
Sheets("2014").Select
Cells(NbLignes + 1, 2) = Patient.Text
End Sub


Remarque complémentaire
L'événement de TextBox Change() intervient à chaque fois qu'un caractère est saisi ou retiré dans le TextBox. Ce qui fait que si tu veux écrire "Bonjour" dans une cellule via ton TextBox, il convient d'utiliser l'événement Exit (par exemple).
Ici, ton code va donner ceci :
"B"
"BO"
"BON"
"BO" => rectif erreur de saisie par l'utilisateur
"B" => rectif erreur de saisie par l'utilisateur
"Bo"
"Bon"
"Bonj"
"Bonjo"
"Bonjou"
"Bonjour"
Au lieu de "Bonjour"...

Essaye donc ceci :
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Sheets("2014").Select
Cells(NbLignes + 1, 2) = Patient.Text
End Sub


0
Merci pour ta réponse très complète !

J'avais effectivement fait ce que tu m'as décrit précédemment, mais cela ne fonctionnait pas et c'est toujours le cas (écriture sur la ligne 1 à chaque fois).
En revanche, j'avais remarqué qu'en appelant au premier champ de saisie la procédure NombreLignes il sautait bien les lignes comme je le souhaitais.
Sub Patient_Change ()
NombreLignes
' instructions...
End Sub
Le seul souci était exactement celui décrit dans ta remarque à savoir qu'à chaque modification du mot, il sautait une ligne. Mais le problème est corrigé grâce à ta proposition à la fin de la remarque !

Merci encore !
0
pijaku Messages postés 12263 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 4 janvier 2024 2 744
8 oct. 2014 à 07:32
Bonjour,

Plutôt que d'utiliser une fonction, qui plus est une fonction qui va te faire changer de feuille active sans retour, utilise ce genre de code pour déterminer la première ligne vide d'une colonne :
Private Sub TextBox1_Exit(ByVal Cancel As MSForms.ReturnBoolean)
Dim NbLignes As Long 'inutile de la déclarer en Public
With Sheets("2014")
    NbLignes = .Range("A" & Rows.Count).End(xlUp).Row
    .Cells(NbLignes + 1, 2) = Patient.Text
End Sub
0
Et si ça ne te dérange pas, j'ai une autre question :

J'ai un grand tableau sur une feuille vers lequel est redirigée une liste déroulante de mon UserForm pour y piocher les noms (colonne A).
Je souhaiterais que, si par exemple l'utilisateur sélectionne ce qui correspond à la cellule A20 dans la liste déroulante, une variable Rp prenne la valeur située dans la case B20 etc...
Évidemment je peux toujours faire un While et comparer le texte choisi par l'utilisateur à tous ceux de la colonne A jusqu'à ce que je tombe sur le bon (ligne i) et ensuite faire un Rp = Range(i,2). Mais peut être existe-t-il un moyen plus simple ?

Merci d'avance
0
pijaku Messages postés 12263 Date d'inscription jeudi 15 mai 2008 Statut Modérateur Dernière intervention 4 janvier 2024 2 744
Modifié par pijaku le 8/10/2014 à 10:55
Bon. Puisque les noms qui composent ta listbox (ou combobox c'est pareil) sont tous issus de ta colonne A, tu es sur de les y retrouver.
Donc, le plus simple est d'utiliser la méthode Find.
Comme ceci :

Dim maLigne As Long
With Sheets("2014")
    maLigne = .Columns(1).Cells.Find(ComboBo1.Value, LookIn:=XlValues, LookAt:=XlWhole).Row
    Rp = .Range("B" & maLigne).Value
End With


Tu trouveras un complément d'informations sur la méthode find ICI.

Remarque :
Tu as pu remarquer l'utilisation de blocs With/End With dans les deux codes que je t'ai donné aujourd'hui. C'est, à mon avis, une bonne habitude à prendre, lorsque tu travailles depuis un UserForm, pour référencer une feuille. Pourquoi? Parce que, en utilisant des blocs With, tu peux accéder à tes feuilles :
1- sans Select
2- même si elles sont masquées.
Tu noteras aussi la présence des points devant les objets faisant partie de la feuille référencée dans le With. Ils servent à dire que ces objets font partie de la feuille. En clair,
maVar = Sheets("Feuil1").Range("A1").Address

devient :
With Sheets("Feuil1")
    maVar = .Range("A1").Address
End With


Autre exemple :
Sheets("Feuil1").Select 'inutile, mais juste pour te dire que la feuille active est Feuil1
With Sheets("Feuil3")
    Valeur = .Range("B2").Value 'fait référence à la cellule Feuil3!B2 => un point devant Range
    Valeur2 = Range("H1").Value 'fait référence à la cellule Feuil1!H1 => pas de point
End With
0
Merci beaucoup !
Et c'est vrai que With c'est mieux pour pas mal d'applications !
0