VBA : optimisation macro

Résolu/Fermé
ptite_joe - 5 févr. 2010 à 01:59
eriiic Messages postés 24575 Date d'inscription mardi 11 septembre 2007 Statut Contributeur Dernière intervention 26 mai 2024 - 9 févr. 2010 à 19:24
Bonjour à tous !

Je suis une newbie en VBA et il y a toujours des bugs que je n'arrive pas à résoudre et mes macros ne sont pas du tout optimisées (elles mettent bcp trop de temps à tourner...) :-s

Voici ce que je veux faire :
J'ai un fichier avec des onglets dans lesquels se trouvent dans chaque colonne A des données (numéro d'identification de protéines) - sachant que dans une cellule, il peut y avoir jusqu'à 50 numéros d'identification différents séparés par un point-virgule. Chaque onglet correspond à une base de données.
-> je veux toutes les regrouper dans mon onglet "Database" (=Worksheets(1)) où chaque "Protein ID" ne doit apparaître qu'une fois, dans la colonne, toutes les unes à la suite des autres. (Sachant que les bases de données sont assez conséquentes).

J'ai donc écrit une macro qui convertit les données sur chaque onglet pour les séparer dans des cases différentes. Ensuite, je recopie toutes les données de mon premier onglet (=première BDD) dans l'onglet "Database". Enfin, je prends les onglets suivants et recherche pour chaque cellule non vide si la donnée existe déjà dans Database, et si non, je la recopie à la suite (ce qui est très long).

Je sais qu'il faut éviter de faire des .select mais la macro ne rapatrie pas mes données quand je ne l'écris pas... Et pour la seconde partie de la macro (à partir du Case Else), les données ne sont pas rapatriées, mais je ne comprends pas pourquoi !

Voici mon code, si quelqu'un a une idée de comment je peux optimiser tout ça et pourquoi la fin de la macro ne fonctionne pas, je vous en serai vraiment reconnaissante !! :-D

Sub generate_database()

Dim nb As Integer
Dim i As Integer, j As Integer, k As Integer
Dim li As Integer
Dim LastCell As Range
Dim myvar
Dim Chart As Range

nb = ActiveWorkbook.Worksheets.Count

For i = 2 To nb
Worksheets(i).Activate
Range("A2").Select
Range(Selection, Range("A66530").End(xlUp)).Select
Selection.TextToColumns Destination:=Range("C2"), DataType:=xlDelimited, _
TextQualifier:=xlDoubleQuote, ConsecutiveDelimiter:=False, Tab:=False, _
Semicolon:=True, Comma:=False, Space:=False, Other:=False, FieldInfo _
:=Array(Array(1, 1), Array(2, 1), Array(3, 1), Array(4, 1), Array(5, 1), Array(6, 1), _
Array(7, 1)), TrailingMinusNumbers:=True
Next i

Set LastCell = Worksheets("Database").Range("A3")
Set Chart = Worksheets("Database").Columns("A:A")

For i = 2 To nb
Worksheets(i).Select
Select Case i

Case 2
Range("A2", Range("A66530").End(xlUp)).Select
li = Selection.Rows.Count
For k = 2 To li + 1
j = 3
While Not IsEmpty(Cells(k, j))
myvar = Cells(k, j).Value
Worksheets("Database").Select
LastCell.Select
LastCell.Value = myvar
Set LastCell = LastCell.Offset(1, 0)
Worksheets(i).Select
j = j + 1
Wend
Next k

Case Else
Range("A2", Range("A66530").End(xlUp)).Select
li = Selection.Rows.Count
For k = 2 To li + 1
j = 3
While Not IsEmpty(Cells(k, j))
On Error Resume Next
If Application.WorksheetFunction.IsError(Application.WorksheetFunction.VLookup(" & Cells(k, j) & ", Chart, 1, False)) = True Then
Worksheets("Database").Select
LastCell.Select
LastCell.Value = myvar
Set LastCell = LastCell.Offset(1, 0)
Worksheets(i).Select
j = j + 1
Else: j = j + 1
End If
Wend
Next k

End Select

Next i

Set LastCell = Nothing
Set Chart = Nothing

End Sub

Merci par avance pour votre précieuse aide !!!!!

8 réponses

eriiic Messages postés 24575 Date d'inscription mardi 11 septembre 2007 Statut Contributeur Dernière intervention 26 mai 2024 7 219
5 févr. 2010 à 07:11
Bonjour,

Déjà au début tu peux ajouter :
application.screenupdating=false
Rétablir à la fin avec =true

Et pour le reste ça serait plus facile avec un fichier exemple de ce que tu as, ce que tu veux obtenir et ta macro.
Tu peux utiliser cijoint.fr et déposer ici le lien fourni.
eric
0
ptite_joe Messages postés 1 Date d'inscription vendredi 5 février 2010 Statut Membre Dernière intervention 5 février 2010
5 févr. 2010 à 14:49
Bonjour Eriiic,

tout d'abord, merci pour ta reponse !

Voici un exemple de fichier :
http://www.cijoint.fr/cjlink.php?file=cj201002/cijEiBQrl0.xlsx

Je n'ai dans ce fichier que 4 bases de donnees que j'ai tronquees, mais les base de donnees vont rapidement devenir importantes. Le probleme est qu'il y a de nombreux doublons entre les differentes bases de donnees.

Ce que je voudrais : que la macro parcourt toutes les bases de donnees, et rapatrie dans l'onglet "Database" chaque '"nom de code de la proteine", en colonne, sans doublon. Je veux creer une base de donnes unique en clair !

Merci pour votre aide !!!

ptite_joe
0
eriiic Messages postés 24575 Date d'inscription mardi 11 septembre 2007 Statut Contributeur Dernière intervention 26 mai 2024 7 219
5 févr. 2010 à 19:40
Bonsoir,

J'ai dû le convertir au format excel 2003, si tu veux récupérer tout ton nombre de lignes possibles sur 2007 il faut que tu l'enregistres en .xlsx
J'ai fait en sorte que la macro s'adapte au nombre de lignes dispo selon la version.
Je n'ai pas comparé le temps avec ta version, je pense qu'il y a un gain mais je ne sais pas de combien.

Par contre une donnée que tu n'as pas fourni : combien d'id à terme ?
Et que faire si le nombre maxi est atteint ? Attaquer la colonne suivante que tout soit sur la même feuille ou ajouter une feuille database ou ... ?

Je pense que ça tourne bien mais je te laisse le soin de tester à fond et de remonter les anomalies assez vite tant que j'ai le truc en tête.
Ptitejoe.xls

eric
0
Bonjour Eriiic,

merci beaucoup pour ton aide !
Je teste ça dès lundi (j'ai un mac à la maison, avec Excel 2008 :-s ), donc je ne peux tester ça tout de suite.
Je te tiens au courant.

Encore merci ! :-)

Ptite_joe
0
Bonjour Eriiic,

je viens de tester la macro et ca marche parfaitement et plus rapidement que la mienne !!
Merci beaucoup ! A terme, je ne sais pas combien d'ID il y aura, cela depend des experiences mais je pense que ce devrait aller...^^

Merci !

Ptite_joe
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
Hello Eriiic !
J'ai encore une tout derniere question si je peux abuser de ton savoir...
Maintenant que j'ai ma base de donnees, je voudrais faire des rechercheV sur mes "Protein IDs". Sauf que dans mes fichiers sources, les IDs sont organisees de la meme facon que dans mes onglets (plusieurs IDs par cellule separees par un point-virgule) - donc la rechercheV ne marche pas... J'ai bien essaye de combiner des fonctions FIND et EQUIV mais ca ne marche pas. Penses-tu qu'il y a une solution pour que la rechercheV fonctionne ou je dois obligatoirement passer par une macro ?

Merci pour ton aide et vive les forums !

Ptite_joe
0
eriiic Messages postés 24575 Date d'inscription mardi 11 septembre 2007 Statut Contributeur Dernière intervention 26 mai 2024 7 219
8 févr. 2010 à 21:03
Bonsoir,

Et non, un recherchev() ne peut pas trouver une portion de chaine dans la table, obligée de faire une macro (qui risque d'être longue à trouver le résultat...)
Mais si ta recherche part de ta database crée pourquoi ne pas inscrire sur la ligne des liens vers les cellules où les ID ont été trouvés (et pourquoi pas non plus ajouter sur ces cellules liens un commentaire approprié pour faciliter ton choix) ?
Dans la limite des 256 colonnes pour 2003...
eric
0
Hello Eriiic,

et bien, je pense que c'est ce que je vais faire, ca me semble une bonne idee et ca sera moins complique !
Merci pour ta reponse ! :-)

Ptite_joe
0
eriiic Messages postés 24575 Date d'inscription mardi 11 septembre 2007 Statut Contributeur Dernière intervention 26 mai 2024 7 219
9 févr. 2010 à 19:24
Ok, bon courage ;-)
Reviens si tu as un soucis, et n'oublie de mettre en résolu si c'est le cas

eric
0