Code VBA qui peine...

J

JJ1

Guest
Bonjour,
J'ai quelques lignes de code qui fonctionnent mais très lentement...
Auriez-vous une idée de turbo !!

Dim cel As Range
Dim a, b, c, d, e, f As Integer
For a = 1 To 50
For b = a + 1 To 50
For c = b + 1 To 50
For d = c + 1 To 50
For e = d + 1 To 50
For f = e + 1 To 50
Range("G1") = a
Range("H1") = b
Range("I1") = c
Range("J1") = d
Range("K1") = e
Range("L1") = f

If [R1] = 0 Then [G1:L1].Copy Range("Y" & Cells(Rows.Count, 28).End(xlUp).Row + 1)' copie de la série
Next
Next
Next
Next
Next
Next



merci beaucoup.

Bon samedi.
 

laurent950

XLDnaute Barbatruc
Re : Code VBA qui peine...

Bonjour jj1,
J’ai fait un test pour comprendre les limites d’Excel. J’ai crée une macro avec deux tableaux
1 Tableau de 10 000 000 Lignes x 6 colonnes
Et un autres de
1 Tableau de 1 048 576 Lignes x 6 colonnes
J’ai commenté la macro et le processus de remplissage de la feuille Excel (cela Fonctionne !! je suis surpris mais ca marche)
Sur mon ordinateur (Excel ne répond pas) mais en fait il tourne.
La macro est jointe le temps de calcul est le suivant =
Bonjour jjl,
J’ai fait un test pour comprendre les limites d’Excel. J’ai crée une macro avec deux tableaux
1 Tableau de 10 000 000 Lignes x 6 colonnes
Et un autres de
1 Tableau de 1 048 576 Lignes x 6 colonnes
J’ai commenté la macro et le processus de remplissage de la feuille Excel (cela Fonctionne !! je suis surpris mais ca marche)
Sur mon ordinateur (Excel ne répond pas) mais en fait il tourne.
La macro est jointe le temps de calcul est le suivant = est environ 3 Minutes

Code :

VB:
Sub testTransfertTableau()

Application.ScreenUpdating = False
Cells(1, 26) = "Depart : " & Time

' Tableau a 2 dimension
' Lignes = 10 000 000
' Colonne = 6
Dim Tab1() As Double
ReDim Tab1(1 To 10000000, 1 To 6) ' 10 000 0000 Lignes x 6 Colonnes

' Tableau a 2 dimension
' Ligne = 1 048 576
' Colonne = 6
Dim Tab2() As Double
ReDim Tab2(1 To 1048576, 1 To 6) '1 048 576  Lignes x 6 Colonnes

' Remplissage du tableau a 2 dimension pour test de capacité
' soit 60 000 000 de case remplis
For i = 1 To UBound(Tab1)
Tab1(i, 1) = i
Tab1(i, 2) = Tab1(i, 1) + i   ' Ici ce sont des valeurs Test de remplissage
Tab1(i, 3) = Tab1(i, 2) + i   ' Suite ne pas en tenir compte c'est juste
Tab1(i, 4) = Tab1(i, 3) + i   ' pour remplir les 10 000 000 Ligne x 6 Colonne
Tab1(i, 5) = Tab1(i, 4) + i
Tab1(i, 6) = Tab1(i, 5) + i
Next i

' Transfert des données dans le deuxiéme tableau
' dimensionné en fonction du nombres maxi de ligne Excel (1 048 576)
col = 1
' Position dans Excel pour collage en bloque de :
' Cells(1, col).Resize(UBound(Tab2, 1), UBound(Tab2, 2)) = Tab2

' For i = 1 To 3 (Je transfert que 3 fois 1 048 576 lignes pour les
' 3 premier tours de boucle
For i = 1 To 3
For j = 1 To 1048576      ' Ici le nombre de ligne maxi = Ligne excel
cpt = cpt + 1
Tab2(j, 1) = Tab1(cpt, 1) ' Ici Tab1 (10 000 000 ligne) cpt = position Ligne
Tab2(j, 2) = Tab1(cpt, 2) ' suite dans ce tableau (Voir cpt = cpt + 1)
Tab2(j, 3) = Tab1(cpt, 3) ' C'est le compteur après la boucle For
Tab2(j, 4) = Tab1(cpt, 4)
Tab2(j, 5) = Tab1(cpt, 5)
Tab2(j, 6) = Tab1(cpt, 6)
Next j
' Colle les premieres valeurs du tableau de 10 000 OOO de lignes
' Soit d'un bloque les 1 048 576 lignes x 6 colonnes
Cells(1, col).Resize(UBound(Tab2, 1), UBound(Tab2, 2)) = Tab2
' Nouvelle posiont dans la feuille Excel soit colonne 1 + 7
' Pour le second tours de boucle soit Colonne 8
' Etc. pour le troisieme tours de boucle Etc.
col = col + 7
Next i

Cells(3, 26) = "Depart : " & Time

Erase Tab1, Tab2
Application.ScreenUpdating = True
End Sub

Ps : Il faudrait 18 700 Tableaux comme les 3 que j'ai fait pour les combinaisons a 6
C'est surement réalisable mais il y a quelque calcul a faire avant, c'est un peu long quand
Même si quelqu'un a une idée ?

L'astuce est cependant pas mal je trouve. A développer encore.

Pour info l'enregistrement de ce fichier est de 123 945 Ko (Juste avec 3 Tableaux dans restitué dans excel)

Pour 12 103 014 pour 5 nombres. (l'ordre ne comptant pas) il faudrait répartir les tableaux sur différent classeur car il y a une limite avec Excel, mais j'ai prsque trouvé la méthode, Peut être se servir d'acces comme Stokage ?? pour des très grandes quantitées.

Si vous avez une idée avec cette exemple (il suffit de remplacer les valeur test par vos valuer de combinaison) mais je suis a 10 000 000 de ligne

Avec 12 103 014 pour voir si sa passe ?? Il faut définir les support pour toutes ces combinaisons stocké dans ce tableau.

Remplacer l'instruction :
ReDim Tab1(1 To 10000000, 1 To 6) ' 10 000 0000 Lignes x 6 Colonnes
Par
ReDim Tab1(1 To 12103014, 1 To 6) ' 12 103 014 Lignes x 6 Colonnes

Je finirais plus tard mais une belle avancer enfin je pense?

Laurent
 

Pièces jointes

  • VariableTableau10000000Lignes.xlsm
    18 KB · Affichages: 24
Dernière édition:

laurent950

XLDnaute Barbatruc
Re : Code VBA qui peine...

Suite pour JJ1,

Le code avec vos données :

VB:
Sub MacroCode_JJ1()
Application.ScreenUpdating = False
Cells(1, 25) = "Depart Macro : " & Time

' Compteur
Dim cpt As Double

' Tableau a 2 dimension
' Lignes = 10 000 000
' Colonne = 6
Dim Tab1() As Double
'ReDim Tab1(1 To 10000000, 1 To 6) '1048576  // 12 103 014
'ReDim Tab1(1 To 12103014, 1 To 6) '1048576  // 12 103 014
ReDim Tab1(1 To 12103014, 1 To 5) '1048576  // 12 103 014


' Tableau a 2 dimension
' Ligne = 1 048 576
' Colonne = 6
Dim Tab2() As Double
'ReDim Tab2(1 To 1048576, 1 To 6) '1048576
ReDim Tab2(1 To 1048576, 1 To 5) '1048576

Dim a As Integer
Dim b As Integer
Dim c As Integer
Dim d As Integer
Dim e As Integer
'Dim f As Integer
For a = 1 To 70
    For b = a + 1 To 70
        For c = b + 1 To 70
        Application.Wait (Now + TimeValue("0:00:01"))
            For d = c + 1 To 70
            'Application.Wait (Now + TimeValue("0:00:01"))
                For e = d + 1 To 70
                    'For f = e + 1 To 70
Application.StatusBar = _
"For pos a = " & a & " (soit 70 reste " & 70 - a & " )" & " / " & _
"For pos b = " & b & " (soit 70 reste " & 70 - b & " )" & " / " & _
"For pos c = " & c & " (soit 70 reste " & 70 - c & " )" & " / " & _
"For pos d = " & d & " (soit 70 reste " & 70 - d & " )" & " / " & _
"For pos e = " & e & " (soit 70 reste " & 70 - e & " )" & " / " 

' "For pos f = " & f & " (soit 70 reste " & 70 - f & " )" & " / "
                        
                         cpt = cpt + 1
                        'CodeJJ1 Tab1, cpt, a, b, c, d, e, f
                         CodeJJ1 Tab1, cpt, a, b, c, d, e
                        
'Range("G1") = a
'Range("H1") = b
'Range("I1") = c
'Range("J1") = d
'Range("K1") = e
'Range("L1") = f
'If [R1] = 0 Then [G1:L1].Copy Range("Y" & Cells(Rows.Count, 28).End(xlUp).Row + 1) ' mis un exemple nb.si pour test de copie si =0
                    'Next f
                Next e
            Next d
        Next c
    Next b
Next a

Cells(3, 25) = "Fin de mise en mémoire Tab1 : " & Time
' Remise a Zero cpt
cpt = Empty

' Code pour copier les valeurs dans Excel
' Juste 3 Tableaux pour l'instant avec vos codes
' A définir pour la suite
' La macro va stoké les 12 103 014 lignes x 5 colonnes
' pour les 5 combinaisons
' le Tableau = Tab1 contient (12 103 014 x 5) = Nombre de case Total

' **************************************************************************************

' Ci dessous Code pour passage des données en mémoire Tab1 vers Excel avec un Tableaux
' Intermédiaire Tab2 de (1 048 576 x 5 ) = Nombre Total de case

' Pour des questions de mémoire de la feuille même excel je copie que les
' 3 x 1 048 576 lignes du tableau Tab1 vers Excel (soit 3 Tableaux)

col = 1
' Position dans Excel pour collage en bloque de :
' Cells(1, col).Resize(UBound(Tab2, 1), UBound(Tab2, 2)) = Tab2

' For i = 1 To 3 (Je transfert que 3 fois 1 048 576 lignes pour les
' 3 premier tours de boucle
For i = 1 To 3
For j = 1 To 1048576      ' Ici le nombre de ligne maxi = Ligne excel
cpt = cpt + 1
Tab2(j, 1) = Tab1(cpt, 1) ' Ici Tab1 (10 000 000 ligne) cpt = position Ligne
Tab2(j, 2) = Tab1(cpt, 2) ' suite dans ce tableau (Voir cpt = cpt + 1)
Tab2(j, 3) = Tab1(cpt, 3) ' C'est le compteur après la boucle For
Tab2(j, 4) = Tab1(cpt, 4)
Tab2(j, 5) = Tab1(cpt, 5)
'Tab2(j, 6) = Tab1(cpt, 6)
Next j
' Colle les premieres valeurs du tableau de 10 000 OOO de lignes
' Soit d'un bloque les 1 048 576 lignes x 6 colonnes
Cells(1, col).Resize(UBound(Tab2, 1), UBound(Tab2, 2)) = Tab2
' Nouvelle posiont dans la feuille Excel soit colonne 1 + 7
' Pour le second tours de boucle soit Colonne 8
' Etc. pour le troisieme tours de boucle Etc.
'col = col + 7
'col = col + 6
Next i

Cells(5, 25) = "Fin Macro : " & Time

Erase Tab1, Tab2
Application.ScreenUpdating = True

End Sub

VB:
'Function CodeJJ1(Tab1, cpt, a, b, c, d, e, f)
Function CodeJJ1(Tab1, cpt, a, b, c, d, e)

' Remplissage du tableau a 2 dimension pour test de capacité
' soit 60 000 000 de case remplis
'For i = 1 To UBound(Tab1)
Tab1(cpt, 1) = a 'i
Tab1(cpt, 2) = b 'Tab1(i, 1) + i   ' Ici ce sont des valeurs Test de remplissage
Tab1(cpt, 3) = c ' Tab1(i, 2) + i   ' Suite ne pas en tenir compte c'est juste
Tab1(cpt, 4) = d 'Tab1(i, 3) + i   ' pour remplir les 10 000 000 Ligne x 6 Colonne
Tab1(cpt, 5) = e 'Tab1(i, 4) + i
'Tab1(cpt, 6) = f 'Tab1(i, 5) + i
'Next i

'CodeJJ1 = Tab1

End Function

Ps : Je joint le fichier Excel avec le code, il faut encore afiné mais c'est presque la fin.

Laurent
 

Pièces jointes

  • JJ1codeFinalVariableTableauSuper.xlsm
    21.7 KB · Affichages: 22
Dernière édition:
J

JJ1

Guest
Re : Code VBA qui peine...

Bonjour Laurent, le Forum
Quel travail! merci beaucoup, ce résultat permettra aussi de connaître les limites d'un tablo.

Hier soir, j'avais commencé à modifier les valeurs du code pour passer à 5 nombres allant de 1 à 10 (pour tester)

Le résultat était toutes les combinaisons de 1 à 10 sur 5 nombres en colonne Y.
J'ai l'impression que les combinaisons ne "passaient" pas par G1:K1 afin d'être testées par la formule pour le résultat à 0 ?

ici:
'Range("G1") = a
T1(1, 1) = a
'Range("H1") = b
T1(1, 2) = b
'Range("I1") = c
T1(1, 3) = c ''
'Range("J1") = d
T1(1, 4) = d
'Range("K1") = e
T1(1, 5) = e
'Range("L1") = f
T1(1, 6) = f

T(1,1) c'est bien A1 et non G1 ?
je me trompe peut être?


Merci encore et bonne journée.
 

laurent950

XLDnaute Barbatruc
Re : Code VBA qui peine...

Suite,

'Range("G1") = a correspond à T1(1, 1) = a
J'ai travaillé sur une variante mais il y a eu une insufisancemémoire est j'ai tous perdu je recommecerais demain.

Je penser faire deux tableaux soit

1 tableaux 1 qui remplis votre teste avec vos boucle (for a for b etc.)

si la condiction de la cellule est respecter votre :

'If [R1] = 0 Then [G1:L1].Copy Range("Y" & Cells(Rows.Count, 28).End(xlUp).Row + 1) '

je transfert la valeur dans un tableau 2

quand le nombre de ligne est atteint :

je copie le tableau 2 dans excel

ensuite je repart sur le tableau 1 et 2 (que je vide avant) puis repart a la case du tableau 1

et recommence autant de fois que possible :

je ferais l'exemple avec peux de case pour voir (mais la vitesse pourrais etre plus rapide encore)

laurent
 

laurent950

XLDnaute Barbatruc
Re : Code VBA qui peine...

Bonjour jj1,

J'ai finis le code avec 5 combinaisons.

La condition If est desactivé pour toute les combinaisons ( a voir par la suite) facillement adaptable.

NOTA : (Excel ne répond pas) ===>>> Mais aprés test cela fonctionne est j'ai mis en feuille 2 le temps de départ et celuis de fin.

c'est ULTRA RAPIDE compte tenu des 12 103 014 lignes sur pour 5 cases a traité.

VB:
Option Explicit

Sub MacroCode_JJ1()

Application.ScreenUpdating = False
Worksheets("Feuil2").Cells(1, 1) = "Depart Macro : " & Time

' Compteur
Dim cpt1 As Double
Dim cpt2 As Double
Dim cpt3 As Double
Dim val As Integer
Dim col As Integer
Dim resTest As Double
cpt3 = 1
col = 1

'Dim Tab1() As Double
Dim x As Double
Dim y As Double
x = 12103014   ' lignes max de données possible
y = Round((12103014 / 1048576))
'ReDim Tab1(1 To y)

Dim Tab2() As Double
ReDim Tab2(1 To 1048576, 1 To 5)

Dim Tab3() As Double
ReDim Tab3(1 To 1048576, 1 To 5)

Dim a As Integer
Dim b As Integer
Dim c As Integer
Dim d As Integer
Dim e As Integer
'Dim f As Integer
For a = 1 To 70
    For b = a + 1 To 70
        For c = b + 1 To 70
        'Application.Wait (Now + TimeValue("0:00:01"))
            For d = c + 1 To 70
                For e = d + 1 To 70
                        Application.StatusBar = "For pos a = " & a & " (soit 70 reste " & 70 - a & " )" & " / " & _
                        "For pos b = " & b & " (soit 70 reste " & 70 - b & " )" & " / " & _
                        "For pos c = " & c & " (soit 70 reste " & 70 - c & " )" & " / " & _
                        "For pos d = " & d & " (soit 70 reste " & 70 - d & " )" & " / " & _
                        "For pos e = " & e & " (soit 70 reste " & 70 - e & " )" & " / "
                        
                        If cpt2 = 1048576 Then
                            cpt2 = Empty
                        End If
                        
                        cpt2 = cpt2 + 1
                       'Fonction
                        resTest = TestR1(Tab2, a, b, c, d, e, cpt2)
                        
'If resTest = 0 Then
cpt3 = TransfertCondition(Tab2, Tab3, cpt2, cpt3, col)
'End If

If cpt3 > 1048576 Then
col = TransfertExcel(Tab3, col)
cpt3 = 1
End If
                
                Next e
            Next d
        Next c
    Next b
Next a

Worksheets("Feuil2").Cells(1, 3) = "Fin Macro : " & Time

'Erase Tab1, Tab2
Erase Tab2, Tab2
Application.ScreenUpdating = True
Application.StatusBar = False

End Sub

Public Function TestR1(Tab2, a, b, c, d, e, cpt2)

Dim resTest As Double

Tab2(cpt2, 1) = a
Tab2(cpt2, 2) = b
Tab2(cpt2, 3) = c
Tab2(cpt2, 4) = d
Tab2(cpt2, 5) = e

resTest = Tab2(cpt2, 1) & Tab2(cpt2, 2) & Tab2(cpt2, 3) & Tab2(cpt2, 4) & Tab2(cpt2, 5)

TestR1 = resTest

End Function

Function TransfertCondition(Tab2, Tab3, cpt2, cpt3, col)

Tab3(cpt3, 1) = Tab2(cpt2, 1)
Tab3(cpt3, 2) = Tab2(cpt2, 2)
Tab3(cpt3, 3) = Tab2(cpt2, 3)
Tab3(cpt3, 4) = Tab2(cpt2, 4)
Tab3(cpt3, 5) = Tab2(cpt2, 5)
cpt3 = cpt3 + 1

TransfertCondition = cpt3

End Function

Function TransfertExcel(Tab3, col)

Cells(1, col).Resize(UBound(Tab3, 1), UBound(Tab3, 2)) = Tab3
col = col + 6
TransfertExcel = col
End Function

Je pense que l'on peux encore rendre le programme plus souple, je vais regarder les module de classe et j'ai tester un variabe de type mais pas ici a voir encore mais trs interressant comme test.

Le compteur est desactivé de temps 1 seconde ==>> Application.Wait (Now + TimeValue("0:00:01")) mais en une seconde cela fait peut etre 25 000 tours de boucles / second environ ? !!! a caculer avec le temps de départ et de fin en feuille deux

au plaisir de lir vos commentaire, je vous join le fichier excel

laurent
 

Pièces jointes

  • JJ1codeFinalVariableTableauTypeSuper.xlsm
    22 KB · Affichages: 28
Dernière édition:
J

JJ1

Guest
Re : Code VBA qui peine...

Bonjour Laurent,

Merci beaucoup pour ce travail de recherche.
Déjà avec 5 nombres c'est suffisant, je vais tester ce we et je te dirai le temps d'exécution et le résultat.

Merci beaucoup et bonne journée.
 

laurent950

XLDnaute Barbatruc
Re : Code VBA qui peine...

Bonjour jj1,

Aprés test conluant malgrés (Excel ne répond pas) l'explication c'est que a vitesse est trop importante pour excel mais l'ordinateur gére est le resultat est la.

1945 en seconde (Temps complet de l'exécution)
soit
32,42 en minutes
6222 Nombre de tours de boucles par seconde en moyenne

Vous connaissez les Modules de Classe ? moi je ne suis pas encore arrivée totalement a maitriser les tableaux par module de classe

par contre j'ai crée un tableau par variable Type. est cela fonctionne mais le tableau ne peut pas dépasser les 64 ko et il y a aussi d'autre probléme liée au envois vers une fonction.

Je peux vous joindre l'exemple si vous connaissais les tableaux un peux évolué.

Laurent
 

Dranreb

XLDnaute Barbatruc
Re : Code VBA qui peine...

Bonjour
Vous connaissez les Modules de Classe ?
Oui, très bien.
moi je ne suis pas encore arrivée totalement a maitriser les tableaux par module de classe
Je ne comprend absolument pas ce que ça veut dire. Je vous ai déjà dit, dans une autre discussion à laquelle vous n'avez pas encore répondu, qu'un tableau dans un module de classe s'utilise comme un dans autre module. La seule restriction c'est qu'il ne peut pas y être déclaré Public de façon à en constituer une propriété.
À +
 
J

JJ1

Guest
Re : Code VBA qui peine...

Bonjour Laurent, Dranreb

Merci pour ce code. J'avais testé mercredi soir mais j'avais un écran "pale"
pourrais tu me dire les limites (nb de 1 à ? et le nb de nb dans la combinaisons 1 à ? ) ex 5 nombres de 1 à 70

merci
Bon samedi
 

Statistiques des forums

Discussions
313 770
Messages
2 102 235
Membres
108 181
dernier inscrit
Chr1sD