Accélerer l'exécution de mon programme en VBA

Accélerer l'exécution de mon programme en VBA - VB/VBA/VBS - Programmation

Marsh Posté le 17-11-2020 à 16:48:25    

Bonjour,
 
Je pensais avoir optimisé mon programme en l'écrivant comme ci-dessous, mais j'ai quelques longueur dans l’exécution (24 lignes traités lors de mon essai).
on est pourtant sur quelque chose de relativement Basic...
 
Je tiens à préciser que je voudrais conserver cette séparation dans le traitement des colonnes qui me permettra de faire évoluer plus facilement ma macro par la suite.
 

Code :
  1. 'Option Explicit
  2. Sub Remplir_Tableau()
  3. Dim sH As Worksheet
  4. Dim Derligne As Long, i As Long
  5. Dim tmp
  6.     Application.ScreenUpdating = False
  7.     Set sH = ActiveSheet
  8.     With sH
  9.         Derligne = .Range("K" & Rows.Count).End(xlUp).Row
  10.         For i = 6 To Derligne
  11.        
  12. .Cells(6, "A" ).Copy .Cells(i + 1, "A" ) 'Catégorie
  13. .Cells(6, "B" ).Copy .Cells(i + 1, "B" ) 'Priorité
  14. .Cells(6, "C" ).Copy .Cells(i + 1, "C" ) 'Type Adresse
  15. .Cells(6, "D" ).Copy .Cells(i + 1, "D" ) 'Nom_API
  16. '.Cells(6, "A" ).Copy .Cells(i + 1, "A" ) 'Type_Variable
  17. '.Cells(6, "A" ).Copy .Cells(i + 1, "A" ) 'Index (Lecture)
  18. '.Cells(6, "A" ).Copy .Cells(i + 1, "A" ) 'Format donnée (Lecture)
  19. .Cells(6, "I" ).Copy .Cells(i + 1, "I" ) 'Condition
  20. '.Cells(6, "A" ).Copy .Cells(i + 1, "A" ) 'N°Def
  21. .Cells(6, "O" ).Copy .Cells(i + 1, "O" ) 'Police
  22. .Cells(6, "P" ).Copy .Cells(i + 1, "P" ) 'Couleur
  23.   Next
  24. End With
  25. End Sub


 
Je ne vois pas trop quoi faire d'autre....
Merci à vous pour vos conseil ;-)
 
Valery


---------------
Il y a deux choses d'infini au monde : l'univers et la bêtise humaine... mais pour l'univers j'en suis pas très sûr
Reply

Marsh Posté le 17-11-2020 à 16:48:25   

Reply

Marsh Posté le 17-11-2020 à 21:15:44    

Bonjour,

 

Pas expert en VBA et ça fait longtemps que je n'en ai pas fait mais ton écriture de .Cells avec les lettres de colonnes me choque, alors certainement que ça fonctionne mais normalement les colonnes sont numérotées et commencent à l'indice 0.
Sinon Pourquoi ne pas copier par colonne plutôt que par ligne ? Cela devrait être plus rapide.

 
Code :
  1. finColonne = .range(Cells(5,i)).End(xlDown).row
  2. colonneSource = .range(Cells(5,i), Cells(finColonne,i))
  3. colonneDest = .range(Cells(6,i), Cells(finColonne + 1,i))
 

Tu incrémentes tes colonnes ou tu les écries en dur, tu copies la colonne source dans la colonne de destination.


Message édité par MaybeEijOrNot le 17-11-2020 à 21:16:52

---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
Reply

Marsh Posté le 18-11-2020 à 13:51:45    

Bonjour MaybeEijOrNot
 
En fait dans les évolution futures de ma macro, je devrais manipuler et modifier des valeurs, du coup copier par ligne est pour moi plus simple je pense.


---------------
Il y a deux choses d'infini au monde : l'univers et la bêtise humaine... mais pour l'univers j'en suis pas très sûr
Reply

Marsh Posté le 18-11-2020 à 14:08:20    

Je suis novice également, mais utiliser par exemple :

Code :
  1. .Cells(i + 1, "A" ).Value = .Cells(6, "A" ).Value  'Catégorie


 
Ne serait pas plus leger niveau ressources?

Reply

Marsh Posté le 18-11-2020 à 18:20:49    

valerypetit a écrit :

Bonjour MaybeEijOrNot
 
En fait dans les évolution futures de ma macro, je devrais manipuler et modifier des valeurs, du coup copier par ligne est pour moi plus simple je pense.


Peut-être que gérer le problème par ligne sera plus simple, mais la raison n'est pas celle de manipuler et modifier des valeurs, il n'y a aucun lien, tu peux tout autant manipuler et modifier des valeurs par colonne...
 
Cela serait plus simple si tu nous disais ce que tu veux faire. ;)  
 
Comme dit, si seules les valeurs t'intéressent et que tu veux les faire évoluer alors passe par .value.
Le copier/coller est plus efficace sur des plages, mais sur des cellules individuelles il va récupérer toutes les propriétés alors que tu n'en as pas forcément besoin.


---------------
C'est en écrivant n'importe quoi qu'on devient n'importe qui.
Reply

Marsh Posté le 20-11-2020 à 00:40:46    

Bonjour,
 
Pas besoin de boucle, copier formats et valeurs  :

Code :
  1. Option Explicit
  2. Sub Remplir_Tableau()
  3. Dim dL As Long
  4.   Application.ScreenUpdating = False
  5.   With ActiveSheet
  6.     dL = .Range("K" & Rows.Count).End(xlUp).Row
  7.     .Range("A6:D6" ).Copy .Range("A7:D" & dL)
  8.     .Range("I6" ).Copy .Range("I6:I" & dL)
  9.     .Range("O6:P6" ).Copy .Range("O7:P" & dL)
  10.   End With
  11. End Sub


 
Et uniquement les valeurs (beaucoup plus rapide) :

Code :
  1. Option Explicit
  2. Sub Remplir_Tableau()
  3. Dim dL As Long
  4.   Application.ScreenUpdating = False
  5.   With ActiveSheet
  6.     dL = .Range("K" & Rows.Count).End(xlUp).Row
  7.     .Range("A7:D" & dL).Value = .Range("A6:D6" ).Value
  8.     .Range("I7:I" & dL).Value = .Range("I6" ).Value
  9.     .Range("O7:P" & dL).Value = .Range("O6:P6" ).Value
  10.   End With
  11. End Sub



Message édité par patrice33740 le 20-11-2020 à 00:52:40

---------------
Cordialement, Patrice
Reply

Marsh Posté le 12-04-2021 à 21:27:53    

valerypetit a écrit :

Bonjour,
 
Je pensais avoir optimisé mon programme en l'écrivant comme ci-dessous, mais j'ai quelques longueur dans l’exécution (24 lignes traités lors de mon essai).
on est pourtant sur quelque chose de relativement Basic...
 
Je tiens à préciser que je voudrais conserver cette séparation dans le traitement des colonnes qui me permettra de faire évoluer plus facilement ma macro par la suite.
 

Code :
  1. 'Option Explicit
  2. Sub Remplir_Tableau()
  3. Dim sH As Worksheet
  4. Dim Derligne As Long, i As Long
  5. Dim tmp
  6.     Application.ScreenUpdating = False
  7.     Set sH = ActiveSheet
  8.     With sH
  9.         Derligne = .Range("K" & Rows.Count).End(xlUp).Row
  10.         For i = 6 To Derligne
  11.        
  12. .Cells(6, "A" ).Copy .Cells(i + 1, "A" ) 'Catégorie
  13. .Cells(6, "B" ).Copy .Cells(i + 1, "B" ) 'Priorité
  14. .Cells(6, "C" ).Copy .Cells(i + 1, "C" ) 'Type Adresse
  15. .Cells(6, "D" ).Copy .Cells(i + 1, "D" ) 'Nom_API
  16. '.Cells(6, "A" ).Copy .Cells(i + 1, "A" ) 'Type_Variable
  17. '.Cells(6, "A" ).Copy .Cells(i + 1, "A" ) 'Index (Lecture)
  18. '.Cells(6, "A" ).Copy .Cells(i + 1, "A" ) 'Format donnée (Lecture)
  19. .Cells(6, "I" ).Copy .Cells(i + 1, "I" ) 'Condition
  20. '.Cells(6, "A" ).Copy .Cells(i + 1, "A" ) 'N°Def
  21. .Cells(6, "O" ).Copy .Cells(i + 1, "O" ) 'Police
  22. .Cells(6, "P" ).Copy .Cells(i + 1, "P" ) 'Couleur
  23.   Next
  24. End With
  25. End Sub


 
Je ne vois pas trop quoi faire d'autre....
Merci à vous pour vos conseil ;-)
 
Valery


 
pour la vitesse, je sais pas si tu va aller sur un gain astronomique ( c''est en VBa Macro ),
dans la refactorisation de ton code, tu a plusieurs façons, sur des grands ensembles...
quand tu fais une boucle : tu FETCH sur un intervalle de données ( i++  jusqu'à dernier element )
donc tu FETCH :
avec ta boucle ... ( Méthode 1 de parcours d'ensemble )
avec .Range ( c'est un ensemble parcouru: fonction et macro pour un intervalle aussi )
avec .Cells( un autre ensemble PARAMètrable aussi, quelques approfondissements sur les paramètres de Cells( ... ) à utiliser)
 
tu vois qu'à l'utilisation de Vba, tu écrit ton code dans un style redondant ( je ferai pas mieux )
tu a oublié que tu peux copier ton Worksheet, et supprimer les colonnes excédentaires.
 
et c'est différent d'appliquer des styles, des couleurs, et de formatter des lignes et colonnes.
 
en 2 étapes :
* pas de modifications sur la base de travail / faire une copie de 'source' ...
isoles tes données nécessaires ( dans un autre document, ... c'est une copie ... )
formates selon les besoins ce nouveau fichier, worksheet, cette nouvelle colonne , lignes etc...)
 
la fonction que tu a fourni, fait beaucoup trop de choses finalement.
éclates les lignes en 4 ou 5 autres fonctions supplémentaires...
 
SYNTAXE for Vba :
 
for i = 0 to Maxelemnt step 1
 
 
next i
 
 
step : c'est le pas ( la valeur d'incrément )  ... 1 == i++
step 2.5 ... ça fait 0 // 2.5 // 5 // 7.5 ... ect ....
par défaut step = 1 // quand tu ne le mentionnes pas.
 
next // il conduit à l'itération suivante ..
tu a next for // next i // next
 
next i // il ajoute ton "step" à ton 'indexer' i ...
avec next i // tu a pas besoin de faire i++ ou i+ 1
 
tu utilise bien i+1 pour parcourir les cells() ,   tu peux imbriquer 2 boucles... pour une lecture simplifiée
car i parcours verticalement et horizontalement tes enregistrements.. ( c'est booléen ASTUCIEUX !!  mais dur à suivre)
 
for i = 0 to Max step 1
  for j= ''cellulle....'' to ''cellule...der'' step 1
    // ou tout autre chose...
 
     
 
  next j
next i
 
 
 


Message édité par djinto le 12-04-2021 à 21:49:24
Reply

Marsh Posté le 12-04-2021 à 23:54:05    

D'autres notions : les types spécialisés, les types primitifs et la charge d'éxècution
 
Les types spécialisés : ils sont gros consommateurs de mémoire et de 'process'.
Ils sont encapsulés et utilisables dans des API, pas du tout 'noyau Os'.
 
Les types primitifs :
binaires, entiers , char .
 
 
Charge d'éxècution :
c'est le 'poids' et le 'temps' nécessaires à l'éxècution d'un 'process'.
 
 
Quand tu utilises des macro Excel, tu es haut dans les usages de l'Os,
les types sont intégrés Excel, le code est un code interprété.
 
Lorsque tu réalises la copie de la colonne K... , tu reprends les cellules une à une.
 
L'encapsulation de Excel dans ton Windows, crées une forte consommation de ressources, crées et supprimes bcp d'objets ( en mémoire ) et demande donc bcp de "temps de calcul".
 
en fait, au lieu de manipuler des entiers, ou une chaine de caractères ( une chaine, une date ?? ) , tu manipules des cellules de tableur par une macro.
 
quand tu lis les données avant de les copier en utilisant range().
tu peux aussi les placer dans un tableau temporaire, pour 'quitter' la grande consommation de ressources des Objets Excel.
 
Autrement dit :
ton tas dans ton code : ( Cell 1 ..... ;;;;;;;; Cell N ) , // type spécialisé  
qui pourrait être :
tableau d'entier ( long ) : ( Valeur 1 ;;;;;;;; Valeur N ) // type primitif + rapide !!!
 
c'est comme utiliser une séquence assembleur quand il y a pas besoin de plus. ( c'est léger et trés efficace ).
 
 
Puis tu les replaces, après modifications dans le Worksheet voulu.
ce sera + rapide, pour à peine plus de lignes de code.
 

Reply

Marsh Posté le 13-04-2021 à 11:16:15    

Ranger son code ( tout les codes ) :
 
toutes les déclarations/initialisation de variables en en-têtes de fichiers,
elles seront de portées globales,  
tant qu'une fonction ne nécessites pas de faire autrement.
 
La taille de ce 'bulk'  de variables sera égale à la ram nécessaire au lancement de l'application, nominale ( comme ils disent ).
 
les fonctions du dev n'ont aucun paramètres spécifiés en 'input' puisqu'elle utilisent que les variables qui sont dans le 'bulk'.
 
les fonctions 'language' ont des paramètres explicites, écrits, puisqu'elles ne fonctionnent pas sans ces paramètres ( quoi que ... )
 
Et ça permet quoi ?
 
de n'avoir que i, j, k comme compteur de boucle par exemple,
puisque tout va se faire autour de ces 3 compteurs, les exceptions seront rares...
 
de faire qu'une seule déclaration pour un usage ou plusieurs, et cela pour tout ( le maximum d'usage ) de ces variables.
ex : avoir un 'conteneur', qui est utilisé plusieurs fois, plutôt que créer / détruire la variable d'un même type ( hé oui ).
 
Sur des traitement importants,
400 000 additions, ou concaténations ( un Blu-ray ... ), sont effectuées sur le même ensemble.
C'est inutile d'instancier ou détruire 400 000 fois une variable, puisque le conteneur est le même, et le Type aussi.
 
C'est aller vers le 'traitement par lots', là ou un ordinateur est trés trés fort.
 
Les CPUs ne travaillent qu'en binaire , un fichier Xml, un fichier Excel, un Mp3 ... le Cpu ne les voit pas passer dans ses gravures, ni ses circuits.
Le Cpu traite des 'binaires'. rien d'autres. ( c'est le Type le + rapide )
 
Pour le traitement par lots, et les boucles,
sachant que while( condition ) réalise un test avant d'executer les lignes de codes,
while( i++ && i < 4 ) c'est égale à :
while ( i ++ ){
if( i < 4 ){}{}
}
pour dire que il y a pas besoin de if dans un programme,
puisque qu'une boucle fournit un ( ou plusieurs ) IF aussi.
 
while inclut if  ;) programme exclut if  ;)
 
 
un 'process' est executé une fois / ou des milliards de fois...
la boucle sera executé, puis arreté en fin de 'lots' ... pour zéro, une, ou des milliards de fois.
 
 
C'est du 'code design' , et ça mènes vers les 'codes page', il y a rien de trop dans un code page.


Message édité par djinto le 13-04-2021 à 11:21:27
Reply

Sujets relatifs:

Leave a Replay

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