XL 2013 Ajout de textboxes sur plusieurs lignes d'un tableau selon la parité de la textbox

Tubule

XLDnaute Nouveau
Bonjour,

Je cherche à ajouter des textbox issues d'un formulaire dans un tableau. Ces textbox sont numérotées, et je souhaiterais ajouter celles qui sont impaires dans une ligne d'un tableau et celles qui sont paires dans une autre ligne.
J'ai tenté ce code, inspiré de ce forum, mais celui -ci ne fonctionne pas:

VB:
Dim CTRL As Control
    Dim LO As ListObject
    Dim i As Integer, p As Integer
    Dim ligne As Long
    
   ' ligne = Me.Nom_Dossier.ListIndex + 2
    
    Set LO = Sheets("Feuil1").ListObjects("LO_test")
                
    'La variable i va successivement prendre les valeurs 1, 3, 5
With LO.ListRows.Add(AlwaysInsert:=True) 'Ajout d'une ligne dans les charges
    For i = 1 To 7 Step 2 'Juste les impairs
            For Each CTRL In Me.Controls("TextBox" & i) 'Ajout dans les cases du tableau des dates, selon le numéro du tag
                If Len(CTRL.Tag) Then
                    .Range(1, CLng(CTRL.Tag)) = CTRL.Value
                End If
            Next
    Next i
End With
    
    'For p = 2 To 8 'juste les pairs
            
    Me.Hide
    Unload Me
    
End Sub
J'obtiens le message suivant :"membre de méthode ou donnée introuvable" et ".ListIndex" est surligné. Je ne comprends pas ce qui se passe. Auriez-vous une idée ?
Le fichier est joint
Merci
 

Fichiers joints

Dranreb

XLDnaute Barbatruc
Bonsoir.
Ce qui se passe c'est que Nom_Dossier est un Label, lequel n'a pas de propriété ListIndex.
C'est une propriété des ComboBox essentiellement.
 

Tubule

XLDnaute Nouveau
Bonjour Dranreb,

Merci beaucoup pour votre réponse. Ainsi, j'ai donc remplacé le nom du label par le nom dd'une ComboBox et ça fonctionne :

VB:
ligne = Me.ComboBox1.ListIndex + 2
Après quelques petites corrections, je n'ai plus de messages d'erreur. Néanmoins, lorsque je remplis le formulaire, rien ne s'écrit dans les TextBox ! Je pense qu'il y a quelque chose qui cloche dans ce paragraphe, mais je ne comprends pas bien pourquoi :


Code:
With LO.ListRows.Add(AlwaysInsert:=True) 'Ajout d'une ligne dans les charges
    For i = 1 To 7 Step 2 'Juste les impairs donc 'La variable i va successivement prendre les valeurs 1, 3, 5
            
            For Each CTRL In Me.Controls 'Ajout dans les cases du tableau des dates, selon le numéro du tag
                If TypeName(CTRL) = "TextBox" & i And Len(CTRL.Tag) Then
                    .Range(ligne, CLng(CTRL.Tag)) = CTRL.Value
                End If
            Next
    Next i
End With
Lorsque je sélectionne un nom de dossier dans la ComboBox, on voit bien les noms apparaître, si je tape un nouveau nom de dossier, la ligne dasn le tableau s'ajout bien, mais rien n'apparaît dans le contenu du tableau !
Ca ne doit sûrement pas être grand chose mais bon ..

Auriez-vous une petite idée ?
Vous trouverez en pièce jointe le fichier corrigé.
Merci
 

Fichiers joints

Dranreb

XLDnaute Barbatruc
Bonjour.
Remettez 1 au lieu de ligne
Remarque: je ne comprends pas trop With LO.ListRows.Add(AlwaysInsert:=True)
J'aurais mieux compris With LO.ListRows(ligne)
 
Dernière édition:

Tubule

XLDnaute Nouveau
En fait je crois que je ne comprends rien à ce que vous voulez faire.
Je souhaite que lorsque l'on clique sur le bouton Valider, le contenu des textboxes impaires soient dans une ligne du tableau et que le contenu des textboxes paires soient une ligne en-dessous.
Je suis désolée, je n'ai peut-être pas été très claire, je ne suis pas une pro du VBA ...!
 

Tubule

XLDnaute Nouveau
Bonjour.
Remettez 1 au lieu de ligne
Remarque: je ne comprends pas trop With LO.ListRows.Add(AlwaysInsert:=True)
J'aurais mieux compris With LO.ListRows(ligne)
Je souhiate ajouter une ligne au tableau donc je pense qu'il faut garder Add.
J'ai modifié pour mettre 1, et ça fait la même chose. J'avais déjà essayé avant .. Mais ne fait, c'est plus logique de mettre ligne je trouve , car on ne va pas toujours ajouter à la ligne 1 !
 

Dranreb

XLDnaute Barbatruc
Et à l'inverse les valeurs des TextBox paires et impaires ne pourraient-elles pas être mises dans la même cellule avec un vbLf entre les deux ?
Je pense qu'on ne peut rien fusionner dans un Tableau.
Sinon, il vaudrait mieux qu'elles soient dans des colonnes différentes du tableau que sur plusieurs lignes.
 

Tubule

XLDnaute Nouveau
Je viens d'essayer ça mais ça ne fonctionne toujours pas :
VB:
With LO.ListRows.Add(AlwaysInsert:=True) 'Ajout d'une ligne dans les charges
    For i = 1 To 7 Step 2 'Juste les impairs donc 'La variable i va successivement prendre les valeurs 1, 3, 5
            
            For Each CTRL In Me.Controls 'Ajout dans les cases du tableau des dates, selon le numéro du tag
                If TypeName(CTRL) = "TextBox" And Len(CTRL.Tag) Then
                    Me.Controls("TextBox" & i).Value = LO.Range(1, CLng(CTRL.Tag)) = CTRL.Value
                End If
            Next
    Next i
End With
 

Dranreb

XLDnaute Barbatruc
Enlevez LO, c'est sur la seule ligne 1 du ListRow, pas du ListObject
Mais tout ça n'est pas clair. Je ne comprends pas pourquoi votre tableau a des paires de lignes. C'est vraiment malcommode.
 

Tubule

XLDnaute Nouveau
Et à l'inverse les valeurs des TextBox paires et impaires ne pourraient-elles pas être mises dans la même cellule avec un vbLf entre les deux ?
Je pense qu'on ne peut rien fusionner dans un Tableau.
Sinon, il vaudrait mieux qu'elles soient dans des colonnes différentes du tableau que sur plusieurs lignes.
Impossible pour un VbLf car je vais tracer des graphiques ensuite.
Vous avez sûrement raison pour le tableau.
J'avais fait ça au début, mais pour mon graphique, ça m'arrangeait de mettre sur 2 lignes :(
 

Dranreb

XLDnaute Barbatruc
Les noms de dossiers pourraient aussi être dans un tableau à part avec une seule ligne par dossier.
Dans votre dernier classeur il y avait des noms de dossiers différents dans une même paire de lignes
 

Dranreb

XLDnaute Barbatruc
Vous pourriez alors essayer ça :
VB:
Option Explicit
Private LOtDos As ListObject, LOtVal As ListObject, LCou As Long, TVL()
Private Sub UserForm_Initialize()
   Set LOtDos = Feuil1.ListObjects("TabDos")
   Set LOtVal = Feuil1.ListObjects("TabVal")
   ComboBox1.List = LOtDos.DataBodyRange.Value
   End Sub
Private Sub ComboBox1_Change()
   Dim L As Long, C As Long
   If ComboBox1.MatchFound Then
      LCou = ComboBox1.ListIndex + 1
      TVL = LOtVal.ListRows(2 * LCou - 1).Range.Resize(2).Value
   Else
      LCou = 0
      ReDim TVL(1 To 1, 1 To 4)
      End If
   For L = 1 To 2: For C = 2 To 5
      Me("TextBox" & 2 * (C - 2) + L).Text = TVL(L, C)
      Next C, L
   End Sub
Private Sub Validation_Click() 'Bouton Valider
   Dim L As Long, C As Long, V, Rng As Range
   For L = 1 To 2: For C = 2 To 5
      V = Me("TextBox" & 2 * (C - 2) + L).Text
      If IsNumeric(V) Then TVL(L, C) = CDbl(V)
      Next C, L
   If LCou = 0 Then
      LOtDos.ListRows.Add(AlwaysInsert:=True).Range.Value = ComboBox1.Text
      ComboBox1.List = LOtDos.DataBodyRange.Value
      Set Rng = LOtVal.ListRows.Add(AlwaysInsert:=True).Range
      LOtVal.ListRows.Add AlwaysInsert:=True: Set Rng = Rng.Resize(2)
   Else
      Set Rng = LOtVal.ListRows(2 * LCou - 1).Resize(2)
      End If
   Rng.Value = TVL
   End Sub
 

Ananas94

XLDnaute Junior
Vous pourriez alors essayer ça :
VB:
Option Explicit
Private LOtDos As ListObject, LOtVal As ListObject, LCou As Long, TVL()
Private Sub UserForm_Initialize()
   Set LOtDos = Feuil1.ListObjects("TabDos")
   Set LOtVal = Feuil1.ListObjects("TabVal")
   ComboBox1.List = LOtDos.DataBodyRange.Value
   End Sub
Private Sub ComboBox1_Change()
   Dim L As Long, C As Long
   If ComboBox1.MatchFound Then
      LCou = ComboBox1.ListIndex + 1
      TVL = LOtVal.ListRows(2 * LCou - 1).Range.Resize(2).Value
   Else
      LCou = 0
      ReDim TVL(1 To 1, 1 To 4)
      End If
   For L = 1 To 2: For C = 2 To 5
      Me("TextBox" & 2 * (C - 2) + L).Text = TVL(L, C)
      Next C, L
   End Sub
Private Sub Validation_Click() 'Bouton Valider
   Dim L As Long, C As Long, V, Rng As Range
   For L = 1 To 2: For C = 2 To 5
      V = Me("TextBox" & 2 * (C - 2) + L).Text
      If IsNumeric(V) Then TVL(L, C) = CDbl(V)
      Next C, L
   If LCou = 0 Then
      LOtDos.ListRows.Add(AlwaysInsert:=True).Range.Value = ComboBox1.Text
      ComboBox1.List = LOtDos.DataBodyRange.Value
      Set Rng = LOtVal.ListRows.Add(AlwaysInsert:=True).Range
      LOtVal.ListRows.Add AlwaysInsert:=True: Set Rng = Rng.Resize(2)
   Else
      Set Rng = LOtVal.ListRows(2 * LCou - 1).Resize(2)
      End If
   Rng.Value = TVL
   End Sub
Merci beaucoup pour votre réponse Dranreb.

Ca a l'air super bien codé, par contre je ne comprends pas tout !
J'obtient le message d'erreur suivant : "L'indice n'appartient pas à la sélection", avec cette ligne surlignée :

VB:
 Me("TextBox" & 2 * (C - 2) + L).Text = TVL(L, C)
Je vous joins le fichier
Auriez-vous une idée ?
Je vous remercie
 

Fichiers joints

Dranreb

XLDnaute Barbatruc
Essayez comme ça :
VB:
Option Explicit
Private LOtDos As ListObject, LOtVal As ListObject, LCou As Long, TVL()
Private Sub UserForm_Initialize()
   Set LOtDos = Feuil1.ListObjects("TabDos")
   Set LOtVal = Feuil1.ListObjects("TabVal")
   ComboBox1.List = LOtDos.DataBodyRange.Value
   ReDim TVL(1 To 1, 1 To 4)
   End Sub
Private Sub ComboBox1_Change()
   Dim L As Long, C As Long
   If ComboBox1.MatchFound Then
      LCou = ComboBox1.ListIndex + 1
      TVL = LOtVal.ListRows(2 * LCou - 1).Range.Resize(2).Value
   Else
      LCou = 0
      ReDim TVL(1 To 2, 1 To 4)
      End If
   For L = 1 To 2: For C = 1 To 4
      Me("TextBox" & 2 * (C - 1) + L).Text = TVL(L, C)
      Next C, L
   End Sub
Private Sub Validation_Click() 'Bouton Valider
   Dim L As Long, C As Long, V, Rng As Range
   For L = 1 To 2: For C = 2 To 4
      V = Me("TextBox" & 2 * (C - 1) + L).Text
      If IsNumeric(V) Then TVL(L, C) = CDbl(V)
      Next C, L
   If LCou = 0 Then
      LOtDos.ListRows.Add(AlwaysInsert:=True).Range.Value = ComboBox1.Text
      ComboBox1.List = LOtDos.DataBodyRange.Value
      Set Rng = LOtVal.ListRows.Add(AlwaysInsert:=True).Range
      LOtVal.ListRows.Add AlwaysInsert:=True: Set Rng = Rng.Resize(2)
   Else
      Set Rng = LOtVal.ListRows(2 * LCou - 1).Range.Resize(2)
      End If
   Rng.Value = TVL
   End Sub
Private Sub Retour_Click() 'Pour le bouton Retour
    'Ajout_Dossier.Show 0 'On retourne au formulaire précédent
   Me.Hide
   Unload Me
   End Sub
 
Dernière édition:

Ananas94

XLDnaute Junior
Essayez comme ça :
VB:
Option Explicit
Private LOtDos As ListObject, LOtVal As ListObject, LCou As Long, TVL()
Private Sub UserForm_Initialize()
   Set LOtDos = Feuil1.ListObjects("TabDos")
   Set LOtVal = Feuil1.ListObjects("TabVal")
   ComboBox1.List = LOtDos.DataBodyRange.Value
   ReDim TVL(1 To 1, 1 To 4)
   End Sub
Private Sub ComboBox1_Change()
   Dim L As Long, C As Long
   If ComboBox1.MatchFound Then
      LCou = ComboBox1.ListIndex + 1
      TVL = LOtVal.ListRows(2 * LCou - 1).Range.Resize(2).Value
   Else
      LCou = 0
      ReDim TVL(1 To 2, 1 To 4)
      End If
   For L = 1 To 2: For C = 1 To 4
      Me("TextBox" & 2 * (C - 1) + L).Text = TVL(L, C)
      Next C, L
   End Sub
Private Sub Validation_Click() 'Bouton Valider
   Dim L As Long, C As Long, V, Rng As Range
   For L = 1 To 2: For C = 2 To 4
      V = Me("TextBox" & 2 * (C - 1) + L).Text
      If IsNumeric(V) Then TVL(L, C) = CDbl(V)
      Next C, L
   If LCou = 0 Then
      LOtDos.ListRows.Add(AlwaysInsert:=True).Range.Value = ComboBox1.Text
      ComboBox1.List = LOtDos.DataBodyRange.Value
      Set Rng = LOtVal.ListRows.Add(AlwaysInsert:=True).Range
      LOtVal.ListRows.Add AlwaysInsert:=True: Set Rng = Rng.Resize(2)
   Else
      Set Rng = LOtVal.ListRows(2 * LCou - 1).Range.Resize(2)
      End If
   Rng.Value = TVL
   End Sub
Private Sub Retour_Click() 'Pour le bouton Retour
    'Ajout_Dossier.Show 0 'On retourne au formulaire précédent
   Me.Hide
   Unload Me
   End Sub
Merci beaucoup ça fonctionne presque ! Sauf que le contenu des TextBoxes 1 et 2 ne s'affichent pas, ce n'est peut-être pas grand chose ..?
Par ailleurs, je viens d’étoffer mon fichier mais je ne parviens pas à adapter le code, car il est vraiment trop compliqué pour moi ..
En effet, je souhaite juste ajouter une liste d'interlocuteurs à côté des dossiers, et à chaque fois indiquer automatiquement dans le tableau 2 rôles différents : pour la première ligne insérée, ça serait "rôle1" (avec les textboxes impaires) et la seconde "role2" (avec les textboxes paires).
je vous joins une proposition que j'ai essayé d'adapter , sans succès. Pouvez-vous me dire ce que vous en pensez s'il vous plaît ?
En tout cas c'est super bien codé, merci et bravo
 

Fichiers joints

Dranreb

XLDnaute Barbatruc
Il y a trois colonnes maintenant dans le LOtDos ? Il faut préciser les ListColumn alors !
S'il peut y avoir plusieurs dossiers pour un même interlocuteur je vous conseille l'emploi d'un objet ComboBoxLiées du complément à installer depuis cette ressource.
Sinon il y a encore quelque chose qui ne va pas: il y a un nombre impaire de lignes dans le second tableau alors l'ajout de nouvelles lignes ne se fait pas là où il devrait. Peut être vaudrait-il mieux écrire la Validation_Click comme ça :
VB:
Private Sub Validation_Click() 'Bouton Valider
   Dim L As Long, C As Long, V, Rng As Range
   If LCou = 0 Then
      LOtDos.ListRows.Add(AlwaysInsert:=True).Range.Value = ComboBox1.Text
      ComboBox1.List = LOtDos.DataBodyRange.Value
      LCou = ComboBox1.ListIndex + 1
      While LOtVal.ListRows.Count < 2 * LCou: LOtVal.ListRows.Add AlwaysInsert:=True: Wend
      End If
   Set Rng = LOtVal.ListRows(2 * LCou - 1).Range.Resize(2)
   For L = 1 To 2: For C = 2 To 4
      V = Me("TextBox" & 2 * (C - 1) + L).Text
      If IsNumeric(V) Then TVL(L, C) = CDbl(V)
      Next C, L
   Rng.Value = TVL
   End Sub
Ne pourriez vous vraiment pas faire un seul tableau simple où vous mettez à jour une seule ligne ? Maintenant je sens déjà que vous voulez pouvoir identifier par quelque chose les lignes 1 et 2. Un objet ComboBoxLiées se débrouille pour trouver une ligne correspondant à des critères spécifiés dans plusieurs ComboBox pour différentes colonnes.
 
Dernière édition:

Ananas94

XLDnaute Junior
Bonjour Dranreb,

Merci beaucoup pour votre réponse :D. Je viens de copier votre code et de le modifier un peu, selon vos indications, à savoir :
1-Création d'un seul tableau
2-Nombre pair de lignes (j'ai indiqué dans le tableau le contenu que je voudrais précisément).

En soit, je pourrais ajouter et mettre à jour une seule ligne, mais j'ai sollicité ce forum pour ajouter deux lignes, car sinon, je saurais faire ! Voilà pourquoi j'insiste un peu :)
J'ai modifié votre code avec la fusion dans un seul tableau LOtDos. Par ailleurs, j'ai enlevé le tableau TVL, je n'ai pas compris à quoi il servait ; sûrement à lier les données puisque nous avions 2 tableaux ...?)

J'ai regardé les combobox liées ; si j'ai bien compris, cette application est utile lorsque l'on souhaite qu'une combobox soit mise à jour selon une autre combobox modifiée précédemment ; c'est astucieux ! Mais je ne pense pas que ceci soit utile dans mon cas (néanmoins, je serai curieuse de savoir faire !)

Lorsque je tente d'exécuter la macro, le message "L'indice n'appartient pas à la sélection" avec le module "Formulaire.Show 0" surligné en jaune qui apparaît : ainsi, on en peut pas vraiment savoir d'où vient la véritable erreur !
J'ai commenté le code (en pièce jointe) ; pourriez-vous y jeter un oeil s'il vous plaît ?
Merci beaucoup par avance
 

Fichiers joints

Créez un compte ou connectez vous pour répondre

Vous devez être membre afin de pouvoir répondre ici

Créer un compte

Créez un compte Excel Downloads. C'est simple!

Connexion

Vous avez déjà un compte? Connectez vous ici.

Haut Bas