bug PC à cause d'une macro

bug PC à cause d'une macro - VB/VBA/VBS - Programmation

Marsh Posté le 05-02-2013 à 13:27:11    

Euh... pourquoi Dans le If : si je mets Range(..) à la place de Cells(..) j'ai une erreur, et si je laisse Cells(..), ben j'ai mon ordinateur en mode écran noir, l'écran se met en veille, l'ordi toujours allumé mais impossible d'avoir une réponse, pas de ctrl alt suppr rien, donc obligé de shut down... ?
 
(i étant un compteur)
 

Code :
  1. For Each Cell In Selection
  2.         If Not (Cell.Value Like "D*" ) Then
  3.             Rows(i).Delete shift:=xlUp
  4.             i = i - 1
  5.         End If
  6.         If Cells(i, 1).Value = "" And Cells(i + 1, 1).Value = "" And Cells(i + 2, 1).Value = "" Then
  7.             Exit For
  8.         End If
  9.         i = i + 1
  10. Next Cell

Reply

Marsh Posté le 05-02-2013 à 13:27:11   

Reply

Marsh Posté le 05-02-2013 à 13:59:42    

Si la cellule ne commence pas par D, Alors on supprime la ligne, et on décrémente i pour reprendre correctement le parcours des lignes
 
Si 3 cellules consécutives sont vides (c'est-à-dire qu'on est à la fin du tableau) Alors on sort du For

Reply

Marsh Posté le 05-02-2013 à 13:59:56    

For each et like doivent utiliser pas mal de mémoire je pense.

 

Tu devrais essayer avec une boucle type do ... loop et à la place du like "D*" faire un left(cells(i,1).value, 1) = "D".

 
Code :
  1. i = LigneMax
  2. do while i <> 1 step -1
  3.    if left(cells(i,1).value, 1) <> "D" then
  4.       Rows(i).Delete shift:=xlUp
  5. ... etc
  6. loop
 

Y a sûrement des erreurs dans mon code, je l'ai écrit directement dans le post.


Message édité par vave le 05-02-2013 à 14:00:12

---------------
Bel ours Vave, je me dois de l’admettre. -Skyl"win"-  Mais toi tu es intelligent -Homerde- - Ce génie -SkylWINd- JDD S16M72 10:43:46 GMT-DTC +1
Reply

Marsh Posté le 05-02-2013 à 14:02:16    

je n'ai pas LigneMax, vu que le tableau ne sera pas toujours de la même taille... :(

Reply

Marsh Posté le 05-02-2013 à 14:08:41    

Tu peux la trouver comme ça :
(la colonne est à adapter) :

 
Code :
  1. LigneMax = Range("A1048576" ).End(xlUp).Row
 

1048576 à partir d'excel 2007, 65536 avant.

 

Ca revient à te positionner tout en bas de l'onglet et de faire ctrl + flèche du haut => ça t'emmène à la dernière cellule renseignée.


Message édité par vave le 05-02-2013 à 14:09:04

---------------
Bel ours Vave, je me dois de l’admettre. -Skyl"win"-  Mais toi tu es intelligent -Homerde- - Ce génie -SkylWINd- JDD S16M72 10:43:46 GMT-DTC +1
Reply

Marsh Posté le 05-02-2013 à 14:09:47    

ooooh... c'est bon à savoir ça!! :D
merci je vais essayé :)

Reply

Marsh Posté le 05-02-2013 à 14:17:34    

alors... j'ai fait :  

Code :
  1. i = ligneMax
  2.        
  3.     ' Suppression des lignes inutiles
  4.     Do While i <> 1
  5.         If Left(Cells(i, 1).Value, 1) <> "D" Then
  6.             Rows(i).Delete shift:=xlUp
  7.             i = i - 1
  8.         End If
  9.         i = i + 1
  10.     Loop


 
 
et mon PC a redémarré...

Reply

Marsh Posté le 05-02-2013 à 14:18:11    

avec ligneMax = Range("A65536 " ).End(xlUp).Row

Reply

Marsh Posté le 05-02-2013 à 14:33:06    

et le problème vient de cette partie du code, vu que si je mets le do loop en commentaire, ça fonctionne...  Là j'ai eu mon écran qui a "clignoté un peu", puis mon PC a redémarré...

Reply

Marsh Posté le 05-02-2013 à 14:52:29    

erreur stupide j'ai fait


Message édité par minimoack le 05-02-2013 à 14:52:41
Reply

Marsh Posté le 05-02-2013 à 14:52:29   

Reply

Marsh Posté le 05-02-2013 à 14:53:47    

Tu as encore le problème ?


---------------
Bel ours Vave, je me dois de l’admettre. -Skyl"win"-  Mais toi tu es intelligent -Homerde- - Ce génie -SkylWINd- JDD S16M72 10:43:46 GMT-DTC +1
Reply

Marsh Posté le 05-02-2013 à 14:55:04    

Tu ferais mieux de partir de la première colonne de la première ligne et scanner le contenu et voir s'il est non nul (ou prendre une autre colonne), passer à la suivante jusqu'à trouver la dernière ligne de ton tableau.. Ca devrait aller plus vite que de partir de la fin du nb de lignes max d'Excel :/


---------------
Astres, outil de help-desk GPL : http://sourceforge.net/projects/astres, ICARE, gestion de conf : http://sourceforge.net/projects/icare, Outil Planeta Calandreta : https://framalibre.org/content/planeta-calandreta
Reply

Marsh Posté le 05-02-2013 à 14:57:49    

 
           Il y a une grosse erreur de "logique" dans le dernier code ‼   Personnellement je préfères une boucle comme dans le premier …
 
           Ensuite, c'est parfois risqué de travailler avec Selection sans contrôle au préalable.
           De plus je note le même souci de logique avec un coup i = i - 1 puis plus bas i = i + 1 ...
 
           Sans code plus exhaustif ni une explication claire des besoins, je ne pourrais aider …
 

Reply

Marsh Posté le 05-02-2013 à 15:00:15    

Code :
  1. Do While i <> 1
  2.         If Left(Cells(i, 1).Value, 1) <> "D" Then
  3.            Rows(i).Delete shift:=xlUp
  4.         End If
  5.         i = i - 1
  6.     Loop


 A oovaveoo : ben je pense qu'il boucle à l'infini car MsbBox de ligneMax me renvoie 757 alors que ma dernière ligne 754
 
A rufo : c'est ce que j'avais fait au début avec

Code :
  1. If Cells(i, 1).Value = "" And Cells(i + 1, 1).Value = "" And Cells(i + 2, 1).Value = "" Then
  2.             Exit For
  3.         End If

mais ça ne marchait pas...  
en fait, j'ai des lignes vides dans mon tableau, donc je suis obligée de faire un test sur au moins deux cellules vides consécutivement
 
 

Reply

Marsh Posté le 05-02-2013 à 15:00:59    

rufo a écrit :

Tu ferais mieux de partir de la première colonne de la première ligne et scanner le contenu et voir s'il est non nul (ou prendre une autre colonne), passer à la suivante jusqu'à trouver la dernière ligne de ton tableau.. Ca devrait aller plus vite que de partir de la fin du nb de lignes max d'Excel :/


C'est ce qu'on fait dans excel et normalement c'est immédiat.

Marc L a écrit :

 
           Il y a une grosse erreur de "logique" dans le dernier code ‼   Personnellement je préfères une boucle comme dans le premier …
 
           Ensuite, c'est parfois risqué de travailler avec Selection sans contrôle au préalable.
           De plus je note le même souci de logique avec un coup i = i - 1 puis plus bas i = i + 1 ...
 
           Sans code plus exhaustif ni une explication claire des besoins, je ne pourrais aider …
 


La boucle du premier avec For Each ?
 


---------------
Bel ours Vave, je me dois de l’admettre. -Skyl"win"-  Mais toi tu es intelligent -Homerde- - Ce génie -SkylWINd- JDD S16M72 10:43:46 GMT-DTC +1
Reply

Marsh Posté le 05-02-2013 à 15:02:02    

Marc L a écrit :

 
           Il y a une grosse erreur de "logique" dans le dernier code ‼   Personnellement je préfères une boucle comme dans le premier …
 
           Ensuite, c'est parfois risqué de travailler avec Selection sans contrôle au préalable.
           De plus je note le même souci de logique avec un coup i = i - 1 puis plus bas i = i + 1 ...
 
           Sans code plus exhaustif ni une explication claire des besoins, je ne pourrais aider …
 


 
Bah sur mon code du début, je fais i-1 lorsque je supprime une ligne, car sinon je louperais des lignes, puis après j'incrémente... ce n'est pas une erreur de logique

Reply

Marsh Posté le 05-02-2013 à 15:03:14    

si je supprime la ligne 3 par exemple, la ligne 4 va prendre la place de la ligne 3. Donc je dois décrémenter i quand je supprime, et l'incrémenter à la fin de ma boucle

Reply

Marsh Posté le 05-02-2013 à 15:06:15    

Marc L a écrit :

 
           Il y a une grosse erreur de "logique" dans le dernier code ‼   Personnellement je préfères une boucle comme dans le premier …
 
           Ensuite, c'est parfois risqué de travailler avec Selection sans contrôle au préalable.
           De plus je note le même souci de logique avec un coup i = i - 1 puis plus bas i = i + 1 ...
 
           Sans code plus exhaustif ni une explication claire des besoins, je ne pourrais aider …
 


 
Les besoins, je les ai mis plus haut :  

Citation :

Si la cellule ne commence pas par D, Alors on supprime la ligne, et on décrémente i pour reprendre correctement le parcours des lignes
 
Si 3 cellules consécutives sont vides (c'est-à-dire qu'on est à la fin du tableau) Alors on sort du For


 
je pense que c'est plutot clair non?

Reply

Marsh Posté le 05-02-2013 à 15:07:56    

Comme ça sinon :

Code :
  1. ligneMax = Range("A65536 " ).End(xlUp).Row
  2. For i = ligneMax To 1 Step -1
  3.         If Left(Cells(i, 1).Value, 1) <> "d" Then
  4.            Rows(i).Delete shift:=xlUp
  5.         End If
  6. Next


---------------
Bel ours Vave, je me dois de l’admettre. -Skyl"win"-  Mais toi tu es intelligent -Homerde- - Ce génie -SkylWINd- JDD S16M72 10:43:46 GMT-DTC +1
Reply

Marsh Posté le 05-02-2013 à 15:10:21    

 
           +1 avec oovaveoo, j'étais pratiquement en train de poster le même code !
 

Reply

Marsh Posté le 05-02-2013 à 15:10:58    

Et pour les 3 lignes vides, tu ajoutes un compteur :
 

Code :
  1. compteur = 0
  2. ligneMax = Range("A65536 " ).End(xlUp).Row
  3. For i = ligneMax To 1 Step -1
  4.         If Left(Cells(i, 1).Value, 1) <> "d" Then
  5.            Rows(i).Delete shift:=xlUp
  6.         End If
  7. if cells(i,1) = "" then
  8. compteur = compteur+1
  9.     if compteur = 3 then: exit for
  10. else
  11. compteur = 0
  12. end if
  13. Next


---------------
Bel ours Vave, je me dois de l’admettre. -Skyl"win"-  Mais toi tu es intelligent -Homerde- - Ce génie -SkylWINd- JDD S16M72 10:43:46 GMT-DTC +1
Reply

Marsh Posté le 05-02-2013 à 15:11:46    

ça ne peut pas marcher, il va boucler à l'infini non?

Reply

Marsh Posté le 05-02-2013 à 15:14:22    

je vais essayer! si je mets du temps à répondre, c'est que mon PC a planté! :D

Reply

Marsh Posté le 05-02-2013 à 15:17:26    

 
           Au contraire vu que les bornes sont cette fois bien définies et non modifiées en cours de route !
 
           Dans le cas de suppression de lignes, il faut remonter vers le haut pour ne pas avoir de souci …
 
           A tous, mieux vaut éviter de mettre en dur le numéro de la dernière ligne car lorsque l'on change de version d'Excel …
           … et qu'il est extrêmement simple de l'obtenir :   Rows.Count  !

Code :
  1. For i = Cells(Rows.Count, 1).End(xlUp).Row To 1 Step -1

Reply

Marsh Posté le 05-02-2013 à 15:22:18    

bon... je viens de redémarrer...

Code :
  1. If Left(Cells(i, 1).Value, 1) <> "d" Then
  2.            Rows(i).Delete shift:=xlUp
  3. End If


 
il faut pas plutot mettre :=xldown?
 
parce que imaginons :  
la macro supprime la dernière ligne du tableau (749) car la cellule est de type "----". Donc la ligne 750 qui est vide va prendre la place de la 749, et la macro boucle dessus... non?

Reply

Marsh Posté le 05-02-2013 à 15:28:58    

Marc L a écrit :

 
           Au contraire vu que les bornes sont cette fois bien définies et non modifiées en cours de route !
 
           Dans le cas de suppression de lignes, il faut remonter vers le haut pour ne pas avoir de souci …
 
           A tous, mieux vaut éviter de mettre en dur le numéro de la dernière ligne car lorsque l'on change de version d'Excel …
           … et qu'il est extrêmement simple de l'obtenir :   Rows.Count  !

Code :
  1. For i = Cells(Rows.Count, 1).End(xlUp).Row To 1 Step -1



C'est noté ;)  

minimoack a écrit :

bon... je viens de redémarrer...

Code :
  1. If Left(Cells(i, 1).Value, 1) <> "d" Then
  2.            Rows(i).Delete shift:=xlUp
  3. End If


 
il faut pas plutot mettre :=xldown?
 
parce que imaginons :  
la macro supprime la dernière ligne du tableau (749) car la cellule est de type "----". Donc la ligne 750 qui est vide va prendre la place de la 749, et la macro boucle dessus... non?


Ben non, essaye tu verras.
 


---------------
Bel ours Vave, je me dois de l’admettre. -Skyl"win"-  Mais toi tu es intelligent -Homerde- - Ce génie -SkylWINd- JDD S16M72 10:43:46 GMT-DTC +1
Reply

Marsh Posté le 05-02-2013 à 15:30:33    

ça marche avec xlDown, et pas avec xlUp

Reply

Marsh Posté le 05-02-2013 à 15:31:53    

je ne sais pas vraiment pourquoi... mais avec xlUp il m'éteignait systématiquement l'ordi, et avec xlDown non... j'ai tout ce que je veux là... ben Merci pour votre aide :D  
:jap:

Reply

Marsh Posté le 05-02-2013 à 15:47:31    

Un dernier petit truc :  
je souhaite faire un for pour supprimer la récurrence des entêtes des colonnes dans mon tableau. Vaut-il mieux utiliser celui que vous m'avez montré, et l'alourdir, ou vaut-il mieux en créer un autre? quelle solution est la moins lourde?

Reply

Marsh Posté le 05-02-2013 à 15:52:15    

Si tu dois tester toutes les lignes, il vaut mieux utiliser la même boucle, ça les parcourras qu'une seule fois.


---------------
Bel ours Vave, je me dois de l’admettre. -Skyl"win"-  Mais toi tu es intelligent -Homerde- - Ce génie -SkylWINd- JDD S16M72 10:43:46 GMT-DTC +1
Reply

Marsh Posté le 05-02-2013 à 15:55:35    

oki merci :D

Reply

Marsh Posté le 05-02-2013 à 16:24:30    

Bon... en fait ça me shut down environs une fois sur deux...


Message édité par minimoack le 05-02-2013 à 16:43:10
Reply

Marsh Posté le 05-02-2013 à 16:48:06    

Voici donc mon code actuel :  

Code :
  1. For i = ligneMax To 1 Step -1
  2.         If Cells(i, 1).Value = Range("A1" ).Value Then
  3.             Rows(i).Delete
  4.         End If
  5.         If Left(Cells(i, 1).Value, 1) <> "D" Then
  6.             Rows(i).Delete shift:=xlDown
  7.         End If
  8.         If Cells(i, 1) = "" Then
  9.             compteur = compteur + 1
  10.         If compteur = 3 Then: Exit For
  11.         Else
  12.             compteur = 0
  13.         End If
  14.     Next


 
y-aurait-il un moyen de l'alléger? Il me shut down une fois sur deux, donc il marche, mais  il est trop lourd je crois...

Reply

Marsh Posté le 05-02-2013 à 17:15:40    

T'as beaucoup de lignes ?
 
Sinon, une autre solution serait de filtrer les lignes qui ne commencent pas par D et les supprimer.
Avec l'enregistreur de macro ça doit bien se faire.


---------------
Bel ours Vave, je me dois de l’admettre. -Skyl"win"-  Mais toi tu es intelligent -Homerde- - Ce génie -SkylWINd- JDD S16M72 10:43:46 GMT-DTC +1
Reply

Marsh Posté le 05-02-2013 à 19:20:24    

 
           Avant toute chose, où se situe le code : dans un module, dans une classe d'une feuille ou ThisWorkbook ?

 

           La feuille traitée a l'air d'être la feuille active, fait-elle partie du classeur contenant le code ou d'un autre classeur ?
           Si c'est un classeur de macros (.xla), il faut alors bien qualifier les objets, éviter donc les raccourcis …

 

           J'éviterais le compteur (même si je pense qu'il ne pause pas de problème sauf peut-être la syntaxe employée),
           je remplacerais les lignes 8 à 13 par celle-ci :

Code :
  1. If Cells(i, 1) = "" And Cells(i + 1, 1) = "" And Cells(i + 2, 1) = "" Then Exit For


            Edit :   en fait il n'y a pas besoin de compteur car c'est une remontée et non pas une descente !

 

            De plus, je suppose que la première ligne ne doit pas être supprimée (à cause du test avec la cellule A1),
            donc la remontée devrait s'arrêter à ligne 2;    la non imbrication des If pourrait poser problème
            alors qu'à mon avis il faudrait les combiner comme ceci :

Code :
  1.     Application.EnableCancelKey = xlInterrupt
  2.     For i = Cells(Rows.Count, 1).End(xlUp).Row To 2 Step -1
  3.         If Cells(i, 1) > "" And (Cells(i, 1) = [A1] Or _
  4.                             Left(Cells(i, 1), 1) <> "D" ) Then Rows(i).Delete
  5.     Next
  6.     Application.EnableCancelKey = xlDisabled
 

            Astuce :   la première ligne permet de suspendre la boucle via la touche ECHAP …


Message édité par Marc L le 06-02-2013 à 01:44:00
Reply

Marsh Posté le 06-02-2013 à 09:04:11    

Alors :  
le code est dans un module. Les fonctions qui y sont, sont appelées dans le ThisWorkbook.
Les données sont dans un autre classeur : je pars de Classeur1.xls qui contient la macro, et qui ouvre un fichier txt dans un excel.
 
je vais tester ça merci! et super l'astuce de la touche échap, j'étais bien embêtée :D

Reply

Marsh Posté le 06-02-2013 à 10:16:05    

 
           Comme dans un cas similaire en version 2003 j'ai été obligé de qualifier complètement les objets
           (exemple :   ActiveWorkbook.ActiveSheet.Cells(i, 1)   au lieu de   Cells(i, 1)   tout court …),
           je pense que dans ta version 2002 il faut aussi être rigoureux !

 

           Mais cela demande une vue d'ensemble, insuffisante avec des bouts de code …


Message édité par Marc L le 06-02-2013 à 10:16:54
Reply

Marsh Posté le 06-02-2013 à 10:29:50    

je vais le faire merci :D

Reply

Marsh Posté le 06-02-2013 à 10:30:30    

c'est ma principale fonction.
 
dans mon programme principal, j'ouvre un fichier, et j'appelle cette fonction, c'est tout

Reply

Marsh Posté le 06-02-2013 à 11:01:41    

 
           Soit une variable objet est créée juste après l'ouverture du fichier

Code :
  1.     Workbooks.Open […]
  2.     Set Ws = ActiveWorkbook.ActiveSheet

           puis cette référence est utilisée dans le code

Code :
  1.     For i = Ws.Cells(Ws.Rows.Count, 1).End(xlUp).Row To 2 Step -1
  2.         If Ws.Cells(i, 1) > "" And (Ws.Cells(i, 1) = Ws.[A1] Or _
  3.                                Left(Ws.Cells(i, 1), 1) <> "D" ) Then Ws.Rows(i).Delete
  4.     Next

          (l'utilisation de variables objet est pratique pour "naviguer" entre 2 classeurs ou feuilles),
 
          soit l'objet est qualifié ponctuellement dans une structure With
          (dans ce cas ne pas oublier le point devant chaque propriété y faisant référence)

Code :
  1.     With ActiveWorkbook.ActiveSheet
  2.         For i = .Cells(.Rows.Count, 1).End(xlUp).Row To 2 Step -1
  3.             If .Cells(i, 1) > "" And (.Cells(i, 1) = .[A1] Or _
  4.                                  Left(.Cells(i, 1), 1) <> "D" ) Then .Rows(i).Delete
  5.         Next
  6.     End With

Reply

Marsh Posté le    

Reply

Sujets relatifs:

Leave a Replay

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