Optimiser recherche dans une grosse BDD Excel

Optimiser recherche dans une grosse BDD Excel - VB/VBA/VBS - Programmation

Marsh Posté le 25-05-2012 à 15:39:28    

Bonjour,  
 
Voici la problématique à laquelle je fais face : je dois vérifier que les infos contenues dans une première base de données sont conformes au contenu d'une deuxième base de données.
 
 
Première base (600 lignes), les colonnes E, F et I m'intéressent :
- E = nom_table
- F = nom_champ
- I = description_champ
 
Deuxième base (35000 lignes), les colonnes C, E et G m'intéressent :
- C = table_name
- E = column_name
- G = column_description
 
 
Objectif : Afficher à l'utilisateur 4 colonnes :
- nom_table (selon la première base)
- nom_champ (selon la première base)
- description_champ (selon la première base)
- column_description (selon la deuxième base) : on fait la correspondance sur les deux critères "nom_table/table_name" et "nom_champ/column_name"
 
On fait ce contrôle pour les 600 lignes de la première base.
 
Les contraintes que je rencontre :
- je ne peux pas modifier les colonnes présentes dans les deux bases
- recherchev (Vlookup en VBA) ne permet de travailler que sur un seul critère et non 2 (or, la contrainte du dessus fait que je ne peux pas faire une colonne où je concatène mes données pour pouvoir utiliser cette fonction)
- bdlire (Dget en VBA) ne permet pas non plus de répondre à mon besoin
 
Ma solution actuelle est de faire une boucle avec condition classique "if" pour vérifier les correspondances sur les deux critères.
Autrement dit, pour les 600 lignes, j'en vérifie 35000. Ce qui fait... trop (21 000 000 de vérifications). Cette macro est interminable, et donc inutilisable en l'état.
J'ai bien tenté de mettre un vilain goto  :whistle:  qui permet de passer automatiquement à la suivante de mes 600 lignes dès que je trouve la bonne, mais la différence de performance est imperceptible.
 
 
Ma question :
Y a t-il une façon d'optimiser ce traitement, au vu de mes contraintes ?
Est-il par exemple envisageable de créer une feuille temporaire, dans laquelle je mettrai la concaténation "nom_table/nom_champ" et la concaténation "table_name/column_name", pour ensuite faire un recherchev (Vlookup), qui serait éventuellement plus rapide ?
 
Et bien sur, à terme, l'objectif sera de n'afficher que les lignes pour lesquelles je constate un écart entre "description_champ" et "column_description", mais je n'en suis pas encore là.
 
 
Merci d'avance à ceux qui se sentiront inspirés,

Reply

Marsh Posté le 25-05-2012 à 15:39:28   

Reply

Marsh Posté le 25-05-2012 à 16:08:06    

Excel est pas franchement fait pour ce genre de traitement. Tu ferais mieux de charger tes 2 fichiers Excel sources dans une BD et de faire du SQL ensuite :/


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 25-05-2012 à 16:34:50    

Tout à fait d'accord avec Rufo.
Tu charge tes 2 fichiers dans access et tu fais tes requêtes.
 
 
 
Et pour info, pour le point :

Citation :

- recherchev (Vlookup en VBA) ne permet de travailler que sur un seul critère et non 2 (or, la contrainte du dessus fait que je ne peux pas faire une colonne où je concatène mes données pour pouvoir utiliser cette fonction)


tu as toujours la possibilité de concaténer tes 2 colonnes dans tes 2 fichiers et de rechercher sur la valeur unique que tu viens ainsi de créer ou bien, moins évident et plus lourd, les formules matricielles qui permettent de faire des recherches à 2 critères avec INDEX() et EQUIV()


---------------
Bel ours Vave, je me dois de l’admettre. -Skyl"win"-  Mais toi tu es intelligent -Homerde- - Ce génie -SkylWINd- JDD S16M72 10:43:46 GMT-DTC +1
Reply

Marsh Posté le 25-05-2012 à 16:41:49    

rufo > Cette histoire de macro n'est pas mon idée, et je suis bien d'accord avec le fait qu'Excel n'est pas le meilleur outil pour faire ça. Mais je n'ai pas la possibilité d'utiliser un autre outil.
 
oovaveoo > Comme indiqué précédemment, je ne peux pas toucher au format des deux bases. D'où l'idée que j'émettais de créer un onglet temporaire dans lequel j'aurais pu créer ces colonnes concaténées.
 
Je vais opter pour un compromis et leur faire un truc avec des formules et sans macro, et voir si ça passe.
 
Merci quand même  :jap:

Reply

Marsh Posté le 25-05-2012 à 16:57:57    

Pourquoi ne peux-tu pas utiliser un autre outil? Qu'est-ce qui t'en empêche?


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 25-05-2012 à 17:16:55    

C'est une contrainte qui m'est imposée.

Reply

Marsh Posté le 25-05-2012 à 17:32:05    

T'as pas le droit faire une macro qui exploiterait un SGBD (même en version portable) pour faire la partie traitement "temporaire" qui te prend tant de temps avec Excel, et qui fournirait en sortie le fichier Excel résultat :??:


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 26-05-2012 à 15:35:19    

rufo et oovaveoo: pourquoi vous ne lui proposez pas d'utiliser un dictionnaire ?  :heink:  
 
J'ai fait un test avec des données aléatoires:
A B C D E F G H
table1 champ1 desc1   table12361 champ12361 desc12361
table2 champ2 desc2   table23925 champ23925 desc23925
table3 champ3 desc3   table19792 champ19792 desc19792
table4 champ4 desc4   table5686 champ5686 desc5686
table5 champ5 desc5   table30673 champ30673 desc30673
table6 champ6 desc6   table2391 champ2391 desc2391
 

Citation :


Sub fdgfd()
 
Dim dico As Scripting.Dictionary
 
Set dico = New Scripting.Dictionary
 
For i = 2 To 35001
    dico(Cells(i, 6).Value & Cells(i, 7).Value) = Cells(i, 8).Value
Next i
 
For i = 2 To 601
    If dico.Exists(Cells(i, 1).Value & Cells(i, 2).Value) = True Then Cells(i, 4).Value = dico(Cells(i, 1).Value & Cells(i, 2).Value)
Next i
 
Set dico = Nothing
 
End Sub


 
- de 2 secondes  :o  

Reply

Marsh Posté le 28-05-2012 à 19:50:30    

A la lecture du truc, je ne comprends pas tout à fait comment ça fonctionne, mais je tenterai d'exploiter ça dès  demain, ça me semble prometteur.
 
Merci !

Reply

Marsh Posté le 28-06-2012 à 15:29:42    

Hello,  
 
Merci pour l'astuce avec le dico. J'ai enfin trouvé le temps de bosser dessus aujourd'hui, et je sens déjà que ça va bien plus rapidement que mes bidouillages précédents.
 
En revanche, mes recherches Google m'indiquent que dans un dico, on a forcément une clé unique + une valeur associée, et c'est tout. Du coup je me retrouve à bidouiller quand même avec :
- clé = concaténation "nom de la table & nom du champ"
- valeur = la valeur qui m'intéresse, mais du coup je dois créer un dico pour chacune des infos que je veux vérifier (un dico pour les descriptions, un dico pour les formats, ...)
 
Sur ce, je retourne à mes recherches et bidouilles...

Reply

Marsh Posté le 28-06-2012 à 15:29:42   

Reply

Marsh Posté le 28-06-2012 à 18:06:55    

Je confirme que cette solution déchire.
Certes, elle a des limites semble t-il, comme le fait de ne pouvoir associer qu'une seule valeur à la clé, mais avec quelques bidouillages (et 4 dictionnaires), ça marche super rapidement ! En 15 ou 20 secondes je dirais.
 
Merci beaucoup tarteflambee !

Reply

Marsh Posté le 06-04-2013 à 17:22:31    

Bonjour,
 
-Sélectionner G2:G2673
=RechvM(F2:F2673;matable;2)
-Valider avec maj+ctrl+entrée
 
Function RechvM(clé As Range, champ As Range, colResult)
  Application.Volatile
  Set d = CreateObject("Scripting.Dictionary" )
  a = champ.Value
  b = clé.Value
  For i = LBound(a) To UBound(a)
    d(a(i, 1)) = a(i, colResult)
  Next i
  Dim temp()
  ReDim temp(LBound(b) To UBound(b))
  For i = LBound(b) To UBound(b)
    temp(i) = d(b(i, 1))
  Next i
  RechvM = Application.Transpose(temp)
End Function
 
http://boisgontierjacques.free.fr/ [...] hVMult.zip
 
JB

Reply

Marsh Posté le 06-04-2013 à 19:26:59    

Bonjour,

 

Je ne comprends pas trop l'intérêt de remonter ainsi mon message qui date d'il y a plus de 10 mois. J'indiquais d'ailleurs avoir trouvé une solution qui fonctionnait.

 

Là, en dehors du code, il y a juste "Bonjour" et "JB", bref, aucune explication sur ce que fait ce morceau de code (que j'ai survolé mais pas étudié). Bref, ça aurait été intéressant pour moi que quelqu'un réponde à ma problématique de "mettre plusieurs variables en face d'une clé" (comme une sorte de mini-table en fait), mais en lisant ce code (qui fait appel à certaines notions que je ne connais pas), en l'état, je n'apprends rien en fait.

 

Je ne demande pas non plus un roman, mais tout du moins quelques explications contextuelles. En l'état, ça fait vraiment "pub" et du coup, je n'ai même pas pris la peine de cliquer sur le lien [:thalis]


Message édité par $temp le 06-04-2013 à 19:27:57
Reply

Marsh Posté le 08-04-2013 à 21:52:26    

Bonsoir,
 
Si tu mettais une pièce jointe, ça serait + facile de regarder ton pb.
 
 
>Je ne comprends pas trop l'intérêt de remonter ainsi mon message qui date d'il y a plus de 10 mois
 
Ma pièce jointe montre que pour Recherchev():
 
-sur une table de 20000 items,
-la formule recopiée 2600 fois
 
On passe d'un temps de recalcul de 5 sec à 0,12 s grâce à une fonction perso matricielle.
 
-Je penses que beaucoup de personnes sont concernées par ce cas très fréquent et aurons la réponse si elles font une recherche sur Google.
C'est en recherchant ' Recherchev plus rapide' que je suis arrivé sur ce post.
 
>mettre plusieurs variables en face d'une clé" (comme une sorte de mini-table en fait),
 
Justement, il me semble bien que c'est ce que fait la fonction du  lien (on a plusieurs réponses pour une clé).
 
http://boisgontierjacques.free.fr/ [...] hVMult.zip
 
J'ai utilisé le même principe pour remplacer sommeprod() par une fonction perso matricielle qui permet de passer de 3s à 0,05s pour un champ de 4000 lignes
 
http://boisgontierjacques.free.fr/ [...] dictionary
 

Rappel sur recherchev()  [ la documentation officielle ne précise pas qu'avec une table triée, la recherche est dichotomique] :

 
Si la valeur cherchée est un code et si la table est TRIEE, on peut spécifier le paramètre VRAI.
La recherche est alors faite par DICHOTOMIE et peut être x100 + RAPIDE puisqu'il suffit de quelques
accès pour retrouver le code. C'est TRES IMPORTANT lorsque la table est de taille importante et que
la formule Recherchev() est recopiée x1000 fois (Avec FAUX , Excel consulte la table SEQUENTIELLEMENT).
Pour vérifier si le code existe (on ne récupère pas #N/A mais la valeur inférieure), il faut écrire:
 
=SI(RECHERCHEV(CodeCherché;Articles;1;VRAI)=
CodeCherché;RECHERCHEV(CodeCherché;Articles;2;VRAI);"Inconnu" )  
 
JB
http://boisgontierjacques.free.fr


Message édité par JacquesBoisgontier le 08-04-2013 à 23:18:18
Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed