Liste déroulante en cascade
Bonjour,
Merci à tous.
Petite question :
- Je me dis que si un EPI n'est plus d'actualité car changement de gamme ou fournisseur. Comment je peux le garder dans la liste EPI mais qu'il n'apparaisse plus dans les Mouvement possible d'Entrée ou de Sortie ?
Bonsoir à toutes et à tous.
Doubs25, de mon point de vu, ou vous le supprimez de la liste et donc du stock, ou vous le laissez.
Cordialement.
Bonjour Claude,
Oui je vais vers comme vous le dite.
J'ai voulu réorganiser les tableaux dans l'onglet Paramètre pour tout mettre en colonne car sa allait se chevaucher quand je voulais ajouter des choses dans les différents tableaux.
Et du coup, Dans Accueil quand je clic sur Alimenter EPI, j'ai un message d'erreur :
Bonjour à tous,
@Doubs25, Quand VBA plante et surligne un ligne de code en jaune, et plus précisément comme ici sur la lancement du formulaire, vous devez continuer l'exécution du dit formulaire à l'aide de la touche F8, vous ferez du pas à pas jusqu’à la ligne qui effectivement, crée un problème. Un fois cette ligne trouvée refaite un message pour que l'on puisse vous aider.
Bonjour à toutes et à tous.
Doubs25, en quoi consiste votre réorganisation de l'onglet "Parametres" ?
Cordialement.
Bonjour à toutes et à tous,
Doubs25 apparemment tu rencontres un problème à l'ouverture du formulaire sur le chargement de la Listview. Tu es sûr de ne pas avoir modifié autre chose ?
parce que, normalement, le fait de bouger le tableau "Fournisseurs" (ou tout autre tableau de la feuille "Parametres" ) ne devrait avoir aucune conséquence sur l'ouverture du formulaire. Les codes font appel au "Nom" du tableau ("Tbl_Fournisseurs"). En principe, les codes vont chercher le tableau désigné dans la feuille "Parametres" et chargent les données.
J'ai fait le test chez-moi, et il n'y a aucun problème. Refais le test "F8" (Pas à pas) et continue jusqu'à la ligne où il beug dans "Sub Céer_LsvRecherch().
Cordialement
Bonjour à tous,
@Doubs25, Dans un premier temps prenez l'habitude de compiler le projet, pour voir les erreurs détectées par le compilateur.
Vous devez aussi continuer à appuyer sur F8 jusqu’à l'erreur, (A mon avis sur l'image vous êtes sur l'appel de la procédure, qui n'a pas d'argument, donc l'erreur n'est pas sur cette ligne)
Quand vous faites des changements prenez aussi l'habitude de renommer votre classeur :
- v1.XX (XX étant le numéro version mineure;
- vX.10 (X étant le numéro de version majeure.
En cas de problème vous pouvez revenir à la version précédente.
Je vois aussi que vous continuez à ne pas utiliser les fonctionnalités des Tableaux Structurés. Sur la ligne : C = Sheets("Liste EPI").....
- Dans l'appel vous faites référence à la colonne "A" si le tableau change de place c'est le plantage assuré.
- Faites plutôt référence au DataBodyRange du tableau cela sera plus efficace. et inhérent à sa position.
Même remarque concernant la collection Sheets (Qui comprends les Worksheets, Chart, et Macros héritées) si vous en avez pas absolument besoin préférez lui la collection Worksheets.
Enfin, prenez l'habitude aussi de fournir vôtre fichier de travail, c'est plus facile pour nous (comparé à une image.
Bonjour à tous,
J'ai repris l'ancienne version V5 et refait les même modification dans l'onglet paramètre. J'ai exactement le même problème. Je ne suis pas caler du tout avec les macros et j'ai du mal à tout comprendre et faire ce que vous me dites.
Bonjour à tous,
@Doubs25,
On est toujours sur le même type d'erreurs et de mauvaise programmation. Dans votre code vous tenter d'assigner des variables ou objets en passant leurs référence en dur (Exemple ici : With WsP.ListObjects("Tbl_Fournisseur")). Le problème c'est que le tableau 'Tbl_Fournisseurs' est inexistant, du coup VBA vous met un coup de pied. pour assigner un Objet vous devez impérativement vérifier s'il n'est pas sur Nothing avant de l'utiliser.
Comment résoudre ce problème :
- Soit vous renommez le tableau "Tbl_Fournisseur" en "Tbl_Fournisseur37"
- Soit vous modifiez la ligne pour cet appel :
Voici un exemple que j'utilise il faut juste adapter le nom des procédure d'appel (exemple InitTabData vers InitTabFournisseurs) et les noms de tableaux).
Une fois fait vous pouvez y accéder facilement grâce à l'InteliSence.
Par la suite toujours vérifier que le tableau n'est pas sur Nothing :
Dim lstO As Excel.ListObject
Set lstO = Factory.InitTabFournisseurs ' // L'appel se fait ICI
If Not lstO Is Nothing Then
Dim lstR As Excel.ListRow
Set lstR = lstO.ListRows.Add
With lstR
.Range(lstO.ListColumns("Colonne1").Index).Value = "Nouvelle valeur"
'...
'...
End With
Else
MsgBox "Le tableau Fournisseurs est introuvable." & vbCrLf _
& "Vous l'avez peut-être supprimé ou renommé" & vbCrLf _
& "" & vbCrLf _
& "La procédure va être stoppée !", vbOKOnly Or vbExclamation, "Erruer système."
End IfJ'ai remarqué une autre boulette qui peut peut être poser des problèmes selon utilisation:
'************** Permet d'avoir le prochain Numéro *************
Set ws = Worksheets("Liste EPI")
ws.Select
Set plageA = ws.Columns(1)
N = ws.ListObjects("Tbl_EPI").ListRows.Count + 1
Me.Txt_Index = Format(N, "0")A votre avis que va t-il se passer pour 'N' si vous supprimez des lignes du tableaux ? J'espère que vous n'utiliserez pas cet index pour sélectionner des lignes car là ça va être la cata.
Doubs25, c'est normal que tu aies un beug : tu as renommé le Tableau Fournisseur : initialement dans le fichier fourni, le tableau s'appelait "Tbl_Fournisseur". Vous l'avez renommé : "Tbl_Fournisseur37" : donc, il ne le trouve pas.
Ne change pas les noms des tableaux. Si tu le fais, il faut aller chercher dans tous les codes là où le nom du tableau apparaît et mettre le nouveau nom : cela risque d'être un problème pour toi.
Concernant le "N° Index", c'est une base de donnée : dans l'absolue, on ne supprime pas de ligne dans le tableau. Si on le fait, il faut rependre manuellement la numérotation. Si Jean-Paul a une autre solution, je suis preneur.
Cordialement.
Bonjour à tous,
c'est une base de donnée : dans l'absolue, on ne supprime pas de ligne dans le tableau.
Dans une base de donnée c'est le principal, de pouvoir gérer les enregistrements non ?
Claude, il peut y avoir une autre solution c'est de calculer le max de la colonne index et de l'incrémenter de 1.
De cette façon si une ligne est supprimée, à l'instar de Access l'index disparait cela fait des trous dans la continuité mais ce n'est pas grave. Et cela vous garantie que vos index sont uniques.
Voici deux fonctions complémentaires qui font le Job :
'@Description "Retrieves the maximum value of the indexes incremented by 1 optionally."
Public Function GetMaxID(ByVal Table As Excel.ListObject, _
Optional ByVal Column As Variant, _
Optional ByVal WithIncrement As Boolean _
) As Long
If Not Table Is Nothing Then
If Table.ListRows.Count > 0 Then
Dim Index As Long
Index = IndexColumn(Table, Column)
If Index > 0 Then
Dim IdMax As Long
IdMax = Application.WorksheetFunction.Max(Table.ListColumns(Index).DataBodyRange)
GetMaxID = IdMax + IIf(WithIncrement = True, 1, 0)
Else
GetMaxID = 0
End If
Else
GetMaxID = 1
End If
Else
GetMaxID = 0
End If
End Function
'@Description "Check the index of a column. If not found, return 1."
Public Function IndexColumn(ByVal Table As Excel.ListObject, _
ByVal Column As Variant, _
Optional ByVal setDefaultColumnToFirst As Boolean = True _
) As Long
If Not Table Is Nothing Then
With Table
Dim Index As Long
If setDefaultColumnToFirst Then
Index = 1
Else
Index = 0
End If
If Column = vbNullString Or Column = 0 Then
IndexColumn = Index: Exit Function
Else
If TypeName(Column) = "String" Then
Dim counter As Long
counter = 1
Do While counter <= .ListColumns.Count And Not Index
If StrComp(Table.ListColumns(counter).Name, Column, vbTextCompare) = 0 Then Index = counter
counter = counter + 1
Loop
ElseIf TypeName(Column) = "Long" Or TypeName(Column) = "Integer" Then
If Column > 0 And Column <= .ListColumns.Count Then
Index = Column
End If
End If
End If
End With
IndexColumn = Index
Else
IndexColumn = False
End If
End FunctionPour l'appel si comme moi vous utiliser un endroit centralisé pour initialiser vos tableaux cela donne ceci :
Private Sub NewContact_Click()
Dim newIndex As Long
newIndex = TabsManagement.GetMaxID(Table:=Factory.InitTabClients, _
Column:=Factory.CLIENTS_INDEX_COL_NAME, _
WithIncrement:=True _
)
Index.Value = Format(newIndex, "0000")
'...
'...
'...
End SubPetit exemple ci-dessous
Bonne Programmation, Jean-Paul.
Bonjour à toutes et à tous.
Jean-Paul, je te remercie pour ton intervention. Les codes que tu fournis sont compliqués pour un amateur comme moi. J'aurais du mal à intervenir dessus ci problème. Mais j'ai retenu l'idée et je propose le code ci-joint. A l'ouverture il calcule le nombre d'index et rajoute 1. J'ai mis le même code dans la sub "Supprimer", ce qui fait qu"en cas de suppression, il recalcule les index et rajoute 1. De cette manière je n'ai pas de trous dans mes index.
'************** Recalcule les index du tableau et donne le prochain numéro *************
Set ws = Worksheets("Liste EPI")
Set tbl = ws.ListObjects("Tbl_EPI")
'--- Renumérotation de la colonne Index ---
With tbl
For i = 1 To .ListRows.Count
' Colonne 1 = colonne Index, adapte si nécessaire
.DataBodyRange(i, 1).Value = i
Next i
End With
'--- Prochain index ---
Me.Txt_Index = tbl.ListRows.Count + 1Ci-joint le fichier modifié.
bonjour le fil,
je suis assez tard pour intervenir, mais un TS est un outil assez puissant qu'on peut utiliser d'une manière plus pratique indépendant de sa feuille. Donc c'est par exemple important de savoir une position dans le TS sans s'inquièter sa position dans la feuille. Sauf dans le module d'une feuille, il ne faut pas dire le nom de sa feuille pour ce TS.
Par exemple la macro
Private Sub SupprimerDansTableau(NomTableau As String, Valeur As String)
Dim R As Range
With Range(NomTableau).ListObject 'nom du tableau, le nom de sa feuille n'est pas import
Set R = .DataBodyRange.Find(What:=Valeur, LookIn:=xlValues, LookAt:=xlWhole)
If Not R Is Nothing Then .ListRow(R.Row - .HeaderRowRange.Row).Range.Delete 'on supprime le "listrow" et ne pas la ligne entière
End If
End SubAvec le nom du TS, sans la feuille, on sait déjà tout. Puis on cherche dans le "Databodyrange" pour votre valeur et si on trouve la cellule, on calcule l'index du "listrow" = la ligne de la cellule moins la ligne de l'entête du TS. Et on supprime le "range" de ce listrow, inutile de supprimer la ligne entière.
Mais je suppose que vous ne voulez pas chercher dans le TS entier, mais uniquement dans la colonne "Réf", bon, une adaptation minimale. Mais pour commencer, VBA est d'origine en anglais et a de temps en temps des problèmes avec les accents. Donc c'est mieux d'utiliser des noms sans accents, donc "Ref", "Categorie", "Designation" etc. En changeant cette ligne, on ne cherche que dans la colonne "Ref". Je vois que cette colonne n'est pas toujours dans la même position dans vos TS, mais cela n'a pas d'importance.
Set R = .listcolumns("Ref").DataBodyRange.Find(What:=Valeur, LookIn:=xlValues, LookAt:=xlWhole)L'idée est donc d'utiliser le TS comme un objet indépendant qui doit se trouver dans une feuille mais on oublie le max possible cette relation obligatoire.
la macro dans le poste précédent deviendra comme ceci mais l'utilité pratique de cet index me semble doutable ...
With Range("Tbl_EPI").ListObject.ListColumns("Index").DataBodyRange 'directement le contenu de cette colonne sans l'entête
.FormulaR1C1 = "=row()-" & .Row - 1 'remplacer le contenu de cette colonne par une formule
.Value = .Value 'remplacer la formule par sa valeur
MsgBox .Rows.Count + 1 'Prochain index, attention c'est rows ici et ne pas listrows
Me.Txt_Index = .Rows.Count + 1 '--- Prochain index ---
End Withla macro "quitter" deviendra tout simple (naturellement, on ne peut pas modifier le nom du TS, mais on peut le déplacer vers une autre feuille sans changer la macro
Private Sub CDB_Quitter_Click()
Range("Tbl_EPI").Interior.ColorIndex = xlNone 'ceci fonctionne, même si le TS est vide
Unload Me
Application.Goto Sheets("Accueil").Range("A1"), 1
End SubBsAlv bonjour, tu ne te serais pas "planté de fil" par hasard ?
j'ai pris votre dernier fichier "1-superviseur-V7.xlsm" et le module "Liste-EPI" mais je ne l'ai pas testé, un moment ...
EDIT : désolé, quand on prend l'index pour supprimer dans les autres TS, cela me semble douteux/fragile, un clef unique serait peut-être la combinaision des 5 colonnes Catégorie, sous-catégorie, Ref, Designation et taille" et puis utiliser ce clef dans les autres TS. Que pensez-vous ?
Bonjour à tous,
je te remercie pour ton intervention. Les codes que tu fournis sont compliqués pour un amateur comme moi. J'aurais du mal à intervenir dessus ci problème.
Claude, quand vous utilisez la fonction RechercheV ou X, Ou bien Min, Max ou autre; Regardez-vous leur fonctionnement ? NON, vous ni avez pas accès. Là c'est pareil, vous coller les procédures dans un module et quand vous en avez besoin vous les utilisez. Si l'on regarde la fonction de plus prêt il ne lui faut juste que trois argument :
- Le tableau concerné.
- Le nom de la colonne
- Et si l'on dois l'incrémenté l'index (Cela peut être utile)
Il est vrai que j'initialise le tableau dans un seul module, en réalité c'est plus simple, vous n'avez pas à vous soucier de son nom, par exemple si le tableau et relatifs au stock général je vais appeler le tableau comme ceci : Factory.InitTabGeneralStock. Pourquoi j'implémente le chemin complet tout simplement pour bénéficier de l'intelisence.
Vous n'avez plus à vous soucier de son nom, et si vous devez pour X raison le changer vous ne le faites qu'a un seul endroit.
Je vous rappelle votre citation :
Ne change pas les noms des tableaux. Si tu le fais, il faut aller chercher dans tous les codes là où le nom du tableau apparaît et mettre le nouveau nom : cela risque d'être un problème pour toi.
Ce n'est plus un problème si vous utiliser cette fonction.
Étant donner que la fonction renvoie un ListObjet vous pouvez en utiliser la puissance. Exemple :
Voilà je fais de même pour les noms de colonnes je les colles dans le module et je n'ai plus à me soucier de leurs noms exact. (Voir la première image.)
@BsAlv,
peut-être la combinaision des 5 colonnes Catégorie, sous-catégorie, Ref, Designation et taille" et puis utiliser ce clef dans les autres TS
Encore un manière de se compliquer la vie...
En utilisant La fonction indexMax et des variables de type long, cela devient beaucoup plus simple.
Imaginons une liste déroulante sur un formulaire, avec les colonne 'Id', 'Nom', 'Prénom' etc... vous donner à la propriété BoundColum la valeur 1 celle de l'id et la propriété TextColumn à 2 (Pour afficher le nom)
Vous charger votre liste déroulante, vos sélectionnez un item de cette liste et vous voulez supprimer la ligne correspondante vous pouvez le faire en une ligne. Il vous faudra juste une autre petite fonction qui recherche l'index de la ligne par rapport à son numéro d'Id.
'@Description "Returns the row index based on the ID value."
Public Function GetRowIndex(ByVal Table As Excel.ListObject, _
ByVal ColumnName As String, _
ByVal idValue As Variant _
) As Long
If TypeName(idValue) = "String" Then idValue = """" & idValue & """" Else idValue = idValue * 1
Dim Formula As String
Formula = "iferror(match({value},{table}[{column}],0),0)"
Formula = Replace(Formula, "{value}", idValue)
Formula = Replace(Formula, "{table}", Table.Name)
Formula = Replace(Formula, "{column}", ColumnName)
Dim Index As Long
Index = Evaluate(Formula)
If Index > 0 Then GetRowIndex = Index
End FunctionEt voilà une suppression sur une seule ligne :
Il est bien sûr qu'avec cette version nous ne testons pas les erreurs éventuelles.
Voilà, si je dois donner des conseils ce serait de ne pas réinventer la roue à chaque fois, donc d'utiliser le maximum de fonctions que l'on garde au chaud dans des modules, pour qu'elles puissent être réutilisées.
Voici un exemple de modules qui sont à ma disposition pour diverses taches :
Je les utilise au grès de mes besoins...
re,
Voilà, si je dois donner des conseils ce serait de ne pas réinventer la roue à chaque fois,
@Jean-Paul, cela semble ridicule mais je préfère réinventir la roue pourque le code soit plus lisible, ce que vous proposez me semble un peu "overkill", mais je sais, c'est une discussion comme celle du sexe des anges.
Mais, ce qui m'inquiète, c'est utiliser l'index dans le premier tableaj pour supprimer cet article dans les autres tableaux, cela me semble dangeureux.

