Modif enregistrements depuis listbox avec Rowsource
Bonsoir à tous !
Dans un userform, j'ai une listbox alimentée par Rowsource qui pointe sur une feuille de recherche et des optionbuttons pour effectuer un tri.
J'ai besoin de modifier les postes (0,J,M,S,N) des personnes sélectionnées dans la listbox.
Mais je tourne en rond... j'y arrive si la listbox est alimentée avec .DataBodyRange mais je ne sais pas filtrer le résultat.
Quelqu'un pourrait-il me suggérer un début de réponse ?
Merci d'avance et bonne soirée !
Bonsoir, Salut Ric !
Tu as choisi un système un peu compliqué pour alimenter ta Listbox et la filtrer...
Dans ton cas, ça te fait user une feuille supplémentaire pour le filtrage de ta source réelle, mais permet à ton système de fonctionner plutôt bien. J'en suis même un peu surpris...
Maintenant une ListBox ne permet que de sélectionner un élément sans le modifier et si tu veux introduire une modification c'est dans ton tableau Excel qu'il faut le faire, la répercussion de la modif se fera par ton filtrage...
Reste à savoir si tu n'as à modifier que le seul champ Poste de ta sélection, ce qu'indiquerait le libellé de ton bouton, où si tu pourrais apporter d'autres modifications. Si seul le champ Poste est concerné, tu peux t'afficher une InputBox pour simplement le saisir, récupérer l'ID qui paraît correspondre à ta ligne, et affecter directement dans ton tableau de base la modification. Ce qui donnerait quelque chose comme :
Private Sub CommandButton3_Click()
Dim P$, ln%
With ListBoxpointage
If .ListIndex = -1 Then Exit Sub
ln = .List(.ListIndex, 0)
End With
Do
P = InputBox("Nouveau Poste")
If P = "" Then Exit Sub
If P Like "[0MSNJ]" Then Exit Do
Loop
[Tableau1].Cells(ln, 4) = P
Sheets("qrypersonnel").Range("A2:F2") = ""
rechperso
End SubA affiner par exemple si tu veux tester que l'on ne remet pas l'ancien poste...
Cette procédure s'assure qu'une sélection est faite dans la ListBox (sinon Exit...) et récupère l'ID (colonne 0 de la ListBox sur la ligne sélectionnée (ListIndex), ceci si l'ID correspond bien à la ligne dans le Tableau (ligne comptée à partir de la 1re ligne de données, pas dans la feuille).
Ensuite, saisie du nouveau poste (qui boucle dans le cas où la saisie est non conforme, on pourrait rajouter un message pour l'indiquer) : si saisie = "" (annulation, donc Exit...), si saisie conforme on sort de la boucle.
Il n'y a plus qu'à affecter : pour cela pas besoin de chercher la feuille, le tableau Excel est nommé par Excel dans le gestionnaire de noms, et ce nom (qui correspond au DataBodyRange) est utilisable en VBA à l'instar d'un nom de plage, donc on affecte directement la cellule correspondant à la ligne dans la 4e colonne qui est le Poste...
A la suite, tu relances ton filtrage, et ta modif va se répercuter dans la ListBox !
L'ayant testé avant de le proposer, je peux te confirmer que cela fonctionne.
Cordialement.
Un petit complément tant que j'y suis !
Si tu as d'autres modifications à faire, ce qui n'apparaissait pas mais demeure dans les possibilités, il est évident que des TextBox seront sans doute plus indiqués pour saisir, puis récupérer et affecter les nouvelles valeurs...
Mais note que tu peux avoir la possibilté de récupérer une ligne entière de ta ListBox sous forme de tableau, ainsi :
Dim Lgn
With ListBoxpointage
Lgn = WorksheetFunction.Index(.List, .ListIndex + 1, 0)
End WithLgn est une variable de type Variant dans laquelle tu vas recueillir la ligne sélectionnée. La propriété List de la ListBox renvoie un tableau à 2 dimensions (dans ton cas autant de lignes que tu en as mis et 6 colonnes). On utilise la fonction Excel INDEX pour en récupérer une ligne.
La syntaxe habituelle de la fonction est : INDEX(Tableau, Ligne, Colonne) mais quand tu remplaces l'un des éléments Ligne ou Colonne par 0, INDEX renvoie une matrice (tableau) qui sera toute la colonne ou toute la ligne.
On applique la fonction au tableau List de la ListBox, sur la ligne sélectionnée (NB-il faut ajouter 1 au ListIndex car contrairement à la ListBox, INDEX considère la numérotation des lignes et colonnes à partir de 1), et en indiquant 0 pour l'index colonne, on récupère toute la ligne dans la variable Lgn.
La ligne affectée à Lgn sera un tableau unidimensionnel de base 1, donc dans ton cas un tableau d'indices 1 à 6 (ces numéros correspondant aux numéros de colonnes de ton tableau source).
Tu peux y apporter des modifications, par exemple : Lgn(4) = 0 modifiera le Poste...
Et tu peux affecter une ligne entière de ton tableau source directement (au lieu de le faire cellule par cellule) :
[Tableau1].Rows(lni).Value = Lgnlni étant la ligne d'insertion.
Nb- Pour ajouter une ligne à un tableau Excel, il faut d'abord veiller qu'en permanence le tableau ne comporte pas de ligne vide en fin. Et on fait :
With [Tableau1]
.Rows(.Rows.Count + 1).Value = Lgn
End WithLa nouvelle ligne est alors affectée immédiatement sous le tableau, et sera automatiquement incorporée au tableau par Excel.
Cordialement.
Bonjour à tous,
@MFerrand ... Oliv34 a utilisé "RowSource" pour alimenter la listbox. Si on utilise AddItem, comment fait-on pour avoir les entêtes ? J'ai cherché, sûrement mal cherché, un peu sur le Net et je n'ai trouvé que des exemples où l'on utilisait des Intitulés au dessus de la section de la listbox.
Merci à l'avance.
ric
Merci à vous pour ces propositions,
@Ric : ta solution ne fonctionne que lorsqu'aucun filtre n'est actif, les numéros de ligne étant du coup différents.
Et on ne peut modifier qu' une fiche à la fois. (environ 100 salariés : D)
Mais ça me servira ailleurs donc merci 😊
@MFerrand : wow quel cours !
Il va falloir que je regarde et comprenne tout ça calmement cet après-midi, grand merci pour le temps passé à expliquer, fortement apprécié !!
Bonne journée à vous !
Bonjour,
@Ric: ne cherche pas plus ! Les en-têtes fonctionnent avec RowSource. Avec les autres méthodes d'alimentation on met des étiquettes...
@Oliv34: merci à toi aussi !
En contrepartie j'ai essayé de te montrer que tu as à gagner avec une meilleure utilisation des tableaux Excel, qui te faciliteront la plupart des opérations par adressages relatifs par rapport au tableau... et aussi en utilisant des tableaux VBA...
Cordialement.
@MFerrand
J'ai juste adapté un système qui fonctionne déjà me permettant d'afficher des heures de pointage en filtrant par poste/service/etc.
Tu dis que je n'ai pas utilisé la solution la plus simple, mais justement, quelle serait la solution la plus adaptée d'après toi, permettant de modifier par lot le poste de X salariés en même temps après les avoir sélectionnés (change toutes les semaines) ?
J'ai un peu regardé du côté de Additem mais je peine à relier les enregistrements de la listbox au tableau :s
Je décortique ta proposition plus tard dans la journée, un peu surbooké là
Merci !
PS: C'est con, mais ça fait plaisir de voir que certains savent encore écrire
PS: C'est con, mais ça fait plaisir de voir que certains savent encore écrire
Là tu es sur un système où tu modifies à l'unité... Une modification par lot impliquerait de définir des régles applicables au lot (je ne sais pas ce qui est possible... si tu as par exemple des changements automatiques de postes par rotation en fonction du poste précédent...)
Cordialement.
@MFerrand: Ton bout de code fonctionne bien même quand j'applique un filtre, ça me plait bien
Il devrait être possible de faire une boucle pour traiter une multi-sélection, non ?
Il n'y a pas vraiment de rotation dans les postes, c'est très changeant, et il n'est pas important que le poste soit le même que le précédent.
Je tente de décrypter la suite de ta proposition (Indexage), les connexions commencent lentement à se mettre en place dans mon cerveau....
I'll be back
Bonne après-midi
Si tu passes en multisélection, tes sélections ne sont plus détectées par ListIndex, mais dans une boucle en effet en utilisant Selected... c'est la valeur de la variable de boucle qui remplace alors ListIndex lors du traitement de chaque ligne sélectionnée... Mais bien sûr tu peux alors les traiter en boucle (d'autant que tu ne peux le faire autrement !)
Cordialement.