Temps d'exécution tableau contre For Each

Calvus

XLDnaute Barbatruc
Bonsoir le forum,

Je lis partout, ici et ailleurs, , et je l'ai également constaté à mainte reprises que les variables tableaux sont extrêmement plus rapides que les boucles For Each.

Or, dans un fichier contenant un peu plus de 1000 lignes, je me suis aperçu que c'était le contraire !

J'ai fait un fichier exemple, avec les 2 codes, d'une structure similaire à mon fichier original.

Code variable tableau : temps d'exécution 0,078 secondes
Code boucle for Each : temps d'exécution 0,062 secondes
(Le traitement se fait sur une partie des lignes seulement, et rarement plus de 120)

Alors, à moins que mon code ne soit pas bon, auriez vous une explication logique à cela ? Car cela ne devrait pas se passer ainsi...

Je précise que sur mon fichier qui fait près de 6 Mo, le 1er test met 1,20 secondes, contre 0,90 à peine pour le second, qui est censé être plus lent...

Bonne soirée
 

Pièces jointes

  • Tableau contre For Each.xlsm
    49.8 KB · Affichages: 41
Dernière édition:

Lone-wolf

XLDnaute Barbatruc
Bonsoir Calvus :)

Attention, tout dépend aussi comment le code à été écrit. Mis à part les tableaux, je préfère de loins les boucles for i - for x etc.

Le boucles for each vont bien pour certains cas, par exemple for each ctrl in me.controls, for each ws in worksheets, for each cel in plage (mais quelle soie de petite taille).

Mais lors de plusieures boucles, mieux vaut , soit les tabeaux, soit les for i.
 

Lone-wolf

XLDnaute Barbatruc
Bonjour Calvus :)

Encore une fois, tout dépend de comment on écrit le code. Je ne sais pas si tu as eu l'occasion de lire certaines discussions à propos du remplissage d'un tableau. Pour te donner une idée, vas sur le site de Jacques Boisgontier, et tu comprendra pourquoi avec une méthode on obtiens un résultat, et avec une autre méthode un résultat différent.

EDIT: Voici quelques exemples de Jacques

VB:
Sub TransfertChampTableau2D()
t = Timer
a = [A1:C20000].Value
MsgBox Timer - t    ' 0,015 sec
MsgBox LBound(a, 1) & " à " & UBound(a, 1)   ' 1 à 20000
MsgBox LBound(a, 2) & " à " & UBound(a, 2)   ' 1 à 3
End Sub

Sub TransfertChamp1ColonneTableau1D()
  t = Timer()
  a = Application.Transpose([a1:A20000]) ' tableau à 1 dimension (1 à 20000)
  MsgBox Timer() - t    ' 0,015 sec
  MsgBox LBound(a) & " à " & UBound(a)
End Sub

Sub transfertTableau2DChamp()
  Dim a()
  Nlig = 20000
  Ncol = 3
  ReDim a(1 To Nlig, 1 To Ncol)
  For L = 1 To Nlig
    For C = 1 To Ncol
      a(L, C) = L * C
    Next C
  Next L
  t = Timer
  [A1].Resize(UBound(a, 1), UBound(a, 2)) = a
  MsgBox Timer - t   ' 0,04 sec
End Sub

Sub transfertTableau1DChamp()
  Dim a()
  n = 20000
  ReDim a(1 To n)
  For i = 1 To 20000
    a(i) = i
  Next i
  t = Timer
  [A1].Resize(UBound(a)) = Application.Transpose(a)
  MsgBox Timer - t   ' 0,01 sec
End Sub

Sub TransfertTableauChampAvecBoucle()
  Application.ScreenUpdating = False
  n = 20000
  Dim a()
  ReDim a(1 To n)
  For i = 1 To n: a(i) = i: Next i
  t = Timer
  For i = 1 To n: Cells(i, 1) = a(i): Next
  MsgBox Timer - t '1,25 sec
End Sub

Sub TransfertChampTableau1DAvecBoucle()
  n = 20000
  Dim a()
  ReDim a(1 To n)
  t = Timer
  For i = 1 To n: a(i) = Cells(i, 1): Next
  MsgBox Timer - t ' 0,20 sec
End Sub

Comme tu peux le voir, les 6 macros sont écrites de manières différentes, mais elles font la même chose. Et peut être aussi que la puissance ou la rapidité du PC joue un rôle.
 
Dernière édition:

Lone-wolf

XLDnaute Barbatruc
Bonjour Cath :), et le Forum (I'm Sorry :oops:) :)

@ Calvus: en pj un classeur exemple avec For each - tablo - For Lig-Col, 80000 lignes 14 colonnes.

Et là, je pense qu'il n'y a pas photo. ;)
 

Pièces jointes

  • Classeur1.xlsm
    21.9 KB · Affichages: 27

cathodique

XLDnaute Barbatruc
Lone-wolf;), Calvus:) et toute la Cie:D,

Là aussi, y a pas 2 photos. Il n'est pas de moi (je n'ai pris qu'une partie, celle qui traite ton cas).
Si ça t'intéresse je te fais parvenir le fichier complet (un bon tuto, en complément à ceux de Boisgontier).
 

Pièces jointes

  • Traitement Array_ForEach.xlsm
    47.8 KB · Affichages: 31

JBARBE

XLDnaute Barbatruc
Bonjour à tous,
Je suis d'accord avec Lone-wolf qui dit :
tout dépend aussi comment le code à été écrit.
Certes je ne suis pas un pro du for eah ( j'utilise souvent : ( for each cel in plage) mais l’argument suivant de Lone-Wolf est vrai :
Les boucles for each vont bien pour certains cas, par exemple for each ctrl in me.controls, for each ws in worksheets, for each cel in plage (mais quelle soie de petite taille).
Tout les tests le démontre ( quelques exemples en +!
ici test court :(3,83 s)
Code:
Option Explicit
' Test plus court
Sub test1()
Dim Montab As Variant, cmpt1 As Long, cmpt2 As Long, t As String
t = Timer
Montab = Range("A1:J65535").Value
For cmpt1 = LBound(Montab, 1) To UBound(Montab, 1)
For cmpt2 = LBound(Montab, 2) To UBound(Montab, 2)
Montab(cmpt1, cmpt2) = Montab(cmpt1, cmpt2) * 2 + 3
Next cmpt2
Next cmpt1
Range("A1:J65535").Value = Montab
MsgBox Timer - t
End Sub

ici test long :(50,29 s)
Code:
'Test trés long
Sub test2()
Dim ObjCell As Range, t As String
t = Timer
For Each ObjCell In Range("A1:J65535").Cells
ObjCell.Value = ObjCell.Value * 2 + 3
Next
MsgBox Timer - t
End Sub

Bonne journée à tous !
 
Dernière édition:

Lone-wolf

XLDnaute Barbatruc
Bonjour JBARBE(sans la moustache LOL ;):D) :)

Merci beaucoup pour le soutien(mais pas avec gorge LOL :D) :)

Et sur l'exemple de JBARBE

VB:
' Test plus court
Sub test1()

    With Application
        .EnableEvents = False
        .ScreenUpdating = False
        .Calculation = xlCalculationManual
    End With

    t = Timer
    'Cellules pré-remplies
    Montab = Range("a1:x80000").Value

    For cmpt1 = LBound(Montab, 1) To UBound(Montab, 1)
        For cmpt2 = LBound(Montab, 2) To UBound(Montab, 2)
            Montab(cmpt1, cmpt2) = Montab(cmpt1, cmpt2) * 2 + 3
        Next cmpt2
    Next cmpt1

    Range("a1:x80000").Value = Montab
    MsgBox Timer - t

    With Application
        .EnableEvents = True
        .ScreenUpdating = True
        .Calculation = xlCalculationAutomatic
    End With
End Sub

Temps d'exécution 7.10 sec . Sans pré-remplissage 6.63 sec
 
Dernière édition:

Calvus

XLDnaute Barbatruc
Bonsoir à tous,

Merci de vos réponses et de vos exemples, mais ça ne fait que confirmer ce que je disais, à savoir que les tableaux étaient plus rapides.
Mais alors qu'en est il de mon exemple ? Mon code est mal écrit ? comme vous semblez le suggérer. Mais alors où ? quel est le problème ? Seulement parce que je ne traite que 43 lignes comme le dit Cathodique ?
Il y aurait donc des cas, (celui-ci) où il vaut mieux utiliser le for each.
Si ça t'intéresse je te fais parvenir le fichier complet (un bon tuto, en complément à ceux de Boisgontier).
Je veux bien, merci.

Bonne soirée.
 

Discussions similaires

Réponses
3
Affichages
287
Réponses
2
Affichages
398

Statistiques des forums

Discussions
312 203
Messages
2 086 197
Membres
103 153
dernier inscrit
SamirN