VB6 et Excel

AlexDam Messages postés 31 Date d'inscription mercredi 6 septembre 2006 Statut Membre Dernière intervention 10 octobre 2006 - 6 sept. 2006 à 22:41
AlexDam Messages postés 31 Date d'inscription mercredi 6 septembre 2006 Statut Membre Dernière intervention 10 octobre 2006 - 11 sept. 2006 à 16:27
    Hey there, bon ben deja obnjour a tous (c'est mon premier post :)), et déja ça commence bien je suis pas sur d'avoir posté dans la bonne section lol.

Enfin bon, voila je debute en vba mais j'ai quelques connaissances en VB. En fait pour mon stage, je dois faire un appli (vb6) pour ma boss à partir de vb6 et qui utilise des fichiers excel et .csv.

L'un des premiers truc que j'ai à faire c'est cheker une liste dans un fichier .csv (donc tout les champ une colonne quoi) avec un autre liste dans un autre fichier. En gros, disons que dans un fichier excel j'ai une liste de nouvel recette(une recette par champ) et que je veux cheker si elles sont déja présente dans le livre de recette (toujours un recette par champ).

Donc tout happy, je fais ma connection aux deux fichiers, je fais une double boucle tout ce qu'il y a de plus normal, et la c'est le drame... ça prend un temps terrible... Bon il faut imaginer que la liste des nouvelles recette a 1000 entree et que le livre de recette en a 10000, la d'accord on peut comprendre que ça prenne longtemps. Moi aussi je suis d'accord.

Mon code:


'Check receipts

Set eWorkSheet1 = exl.Worksheets(2)


If Form2.Check1 = "1" Then

'Sales


i = 2

a = a + 5

While eWorkSheet.Cells(i, 5) <> "" 'les cellules de mes recettes a cheker

u = False

b = 2


While eWorkSheet1.Cells(b, 1) <> "" And u = False ' tant que je trouve pas la recette dans le book (si je la trouve ça break)


If eWorkSheet.Cells(i, 5) = eWorkSheet1.Cells(b, 1) Then '

u = True

End If


b = b + 1

Wend


If u = False Then 'je ne fais pas dajout direct mais je sort dans un autre fichier les recettes a rajouter

eWorkSheet2.Cells(a, 1) = "The receipt" & eWorkSheet.Cells(i, 5) & " has to be added to the receipt book."

a = a + 1


End If


End If


i = i + 1

Wend


End If

Print "Brands checked"

Maintenant, on en arrive à la partie que je compre po :
Jusqu'a présent ma boss utilisait cette macro excel pour faire le truc:


Sub checkReceipts()

Range("I2").Select

ActiveCell.FormulaR1C1 = _

"=VLOOKUP(RC[-4],'[myreceipts.xls]Receipts'!C1:C2,1,FALSE)"

Range("I2:I65500").Select

Range("I65500").Activate

Selection.FillDown

Columns("I:I").Select

Selection.Copy

Selection.PasteSpecial Paste:=xlValues, Operation:=xlNone, SkipBlanks:= _

False, Transpose:=False

Range("A1").Select

Application.CutCopyMode = False

Et en fait en utilisant ça, ça va genre facilement 20 fois plus vite...

Donc ma premiere question c'est : Est-ce que ça va plus vite du fait que tout le boulot est fait sous excel et que du fait que je developpe mon projet sous vb6 la connection avec les deux fichier ralenti le traitement (fasse à la fonction VLOOKUP donc notamment); ou est-ce que je m'y suis simplement pris comme un manche?(si oui, i beg your pardon, excel et vb ensemble, j'etais vierge il y a deux jours xD).

Ensuite j'aimerais savoir sil es tpossible d'utiliser des fonction comme vlookup directement depuis vb6 par example dans l'optique de faire aller mon traitement à la meme vitesse que feu la macro de ma boss?

En vous remerciant d'avance, pour toute aide, réponse, etc...

34 réponses

AlexDam Messages postés 31 Date d'inscription mercredi 6 septembre 2006 Statut Membre Dernière intervention 10 octobre 2006
8 sept. 2006 à 11:14
    Ben, on est bien d'accord que la je recherche si ce que contient chaque cellule de la colonne 1 de ma feuille 1 est deja dans la colonne 1 de ma feuille 2? J'aimerais avoir un retour: "oui je lai trouver" ou "non, je ne l'ai pas trouver".
Cela dans loptique de faire juste un rapport a la fin (ou un gros msgbox) "oui il faut ajouter la(les recettes lignes) des lignes: x, y z, etc.... au livre de recette"

Par contre, un Dim ilier as boolean
                      ilier =  Call ........       , vb n'apprecie pas trop.
0
AlexDam Messages postés 31 Date d'inscription mercredi 6 septembre 2006 Statut Membre Dernière intervention 10 octobre 2006
8 sept. 2006 à 11:49
    Bon j'ai rien dit en fait: j'ai maintenant :

While eWorkSheet.Cells(i, 2) <> ""
Call eWorkSheet1.Columns(1).Find(eWorkSheet.Cells(i, 2), , , , xlByRows, xlNext)
i = i + 1
Wend

ça passe nikel sur les petits fichier a tester: ~10 000 ligne.
mais bon sur ceux de 60 000 = overflow :c

Le truc maintenant c'est que j'hesite a continuer sur le find (sachant que les plus gros fichiers passerons pas >.<. Ou a tenter de trouver un autre moyen qui me permette de les traiter.
Genre "coller" le find dans une case du fichier excel et apres juste faire une boule pour voir sil a trouver ou pas les truc:

Fichier 1 a cheker:

    A            B            C
Recette1                  donc coller le find ici pour qu'il me mette un jai trouver ou non
Recette2
Recette3
Recette4
Recette5
Recette6
...
Recette70000            et tirer le truc jusque la                

Puis ensuite juste parcourir une fois la colonne c a partir de vb pour relever les index des recettes a ajouter.

De toute evidence le overflow vient de VB, donc peut etre que cette methode eviterait a vb de saturer puisque tout le traitement se ferait sous excel, tu penses pas?
0
cs_MPi Messages postés 3877 Date d'inscription mardi 19 mars 2002 Statut Membre Dernière intervention 17 août 2018 23
8 sept. 2006 à 11:58
Tu dis que tu fais tes recherches dans la première colonne... alors il
faudrait peut-être changer Cells(i,2) pour Cells(i,1) ou encore

Range("A" & i) ou Columns("A:A")


Ma façon de faire une recherche sous Excel ressemblerait à ceci:

Dim Recherche

For I = 2 To Fin 'boucle les éléments de la Feuille1

Valeur = Sheets("Feuille1").Range("A" & I)
Set Recherche = Sheets("Feuille2").Range("...").Find(Valeur)

If not recherche is nothing then  ' trouvé

    strTemp = strTemp & Sheets("Feuille2").Range(Recherche.Address).Row & vbCrLf

    'Continuer la recherche avec FindNext

Else

    'non trouvé

endif


If strTemp <>"" then

msgbox "Lignes trouvées" & vbCrlf & strTemp


La seule chose qui diffère entre Excel et VB, c'est le nom des objets que tu as déclarés.

eWorkSheet plutôt que Sheets("Feuil1")

eWorkSheet1 plutôt que Sheets("Feuil2")


Évidemment, si tu recherches les lignes non trouvées il faut faire
l'inverse dans la procédure et inscrire les lignes dans le Else

MPi
0
AlexDam Messages postés 31 Date d'inscription mercredi 6 septembre 2006 Statut Membre Dernière intervention 10 octobre 2006
8 sept. 2006 à 12:02
    Oui, en effet je me suis chier dessus dans mon post c'est colonne 2 du fichier 1 et 1 du fichier 2 >.<. Je test ton truc apres dejeuner.
    Merci.
0

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

Posez votre question
AlexDam Messages postés 31 Date d'inscription mercredi 6 septembre 2006 Statut Membre Dernière intervention 10 octobre 2006
8 sept. 2006 à 14:03
    Jai tester ta methode elle est cool, cependant j'ai encore ce putain d'overflow... J'ai donc simplement tester de faire des prints sur 60000 lignes:

While i < 60000
eWorkSheet.Cells(i, 2)="test"
i=i+1
Wend

J'ai toujours l'overflow. J'en conclu que vb ne gere pas un fichier excel depassant une certaine taille (en quantiter de rows columns).

Maintenant ma nouvel question se rapporte a mon post precedent. Pensez vous qu'il soit possible de faire faire tout les traitement sous excel sans aucune boucle sous vb?
0
AlexDam Messages postés 31 Date d'inscription mercredi 6 septembre 2006 Statut Membre Dernière intervention 10 octobre 2006
8 sept. 2006 à 14:06
    dsl post pas fini: je sais que je ne pourrais pas retourner les resultats pour chaque rows a VB pour le ;ontrer a l'utilisateur, ça overflowerait de nouveau, il faudrait je sais pas mettre les resultats dans un nouveau fichier excel pourquoi pas...
0
AlexDam Messages postés 31 Date d'inscription mercredi 6 septembre 2006 Statut Membre Dernière intervention 10 octobre 2006
8 sept. 2006 à 14:17
    Sinon, une question tres conne... je peux pas faire ça en tant que macro excel que je mettrais en module dans mon appli vb. Et faire en sorte que une fois que j'ouvre mon fichier excel, celui-ci utilise la dites macro?
0
cs_MPi Messages postés 3877 Date d'inscription mardi 19 mars 2002 Statut Membre Dernière intervention 17 août 2018 23
9 sept. 2006 à 00:25
Pour l'overflow, c'est peut-être que tu as déclaré ta variable "i" As Integer. Il faut la mettre As Long


Je te reviens avec un exemple plus concret, si je me trouve quelques minutes

MPi
0
cs_MPi Messages postés 3877 Date d'inscription mardi 19 mars 2002 Statut Membre Dernière intervention 17 août 2018 23
9 sept. 2006 à 19:29
Après différents tests

- méthode Find

- Copie de formules et recherche des erreurs

- Copie des valeurs dans des tableaux et vérification de ceux-ci


La dernière méthode semble être la plus rapide, mais c'est long quand même.

Il y a une bonne différence entre travailler sous Excel directement et via VB.

Mon test consistait à vérifier deux onglets de 60000 lignes chacun


Pour accélérer la recherche, il faudrait que le tableau recherché
diminue à chaque item identique. Je sais comment ajouter des items
dynamiquement à un tableau (Redim Preserve), mais je ne vois pas
comment éliminer de façon rapide un item rendu inutile (?) La recherche
en serait accélérée pas mal.


Je cherche encore...

MPi
0
cs_MPi Messages postés 3877 Date d'inscription mardi 19 mars 2002 Statut Membre Dernière intervention 17 août 2018 23
9 sept. 2006 à 20:09
Bon ben la façon la plus rapide que j'ai trouvée est de copier les
nouvelles données à vérifier dans un tableau, de mettre les données
originales dans une String et d'utiliser Instr() Environ 4 à 5 minutes
pour vérifier 60000 données dans les 2 classeurs (Celeron 1.2 GHz)


Comme j'ai utilisé des chiffres pour créer mes données (plus rapide),
je dois modifier ces données en String, séparées par un point-virgule
pour bien identifier chaque valeur. Ce ne sera possiblement pas
nécessaire pour toi (?)


Private Sub Form_Load()

    Set xlApp = New Excel.Application

    Set xlBook1 = xlApp.Workbooks.Open(App.Path & "\Classeur1.xls")

    Set xlSheet1 = xlBook1.Sheets("Feuil1")  

    Set xlBook2 = xlApp.Workbooks.Open(App.Path & "\Classeur2.xls")

    Set xlSheet2 = xlBook2.Sheets("Feuil1")

End Sub


Private Sub Form_Unload(Cancel As Integer)

    xlApp.Quit

    Set xlBook1 = Nothing

    Set xlSheet1 = Nothing

    Set xlBook2 = Nothing

    Set xlSheet2 = Nothing

    Set xlApp = Nothing  

End Sub


Private Sub Command1_Click()

    Dim I As Long, nbLignes As Long, strTemp As String, strResult As String

    Dim Tablo2() As String

    Dim Temps As Single

   

    Temps = Timer  'pour calculer le temps

   

    'copier le "nouveau" classeur et mettre les données entre guillemets et ;

    nbLignes = xlSheet2.Cells.Find("*", xlSheet2.Range("A1"), , , xlByRows, xlPrevious).Row

    xlSheet2.Range("B2:B" & nbLignes).Copy

    strTemp = Clipboard.GetText

    strTemp = Replace(strTemp, Chr(10), "")

    strTemp = Replace(strTemp, Chr(13), Chr(34) & ";" & Chr(34))

    Tablo2 = Split(strTemp, ";")

    Clipboard.Clear

   

    'copier les données du classeur de base dans une chaîne

    strTemp = ""

    nbLignes = xlSheet1.Cells.Find("*", xlSheet1.Range("A1"), , , xlByRows, xlPrevious).Row

    xlSheet1.Range("A2:A" & nbLignes).Copy

    strTemp = Clipboard.GetText

    strTemp = Replace(strTemp, Chr(10), "")

    strTemp = Replace(strTemp, Chr(13), Chr(34) & ";" & Chr(34))

    Clipboard.Clear

    xlApp.Quit 'fermer l'application qui ne sert plus

   

    For I = 0 To UBound(Tablo2)

        Label3 = I & " sur " & UBound(Tablo2) ' pour voir le défilement

        DoEvents

        If InStr(1, strTemp, Tablo2(I)) = 0 Then  'donnée absente

           
strResult = strResult & Tablo2(I) & vbCrLf  'on la stocke

        End If

    Next

   

    If strResult <> "" Then

        MsgBox "Les recettes
suivantes sont dans Classeur2 mais pas dans Classeur1" & vbCrLf
& _

           
strResult & vbCrLf & vbCrLf & "trouvé en " & Timer -
Temps & " sec"

    End If

End Sub

MPi
0
AlexDam Messages postés 31 Date d'inscription mercredi 6 septembre 2006 Statut Membre Dernière intervention 10 octobre 2006
10 sept. 2006 à 16:45
    Oui en effet, je l'avais déclarer en integer :-/... Oui en effet je n'aurais pas besoin de les re -modifier en String.

Tu peux juste m'expliquer ces lignes?
    strTemp = Replace(strTemp, Chr(10), "")

    strTemp = Replace(strTemp, Chr(13), Chr(34) & ";" & Chr(34))

    Tablo2 = Split(strTemp, ";")

En fait t'as rentré desz séries de dix chiffre à chaque fois? Mes recettes ne sont souvent pas terminer par un . donc je vois pas trop comment savoir quelle est la fin.

J'avais fait un truc sumilaire au début. J'avais prix les données du premier fichier pour les mettres dans un tableau en éliminant les doublons. On doit arriver a diviser les recettes à verifier par 40 de cette maniere et je stockait les numeros de ligne aussi. J'avais un tableau pour les recettes et un pour les lignes ou elles étaient présentes.

Genre nameR()  et rowR()
          clafoutit         3;7;9
          tarete tatin      5;6
          etc...

Ouais c'est important que je note à quelles lignes sont les trucs a checker et je vois pas comment les chopper en fait avec le coup du... jai rien dit

Je vais garder ta méthode sur la fin je pense avec le coup de topper tout les trucs deja existant dans un chaine ça semble bien malin ça.

Et je vais refaire comme j'avais fait un tableau pour le nouveau classeur mais faut que je trouve un feinte pour a la fois eliminer les doublons et arriver a garder les numeros de lignes ou les recettes sont présentes.

Et ci au final le temps pue soit je lenvoi chier car faut le dire avec ses macros en 5 minutes c'est fait aussi... Hé mais attends si c'est fait en 5 minutes c'est bon... Jsui dans les temps... Sweet vais faire marcher tout ça au boulot demain.

P.S. Note que ça faisait deux jours que je cherchait sil y avait pas moyen de faire ça plus vite avec des copiers collers de vba pour que le traitement se fasse sous excel :x.
0
AlexDam Messages postés 31 Date d'inscription mercredi 6 septembre 2006 Statut Membre Dernière intervention 10 octobre 2006
10 sept. 2006 à 16:57
    Sinon oui pour la seconde partie, on mettre des ; n'est pas necessaire nan? Vu qu'on le laisera dans la chaine.

Sinon oui je vais faire comme ça pour la premiere phase:
Je vais lire à la main chaque donnée de ma colonne, à chaque ligne je mettrais dans un String temp=worksheet(i,2) , puis je testerais si temp est deja dans mon tableau. S'il n'y est pas je l'ajoute, sil y est déja j'ajoute juste le numéro de la ligne. Sinon je suis con j'ai oublier si les tableau à deux dimension existaient en VB (jvais verifier ça lol). Sinon oui, tu pense que chopper toutes les donnée une par une est moins efficient que ton GetText (dont j'ignorais l'existance [tu m'as appris un truc la{merci}]).
0
cs_MPi Messages postés 3877 Date d'inscription mardi 19 mars 2002 Statut Membre Dernière intervention 17 août 2018 23
11 sept. 2006 à 11:43
En faisant une copie d'une colonne de chiffres dans une String, on se retrouve avec ce genre de valeur

"1 2 3 4..." (les espaces étant des sauts de lignes (chr(10) & chr(13))

Pou fins de vérifications, je préférais

"1";"2";"3"...

Comme ça, chaque valeur est vraiment distincte

Instr() pourrait trouver la valeur 4 dans 14 ou 41, mais ne trouvera pas "4" dans "14"


C'est pourquoi je remplace les Chr(10) par rien ("" ou vbNullString)

et Chr(13) par un point-virgule entouré de 2 guillemets

En ajoutant le point-virgule, ça permet d'utiliser Split sur ce séparateur


J'avais commencé avec 2 tableaux que je vérifiais (double-boucle) et
j'ai trouvé plus rapide d'utiliser Instr(), donc 1 tableau et une String

J'ai aussi essayé en lisant les cellules directement plutôt que de les mettre dans un tableau et c'était plus lent (?)


Mais il y a sûrement possibilité de faire plus rapide...

MPi
0
AlexDam Messages postés 31 Date d'inscription mercredi 6 septembre 2006 Statut Membre Dernière intervention 10 octobre 2006
11 sept. 2006 à 16:27
    J'ai fini... enfin... on a fini lol. Ouais j'ai juste fais en sorte que le premier tableau n'ai pas de doublons. Comme ça:

Dim k As Integer
    For k = 0 To 3000
    namep(k) = ""
    rowp(k) = ""
    Next k
  
    a = 0
    i = 2
    Dim tempcell As String
    Print "aa"
    tempcell = eWorkSheet.Cells(i, 2)
    Print "a"
    While tempcell <> ""
    bool = False
    k = 0
                While k <3000 And bool False And namep(k) <> ""
            If tempcell = namep(k) Then
            bool = True
            rowp(k) = rowp(k) & ";" & i
            End If
            k = k + 1
            Wend
           
            If bool = False Then
            namep(a) = tempcell
            rowp(a) = i
            a = a + 1
            End If
           
           
    i = i + 1
    tempcell = eWorkSheet.Cells(i, 2)
    Wend

Et bon donc en supprimant tout les doublons je fais trois fois la recherche (trois colonne en fait ^^) et je fais un rapport dans un autre fichier excels des trucs a rajouter le tout en 4 minutes pour un fichier a checker de 60 000 row... autant dire que ça pete!
Donc voila jvoulais vous remercier tout les deux qui avez passer du temp a m'aider pour ma merde. Donc voila /bow ^.~ J'y serais peut etre aussi arriver sans vous mais vous m'avez aider a gagner pas mal de temps.

A plouche sur le forum (pas forcement en tant que mendiant comme cette fois :-))
0
Rejoignez-nous