Lister les onglets à partir d'un classeur sélectionné
Bonsoir Peerl Theze
bon alors il apparaît nettement, que tu ne sais pas lire c'est dommage pour toi mais après tout c'est ton problème, c'est tes fichiers.
Je t'ai demandé très clairement de me faire un tableau avec ce que tu souhaites de ton fichier 7890 dans le ficher Userform.xlsm
et là il y a maintenant deux feuilles résultat!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Mais par contre toujours qu'une seule ou deux lignes!!!!
Donc par fichier on ne doit extraire que deux lignes ?????
La réponse est non, bien sur, alors comme tu n'as pas fait manuellement le tableau pour la feuille complète de ton fichier 7890, je ne vais pas te le redemander à chaque fois, donc si d’aventure tu te mets à lire et comprendre ma demande, tu refais le tableau complet et tu renvoies le fichier Userform.xlsm, en attendant je ne réponds plus pas de temps à perdre.
a+
Papou
Salut Papou , Theze , le Forum
J'ai hésité de vous écrire , je n'ai pas envie de vous embêter ..
Bon j'ai essayer de relire la discussion depuis le départ , et je reconnais que c'est de ma faute d’être pas très précise depuis le départ car rien n'était clair même pour moi apparemment . Je suis novice en VBA , et j'ai commencé à imaginer tout et n'importe quoi et faire des propositions ce qui a causé ce mal entendu . ( je m'excuse Theze , Papou ..).
et si je réexplique juste le besoin ?
J'ai un dossier avec plusieurs fichiers --> le but c'est de pouvoir chercher dans une feuille qui a les mêmes tableaux dans chaque fichiers d'ou l'idée de lister les fichiers puis lister leurs onglets . l'idée de Theze était parfaite même pour chercher seulement les feuilles et y accéder directement.
Une fois l'onglet choisi , je dois pouvoir effectuer une recherche ( ce qui m’intéresse c'est les chiffres )en fonction des colonnes et des lignes ET les stocker dans la feuille résultat .
Bien sur , y'aura pas que deux lignes mais quand je sélectionne une ligne je la stocke puis une autre ligne ainsi de suite ( ce qui fera une liste par la suite ).
cette fois ci , j'ai essayer d'imaginer le tableau que je pourrai avoir, cela me semble logique et propre .Je le place dans USERFORM.xlm avec le formulaire que Theze avait posté ici + les deux fichiers et je laisse la main
Papou , si j'ai mal compris encore une fois , c'est parce que je n'ai pas d'autres idée pour le tableau résultat . Je m'excuse d'avance .
Bonne après midi .
Re Bonjour Peerl le forum
bon alors on avance pas vite mais on avance
Ce que tu n'as pas compris c'est qu'il ne faut pas tenir compte des données que tu souhaites ouvrir au moment M,
mais que tu dois pour pouvoir consulter tes données ultérieurement créer une ou plusieurs feuilles avec toutes tes données et ensuite un Userform, avec un module de recherche, et là tu pourras lire ce que tu veux quand tu le veux
je vais ouvrir le fichier pour voir ce que tu as pondu
a+
Papou
Bonjour,
Voici le classeur en retour avec une routine de recherche sur le bouton "Rechercher" vu comment sont construit les classeurs où sont rechercher les valeurs je ne garanti pas un résultat parfait !
Les différents blocs liés aux titres doivent être séparés par au moins une ligne vide car une fois le titre trouvé (boucle For Each ... Next avec Like) la plage de recherche est définie de la cellule contenant le titre recherché jusqu'à la dernière cellule utilisé formant la fin du bloc :
Bonjour , Theze , Papou , en forme le forum ?
Je viens de tester le userform, et il marche très bien sur mes fichiers de test . Sur tout les ID , etc ...
Quand je teste sur les fichiers de bases , ça marche très bien aussi . Par contre , j'ai remarqué quand je passe d'un fichier à un autre ça Ram trop des fois je suis obligé de mettre fin à la tache ( gestionnaire de tache ). Je me demande si ce n'est pas à cause de la taille du fichier : 10,8 Mo .
Puis , sur les fichiers de bases ( sachant que je n'ai modifié que les données ) : quand je choisi un ID autre que celui qui est juste après le titre il ne le trouve pas.En regardant le code , je ne vois pas de spécification de ligne par rapport à la recherche des ID donc je me demande pourquoi cela ?
Merci bien et bonne journée
Bonjour,
Par contre , j'ai remarqué quand je passe d'un fichier à un autre ça Ram trop des fois je suis obligé de mettre fin à la tache ( gestionnaire de tache ). Je me demande si ce n'est pas à cause de la taille du fichier : 10,8 Mo
C'est peut être lié au nombre de classeurs ouverts qui peut poser problème, dans ce cas, il est préférable de fermer ce qui ne sont plus utiles. Remplace le code lié à la ListBox1 par celui-ci dessous. Au changement de sélection dans la ListBox1, le précédent classeur est fermé :
Private Sub ListBox1_Click()
Dim Cat As Object
Dim Tbl() As String
If Existe = False Then Exit Sub
'si le classeur sélectionné est celui-ci, fin de procédure
If ListBox1.Text = ThisWorkbook.Name Then ListBox2.Clear: Exit Sub
'si la variable est initialisée et que le nom du classeur est
'différent de celui qui vient d'être sélectionné dans la liste, ferme le classeur
'et décharge la variable
If Not Cls Is Nothing Then
If Cls.Name <> ListBox1.Text Then
Cls.Close False
Set Cls = Nothing
End If
End If
'dans le cas où il serait déjà ouvert, erreur si ce n'est pas le cas donc la gérer
On Error Resume Next
Set Cls = Workbooks(ListBox1.Text)
'si il y a erreur, le classeur n'est pas ouvert donc, ouverture
If Err.Number <> 0 Then Set Cls = Workbooks.Open(Dossier & ListBox1.Text)
'si on souhaite ne pas voir le classeur ouvert à l'écran, ôter les apostrophes
'Application.ScreenUpdating = False
'Windows(ListBox1.Text).Visible = False
'Application.ScreenUpdating = True
On Error GoTo 0
'crée l'objet catalogue
Set Cat = CreateObject("ADOX.Catalog")
Cat.ActiveConnection = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" & _
Dossier & ListBox1.Text & _
";Extended Properties=""Excel 12.0;HDR=NO;IMEX=2;"""
'récupère les noms des feuilles
Tbl = FeuillesExcel(Cat)
'rempli la liste
ListBox2.List = Tbl()
End SubPuis , sur les fichiers de bases ( sachant que je n'ai modifié que les données ) : quand je choisi un ID autre que celui qui est juste après le titre il ne le trouve pas.En regardant le code , je ne vois pas de spécification de ligne par rapport à la recherche des ID donc je me demande pourquoi cela ?
Comme j'ai dis dans mon précédent message, les blocs doivent être séparés par une ligne vide mais il ne doit pas y en avoir entre la ligne où se trouve le titre et celle soù se trouvent les ID comme dans l'exemple ci-dessous :
Titre 1
ID
ID
ID
ID
<------ ligne vide !
Titre 2
ID
ID
ID
<----- ligne vide
Titre 3
etc...
Cette ligne de code effectue la recherche du titre sur chaque cellule de la colonne A (l'astérisque permet de prendre en compte toutes lettres ou chiffres qui peuvent se trouver entre le mot "Titre" et le titre lui même) :
If Cel.Value Like "Titre*" & TxtTitre.Text ThenSi le titre est trouvé, on défini la plage de recherche de l'ID avec cette ligne de code :
With Fe: Set PlageID = .Range(.Cells(Cel.Row, 1), .Cells(Cel.Row, 1).End(xlDown)): End Withet comme tu peux le voir, la recherche de la dernière ligne utilisée sous la cellule contenant le titre est faite en descendant (xlDown) donc il ne faut pas de ligne vide sous la ligne qui contient le titre mais pour définir le bloc d'ID correspondant au titre recherché, il faut qu'il y est une ligne vide avant le titre prochain !
Re Theze ,
Je viens de modifier le code , effectivement , ça Ram moins mais ça Ram toujours car , si je comprends bien ça dépends de combien on charge dans le LISTBOX . les fichiers que j'ai actuellement sont 18 fichiers et les feuilles sont 90 par fichiers . ça Ram pas pour le premier fichier.
Pour les feuilles , peut on limiter la récupération des noms des feuilles ? si on précise quelle feuille ou par exemple charger que les feuilles commençant par A ou B ? J'ai pensé à ajouter un bouton réinitialiser comme ça une fois je finis avec un classeur je vide la liste puis charger une autre liste de feuilles . --> j'ai testé , mais pas de différence.
Autre question , pour les ID , je comprends mieux maintenant qu'il faut pas y avoir une ligne vide entre le titre et l'ID parce qu’on utilise (xlDown) , et dans le cas ou y'a une ligne vide ? y a t il une solution pour ça ?
Sinon , le code il réponds au plus important Merci Theze .
Bonjour Peerl Theze
sans vouloir me mêler de ce qui ne me regarde pas Theze
a+
Papou
.Cells(Lgn, 3).Value = Cel.Text
.Range(.Cells(Lgn, 4), .Cells(Lgn, 13)).Value = Fe.Range(Fe.Cells(CelTrouve.Row, 1), Fe.Cells(CelTrouve.Row, 10)).Value
End With
MsgBox "Valeurs enregistrés!", , "Enregistreé": TxtTitre = "": TxtID = "": Exit For 'sortie de boucle d'office si le titre est trouvé
End IfRe,
Dans les ListBox, c'est seulement les noms des classeurs et des feuilles qui sont inscrits sans qu'ils soient ouverts donc ce n'est pas ce qui fait ramer ! Les ListBox ne contiennent en fait que du texte et tu pourrais en avoir 100 fois plus que ça ne changerait rien, le problème est ailleurs. Le dernier code que je t'ai donné ferme le classeur ouvert (celui où tu viens de récupérer les valeurs) avant d'en ouvrir un autre donc, il n'y a que deux classeurs ouverts, celui qui contient le code et celui où tu veux récupérer les valeurs.
Poses un bouton sur ta Form et dansl'événement CLick() colles ces lignes de code et testes :
Dim C As Workbook
For Each C In Workbooks
MsgBox C.Name
Next CNormalement, tu ne devrais pas avoir plus de deux messages qui s'affichent, le nom de celui qui contient le code et celui sélectionné dans la ListBox1
Re ,
Theze , avec ce code , ça affiche que les deux noms des deux ficheirs qui sont ouvert comme tu as dis . quand je clique sur le premier fichier de la liste , ça Ram pas du tout c'est surtout les autres fichiers .
Papou , ta macro permet de réinitialiser les txtTitre et txtID .
Bonjour Papou,
pour :
.Cells(Lgn, 3).Value = TxtTitre.Texton peut effectivement mettre "Cel.Text" au lieu de "TxtTitre.Text" mais ceci ne change rien car si trouvé, le titre correspond.
Tu as raison, il faut vider les TextBox et on peut même activer la feuille "Résultat" pour justement les voir :
Private Sub CmdRecherche_Click()
Dim Plage As Range
Dim PlageID As Range
Dim Cel As Range
Dim CelTrouve As Range
Dim Lgn As Long
If Cls Is Nothing Then MsgBox "Veuillez sélectionner un classeur dans la liste de gauche !": Exit Sub
If Fe Is Nothing Then MsgBox "Veuillez sélectionner une feuille dans la liste de droite !": Exit Sub
If TxtTitre.Text = "" Then MsgBox "Veuillez indiquer un titre !": Exit Sub
If TxtID.Text = "" Then MsgBox "Veuillez indiquer un ID !": Exit Sub
With Fe: Set Plage = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp)): End With
For Each Cel In Plage
If Cel.Value Like "Titre*" & TxtTitre.Text Then
With Fe: Set PlageID = .Range(.Cells(Cel.Row, 1), .Cells(Cel.Row, 1).End(xlDown)): End With
Set CelTrouve = PlageID.Find(TxtID.Text, Cel, xlValues, xlWhole)
If CelTrouve Is Nothing Then MsgBox "ID introuvable pour " & TxtTitre.Text: Exit Sub
With ThisWorkbook.Worksheets("Résultat")
Lgn = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
.Cells(Lgn, 1).Value = Fe.Range("B5").Value
.Cells(Lgn, 2).Value = Fe.Range("B4").Value
.Cells(Lgn, 3).Value = Cel.Text '.Cells(Lgn, 3).Value = TxtTitre.Text
.Range(.Cells(Lgn, 4), .Cells(Lgn, 13)).Value = Fe.Range(Fe.Cells(CelTrouve.Row, 1), Fe.Cells(CelTrouve.Row, 10)).Value
MsgBox "Valeurs enregistrés !", , "Enregistrée.": TxtTitre.Text = "": TxtID.Text = ""
ThisWorkbook.Worksheets("Résultat").Activate
End With
Exit For 'sortie de boucle d'office si le titre est trouvé
End If
Next Cel
End SubTheze , avec ce code , ça affiche que les deux noms des deux ficheirs qui sont ouvert comme tu as dis . quand je clique sur le premier fichier de la liste , ça Ram pas du tout c'est surtout les autres fichiers .
Quand tu cliques en premier sur un fichier autre que le premier de la liste ça rame ou pas du tout ? Ou c'est après l'ouverture d'un second classeur quel qu'il soit ?
Quand tu cliques en premier sur un fichier autre que le premier de la liste ça rame ou pas du tout ? Ou c'est après l'ouverture d'un second classeur quel qu'il soit ?
Quand je cliques en premier sur un fichier autre que le premier de la liste ça rame aussi
Donc, je pense que se sont certains classeurs qui posent problème !
C'est à quel moment que ça rame ? Quand tu fais une recherche, quand tu sélectionnes un classeur dans la liste de la ListBox1, quand tu sélectionnes une feuille dans la ListBox2 ?
c'est surtout quand je cliques sur un classeur dans listbox1 : les listes se vident ( tout devient blanc )
Je peux attendre 1 à deux minutes pour que j'aie le formulaire avec les listbox rempli de nouveau . J'ai testé une autre fois en cliquant directement sur un autre classeur , cette fois çi la liste n'a pas disparu mais ça rame de nouveau ( flou + cercle bleu ) sachant qu'il a ouvert le fichier quand même sur mon écran .
Juste pour tester, remplace le code de la ListBox1 par celui-ci, qui n'utilise plus le catalogue ADO mais une boucle puisque le classeur est chargé :
Private Sub ListBox1_Click()
Dim Fe As Worksheet
If Existe = False Then Exit Sub
'si le classeur sélectionné est celui-ci, fin de procédure
If ListBox1.Text = ThisWorkbook.Name Then ListBox2.Clear: Exit Sub
'si la variable est initialisée et que le nom du classeur est
'différent de celui qui vient d'être sélectionné dans la liste, ferme le classeur
'et déchartge la vazriable
If Not Cls Is Nothing Then
If Cls.Name <> ListBox1.Text Then
Cls.Close False
Set Cls = Nothing
End If
End If
'dans le cas où il serait déjà ouvert, erreur si ce n'est pas le cas donc la gérer
On Error Resume Next
Set Cls = Workbooks(ListBox1.Text)
'si il y a erreur, le classeur n'est pas ouvert donc, ouverture
If Err.Number <> 0 Then Set Cls = Workbooks.Open(Dossier & ListBox1.Text)
'si on souhaite ne pas voir le classeur ouvert à l'écran, ôter les apostrophes
'Application.ScreenUpdating = False
'Windows(ListBox1.Text).Visible = False
'Application.ScreenUpdating = True
On Error GoTo 0
'rempli la liste
For Each Fe In Cls.Worksheets
ListBox2.AddItem Fe.Name
Next Fe
End SubJe viens de tester , ça ne rame plus quand je passe d'un classeur à un autre , mais dans listbox2 il rajoute les feuilles à chaque fois : feuilles du premier classeur + les feuilles du deuxième classeur sélectionné etc..
Il faut juste vider la liste avant (j'ai oublié !) avec "ListBox2.Clear" avant la boucle :
Private Sub ListBox1_Click()
Dim Fe As Worksheet
If Existe = False Then Exit Sub
'si le classeur sélectionné est celui-ci, fin de procédure
If ListBox1.Text = ThisWorkbook.Name Then ListBox2.Clear: Exit Sub
'si la variable est initialisée et que le nom du classeur est
'différent de celui qui vient d'être sélectionné dans la liste, ferme le classeur
'et déchartge la vazriable
If Not Cls Is Nothing Then
If Cls.Name <> ListBox1.Text Then
Cls.Close False
Set Cls = Nothing
End If
End If
'dans le cas où il serait déjà ouvert, erreur si ce n'est pas le cas donc la gérer
On Error Resume Next
Set Cls = Workbooks(ListBox1.Text)
'si il y a erreur, le classeur n'est pas ouvert donc, ouverture
If Err.Number <> 0 Then Set Cls = Workbooks.Open(Dossier & ListBox1.Text)
'si on souhaite ne pas voir le classeur ouvert à l'écran, ôter les apostrophes
'Application.ScreenUpdating = False
'Windows(ListBox1.Text).Visible = False
'Application.ScreenUpdating = True
On Error GoTo 0
ListBox2.Clear
'rempli la liste
For Each Fe In Cls.Worksheets
ListBox2.AddItem Fe.Name
Next Fe
End SubC'est ce que je pensais, c'est ADO qui fait ramer. Tu peux virer la fonction "FeuillesExcel()" elle ne t'est plus utile et donc, inutile d'encombrer le module de fonction qui ne servent à rien
Ah ça fonctionne parfaitement maintenant ! Je viens d'apprendre un nouveau truc
et pour ma question précédente , si on tombe sur une ligne vide qui sépare les IDs du titre ?
Une autre question CHEF , est il possible que quand je clique sur la feuille dans listbox2 qu'il me dirige directement vers la feuille . J'ai une macro qui fait ça mais faut insérer le bouton dans la première feuille du classeur à chaque fois :
Sub onglets()
Dim tablRetour As Variant
Dim TheFil As Variant
Dim LeClasseur, LaFeuille As Variant
For Each LeClasseur In Workbooks
For Each LaFeuille In LeClasseur.Worksheets
If LaFeuille.Name = " Nom de la feuille" And LeClasseur.Name <> " Nom du classeur " Then
LeClasseur.Activate
Sheets("Nom de le feuille").Select
End If
Next LaFeuille
Next LeClasseur
End SubRemplaces le code lié au bouton de recherche par celui-ci mais attention, ce n'est pas très propre et plutôt perfectible !
Tes classeurs devraient être construit autrement, plutôt comme une base de données quitte à répéter plusieurs fois certaines valeurs mais bon, c'est à toi de voir :
Private Sub CmdRecherche_Click()
Dim Plage As Range
Dim PlageID As Range
Dim Cel As Range
Dim CelTrouve As Range
Dim Lgn As Long
If Cls Is Nothing Then MsgBox "Veuillez sélectionner un classeur dans la liste de gauche !": Exit Sub
If Fe Is Nothing Then MsgBox "Veuillez sélectionner une feuille dans la liste de droite !": Exit Sub
If TxtTitre.Text = "" Then MsgBox "Veuillez indiquer un titre !": Exit Sub
If TxtID.Text = "" Then MsgBox "Veuillez indiquer un ID !": Exit Sub
With Fe: Set Plage = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp)): End With
For Each Cel In Plage
If Cel.Value Like "Titre*" & TxtTitre.Text Then
If Cel.Offset(1).Value = "" Then
With Fe: Set PlageID = .Range(.Cells(Cel.Row + 2, 1), .Cells(Cel.Row + 2, 1).End(xlDown)): End With
If PlageID Is Nothing Then MsgBox "Impossible de définir la plage !": Exit Sub
Set CelTrouve = PlageID.Find(TxtID.Text, Cel.Offset(2), xlValues, xlWhole)
Else
With Fe: Set PlageID = .Range(.Cells(Cel.Row, 1), .Cells(Cel.Row, 1).End(xlDown)): End With
If PlageID Is Nothing Then MsgBox "Impossible de définir la plage !": Exit Sub
Set CelTrouve = PlageID.Find(TxtID.Text, Cel, xlValues, xlWhole)
End If
If CelTrouve Is Nothing Then MsgBox "ID introuvable pour " & TxtTitre.Text: Exit Sub
With ThisWorkbook.Worksheets("Résultat")
Lgn = .Cells(.Rows.Count, 1).End(xlUp).Row + 1
.Cells(Lgn, 1).Value = Fe.Range("B5").Value
.Cells(Lgn, 2).Value = Fe.Range("B4").Value
.Cells(Lgn, 3).Value = Cel.Text '.Cells(Lgn, 3).Value = TxtTitre.Text
.Range(.Cells(Lgn, 4), .Cells(Lgn, 13)).Value = Fe.Range(Fe.Cells(CelTrouve.Row, 1), Fe.Cells(CelTrouve.Row, 10)).Value
MsgBox "Valeurs enregistrés !", , "Enregistrée.": TxtTitre.Text = "": TxtID.Text = ""
ThisWorkbook.Worksheets("Résultat").Activate
End With
Exit For 'sortie de boucle d'office si le titre est trouvé
End If
Next Cel
End Sub