OVH Cloud OVH Cloud

Sub très lente - comment optimiser

13 réponses
Avatar
J
Bonjour à tous
Dans un fichier d'une soixantaine de feuilles je récupère quelques données sur
chaque feuille que je colle dans une feuille appelée "Etat".
Avant optimisation ma sub tournait en 45 secondes, après en 35, mais c'est bien
long :-[
Quelqu'un aurait une idée??
merci
J@@ (Je n'aurai pas accès au forum pendant les 18 prochaines heures, merci
d'être patient pour le retour)

'******
Sub RecupDonnees()
Dim Feuille As Worksheet
Dim ActivationEvents As Long
Dim ModeRecalcul As Long

Sheets("Etat").Select
ActiveSheet.Unprotect
Range("B5:N58").ClearContents

Application.ScreenUpdating = False
ModeRecalcul = Application.Calculation
Application.Calculation = xlCalculationManual
ActivationEvents = Application.EnableEvents
Application.EnableEvents = False

For Each Feuille In ActiveWorkbook.Worksheets
If Feuille.Name <> "ALIRE" _
And Feuille.Name <> "Etat" Then
With Feuille
Worksheets("Etat").Range("B100").End(xlUp)(2).Value = .Name
Worksheets("Etat").Range("C100").End(xlUp)(2).Value = .[B27]
Worksheets("Etat").Range("D100").End(xlUp)(2).Value = .[B29]
Worksheets("Etat").Range("E100").End(xlUp)(2).Value = .[B28]
Worksheets("Etat").Range("F100").End(xlUp)(2).Value = .[B31]
Worksheets("Etat").Range("G100").End(xlUp)(2).Value = .[C27]
Worksheets("Etat").Range("H100").End(xlUp)(2).Value = .[C29]
Worksheets("Etat").Range("I100").End(xlUp)(2).Value = .[C28]
Worksheets("Etat").Range("J100").End(xlUp)(2).Value = .[C33]
Worksheets("Etat").Range("K100").End(xlUp)(2).Value = .[D27]
Worksheets("Etat").Range("L100").End(xlUp)(2).Value = .[D29]
Worksheets("Etat").Range("M100").End(xlUp)(2).Value = .[D28]
Worksheets("Etat").Range("N100").End(xlUp)(2).Value = .[D33]
End With
End If
Next Feuille

Application.EnableEvents = ActivationEvents
Application.Calculation = ModeRecalcul

ActiveSheet.Protect
End Sub
'******

3 réponses

1 2
Avatar
J
Bonjour jps
Déjà levé ? ;-))
C'est l'heure de la traite? ;-)
N'empêche que suite à ce fil, je vais devoir changer mes lunettes en peau de
saucisson, quand tu penses que je philosophais hardiment sur les fines modifs
proposées par MichDenis, alors que, sollicitant rageusement l'énorme bouton qui
occupe près de 4/5 de mon écran, je lançais une proc non modifiée!!!
Amicalement
@+
J@@

jps wrote:
:-)))
et c'est en scudant les pauv' vieux qu'on devient scuderon
jps

"J@@"
Bonjour MichDenis
J'ai fait une petite modif car tout se copiait sur la même ligne.
Voici le résultat, qui fonctionne, mais si le code est plus agréable à
lire, le gain de temps n'est pas net. D'un autre côté récupérer 600
données en 13 secondes, faut pas se plaindre que la mariée est trop belle
;-)
Faudra que je vois au travail sur mon ordi à vapeur ce que cela donne.
Encore merci
Comme (ne) dirait (pas) JPS, c'est en manipulant (du code) qu'on devient
manipuleron.
@+
J@@

'****
Private Sub CommandButton1_Click()
Dim Feuille As Worksheet
Dim Sh As Worksheet
Dim Ligne As Long
Set Sh = Worksheets("Etat")
Sh.Select
' ActiveSheet.Unprotect
Range("B5:N60").ClearContents
Ligne = Sh.Range("B100").End(xlUp)(0).Row

'Application.ScreenUpdating = False
'ModeRecalcul = Application.Calculation
Application.Calculation = xlCalculationManual
ActivationEvents = Application.EnableEvents
Application.EnableEvents = False

For Each Feuille In ActiveWorkbook.Worksheets
Ligne = Ligne + 1 ''''''''la modif
If Feuille.Name <> "ALIRE" _
And Feuille.Name <> "Etat" Then
With Feuille
Sh.Range("B" & Ligne) = .Name
Sh.Range("C" & Ligne) = .Range("B27")
Sh.Range("D" & Ligne) = .Range("B29")
'''''etc etc
End With
End If
Next Feuille

Application.EnableEvents = ActivationEvents
'Application.Calculation = ModeRecalcul
Application.Calculation = xlCalculationAutomatic

Selection.SpecialCells(xlCellTypeConstants, 16).ClearContents
' ActiveSheet.Protect
Range("a3").Select
End Sub
'****

MichDenis wrote:
Tu remplaces cette ligne de code :

Ligne = Sh.Range("B100").End(xlUp)(2).Value

Par
Ligne = Sh.Range("B100").End(xlUp)(2).Row

ça bloque sur cette ligne :
Sh.Range("B" & Ligne) = .Name

Par la variable Ligne = 0 et que dans excel
il n'y a aucune ligne portant le numéro 0

"J@@" voici le code, et j'ai une erreur 1004 sur la ligne
Sh.Range("B" & Ligne) = .Name

'****
Sub RecupDonnees()
Dim Feuille As Worksheet
Dim Sh As Worksheet
Dim Ligne As Long
Set Sh = Worksheets("Etat")
Ligne = Sh.Range("B100").End(xlUp)(2).Value
Sh.Select
ActiveSheet.Unprotect
Range("B5:N58").ClearContents

Application.ScreenUpdating = False
ModeRecalcul = Application.Calculation
Application.Calculation = xlCalculationManual
ActivationEvents = Application.EnableEvents
Application.EnableEvents = False

For Each Feuille In ActiveWorkbook.Worksheets
If Feuille.Name <> "ALIRE" _
And Feuille.Name <> "Etat" Then
With Feuille
Sh.Range("B" & Ligne) = .Name
Sh.Range("C" & Ligne) = .Range("B27")
Sh.Range("D" & Ligne) = .Range("B29")
''''etc
End With
End If
Next Feuille

Application.EnableEvents = ActivationEvents
Application.Calculation = ModeRecalcul

ActiveSheet.Protect
End Sub
'***

MichDenis wrote:
3 suggestions :
A )
Cette syntaxe est supérieur en rapidité à ceci :
..[B27] -> tu devrais utiliser ce type de syntaxe .Range("B27")

B ) Si tes enregistrements ont lieu sur la même ligne pour tous les
éléments d'une même boucle, pourquoi ne pas utiliser une variable
au lieu de réévaluer la cellule suivante disponible sur la colonne

Dim Ligne as Long
Ligne = Worksheets("Etat").Range("B100").End(xlUp)(2).Value
Et pour tes écritures dans la boucle pour chacun des items :
Worksheets("Etat").Range("B" & ligne) = .Name

C ) Remplace Worksheets("Etat"). par une variable
dim Sh as Worksheet
Set Sh = Worksheets("Etat")
Et dans ton code, tu remplaces ceci
Worksheets("Etat").Range("B100").End(xlUp)(2).Value = .Name
Par
Sh.Range("B" & ligne) = .Name










Avatar
FxM
Bonjour,

Et bien nous n'irons pas "l'aider" ...

@+
FxM

:-)))
et c'est en scudant les pauv' vieux qu'on devient scuderon
jps

"J@@" a écrit dans le message de news:
%
Bonjour MichDenis
J'ai fait une petite modif car tout se copiait sur la même ligne.
Voici le résultat, qui fonctionne, mais si le code est plus agréable à
lire, le gain de temps n'est pas net. D'un autre côté récupérer 600
données en 13 secondes, faut pas se plaindre que la mariée est trop belle
;-)
Faudra que je vois au travail sur mon ordi à vapeur ce que cela donne.
Encore merci
Comme (ne) dirait (pas) JPS, c'est en manipulant (du code) qu'on devient
manipuleron.
@+
J@@

'****
Private Sub CommandButton1_Click()
Dim Feuille As Worksheet
Dim Sh As Worksheet
Dim Ligne As Long
Set Sh = Worksheets("Etat")
Sh.Select
' ActiveSheet.Unprotect
Range("B5:N60").ClearContents
Ligne = Sh.Range("B100").End(xlUp)(0).Row

'Application.ScreenUpdating = False
'ModeRecalcul = Application.Calculation
Application.Calculation = xlCalculationManual
ActivationEvents = Application.EnableEvents
Application.EnableEvents = False

For Each Feuille In ActiveWorkbook.Worksheets
Ligne = Ligne + 1 ''''''''la modif
If Feuille.Name <> "ALIRE" _
And Feuille.Name <> "Etat" Then
With Feuille
Sh.Range("B" & Ligne) = .Name
Sh.Range("C" & Ligne) = .Range("B27")
Sh.Range("D" & Ligne) = .Range("B29")
'''''etc etc
End With
End If
Next Feuille

Application.EnableEvents = ActivationEvents
'Application.Calculation = ModeRecalcul
Application.Calculation = xlCalculationAutomatic

Selection.SpecialCells(xlCellTypeConstants, 16).ClearContents
' ActiveSheet.Protect
Range("a3").Select
End Sub
'****

MichDenis wrote:
Tu remplaces cette ligne de code :

Ligne = Sh.Range("B100").End(xlUp)(2).Value

Par
Ligne = Sh.Range("B100").End(xlUp)(2).Row

ça bloque sur cette ligne :
Sh.Range("B" & Ligne) = .Name

Par la variable Ligne = 0 et que dans excel
il n'y a aucune ligne portant le numéro 0

"J@@" voici le code, et j'ai une erreur 1004 sur la ligne
Sh.Range("B" & Ligne) = .Name

'****
Sub RecupDonnees()
Dim Feuille As Worksheet
Dim Sh As Worksheet
Dim Ligne As Long
Set Sh = Worksheets("Etat")
Ligne = Sh.Range("B100").End(xlUp)(2).Value
Sh.Select
ActiveSheet.Unprotect
Range("B5:N58").ClearContents

Application.ScreenUpdating = False
ModeRecalcul = Application.Calculation
Application.Calculation = xlCalculationManual
ActivationEvents = Application.EnableEvents
Application.EnableEvents = False

For Each Feuille In ActiveWorkbook.Worksheets
If Feuille.Name <> "ALIRE" _
And Feuille.Name <> "Etat" Then
With Feuille
Sh.Range("B" & Ligne) = .Name
Sh.Range("C" & Ligne) = .Range("B27")
Sh.Range("D" & Ligne) = .Range("B29")
''''etc
End With
End If
Next Feuille

Application.EnableEvents = ActivationEvents
Application.Calculation = ModeRecalcul

ActiveSheet.Protect
End Sub
'***

MichDenis wrote:
3 suggestions :
A )
Cette syntaxe est supérieur en rapidité à ceci :
..[B27] -> tu devrais utiliser ce type de syntaxe .Range("B27")

B ) Si tes enregistrements ont lieu sur la même ligne pour tous les
éléments d'une même boucle, pourquoi ne pas utiliser une variable
au lieu de réévaluer la cellule suivante disponible sur la colonne

Dim Ligne as Long
Ligne = Worksheets("Etat").Range("B100").End(xlUp)(2).Value
Et pour tes écritures dans la boucle pour chacun des items :
Worksheets("Etat").Range("B" & ligne) = .Name

C ) Remplace Worksheets("Etat"). par une variable
dim Sh as Worksheet
Set Sh = Worksheets("Etat")
Et dans ton code, tu remplaces ceci
Worksheets("Etat").Range("B100").End(xlUp)(2).Value = .Name
Par
Sh.Range("B" & ligne) = .Name










Avatar
J
Bonjour
Juste un retour d'info : la proc qui me demande maintenant 13 secondes à la
maison (XL2K, WinXP, 500MO de RAM), met 1 min 49 au boulot (XL2K, W2000, 250 MO
de RAM)

Finalement c'est super :
à la maison, je dégage du temps pour la sieste, :-)
au boulot, l'heure de la cloche est plus vite atteinte, d'autant qu'il m'arrive
de m'endormir devant l'écran. ;-)

Merci encore
@+
J@@


MichDenis wrote:
Tu remplaces cette ligne de code :

Ligne = Sh.Range("B100").End(xlUp)(2).Value

Par
Ligne = Sh.Range("B100").End(xlUp)(2).Row

ça bloque sur cette ligne :
Sh.Range("B" & Ligne) = .Name

Par la variable Ligne = 0 et que dans excel
il n'y a aucune ligne portant le numéro 0


1 2