Erreur aléatoire VBA "La méthode _ de l'objet Range a échoué". Pb mémoire ?
Bonjour,
J'ai rédigé un code VBA permettant de lire une grande quantité de données d'un fichier codé en binaire pour les inscrire dans mon fichier Excel.
Le code fonctionne bien, cependant si je tente de l'exécuter plusieurs fois, au bout d'un certain nombre (aléatoire) d'exécutions je vais obtenir le message d'erreur "la méthode ___ de l'objet Range a échoué". Cette erreur peut apparaître de manière aléatoire à n'importe quel endroit dans mon code où j'utilise une méthode Range.___. Un exemple qui arrive souvent est "la méthode Value de l'objet Range a échoué"
Pour faire disparaître cette erreur il faut que je ferme tous mes fichiers Excel ouverts et que j'ouvre mon fichier à nouveau pour ré-exécuter le code. Cela me fait penser à un problème de mémoire.
Si l'un de vous a déjà rencontré ce genre d'erreur, ou connaît des méthodes pour inspecter l'espace mémoire disponible pour Excel/VBA je suis preneur.
Merci d'avance !
Quelques infos supplémentaires :
- Excel 2013
- Les fichiers Excel peuvent faire jusqu'à 10Mo avec pas mal de liaisons internes, de mises en forme conditionnelles et de validations des données
- Le code VBA fait plusieurs milliers de lignes
- Les Range sur lesquelles je fais des opérations font au maximum quelques centaines de lignes et pas plus de 10 colonnes
- Je n'utilise aucune variable globale
- L'erreur arrive avec ou sans Application.ScreenUpdating, Application.EnableEvents, Application.Calculation (Manuel ou Automatic)
- J'ai 32Go de RAM installée, le gestionnaire des tâches m'indique entre 200Mo et 500Mo de mémoire utilisée par Excel
- Je n'ai malheureusement pas la possibilité de joindre une copie du fichier Excel en question
J'ai déjà rencontré ce type de pb parce que je n'avais pas le réflexe de libérer mes objets de leur contenu après emploi (un FSO, une plage, une cellule, une feuille UF, un classeur, etc.). A chaque déclaration d'un objet doit correspondre une libération systématique de la mémoire en fin de procédure ou de fonction. Si les objets sont nombreux, il est bon de mettre cette libération dans une fonction. Un truc du genre :
Set monObjet = NothingBonjour et bienvenue sur le forum
Bonjour à tous
Tu peux aussi essayer de libérer de la mémoire en insérant à l'endroit le plus judicieux l'instruction :
Application.CutCopyMode = falseElle vide le presse papier
Bye !
Bonjour, merci de vos réponses Optimix et gmb
Malheureusement aucune des deux n'a fonctionné pour moi
Je me suis rendu compte que même si l'erreur apparaissait, l'opération d'affectation Range.Value = __ se réalisait tout de même sur mon fichier Excel. J'ai donc résolu le problème en ignorant l'erreur :
Dim maVariable() as Double
ReDim maVariable(1 to 100)
'Affectation des valeurs dans maVariable
On Error Resume Next
With Sheets("MaFeuille")
.Range(.Cells(1,1), .Cells(100,1)).Value = Application.Transpose(maVariable)
End With
On Error GoTo 0J'aimerais tout de même savoir d'où vient l'erreur si vous avez une idée pour éviter de l'ignorer bêtement
Bonne journée !
Bonjour,
J'aimerais tout de même savoir d'où vient l'erreur si vous avez une idée pour éviter de l'ignorer bêtement
Oui, effectivement, comme je vous comprends.
Malheureusement, sans le code complet et sans fichier, ça va être extrêmement difficile de vous répondre...
a minima le code...
Rebonjour,
L'erreur n'est malheureusement toujours pas corrigée, quand je l'ignore quelque part, elle resurgit ailleurs dès que la classe Range est sollicitée. Quand l'erreur est survenue une fois, elle reviendra à chaque procédure où un Range est appelé jusqu'à ce que je relance Excel.
Voici un emplacement simple où l'erreur 1004 survient, sur la méthode ClearContents :
'Reinitialise la feuille "Profils"
Public Sub ReinitialiserProfils()
With Sheets(nomProfils)
.Range(.Cells(ligneNomProfil, 2), .Cells(ligneNomProfil, 1000)).ClearContents
.Range(.Cells(ligne1Profil, 2), .Cells(ligne1Profil + 10000, 1000)).ClearContents
End With
End Suboù les constantes publiques de localisation des lignes/colonnes sont définies comme suit :
'Constantes de la feuille "Profils"
Public Const nomProfils As String = "Profils"
Public Const ligneNomProfil As Long = 5
Public Const ligne1Profil As Long = 9En mode débogage, quand je survole les variables leur valeur apparaissent correctement.
J'ai déjà essayé en activant d'abord le workbook et le worksheet, et en déclarant un range de cette manière, mais toujours la même erreur :
Dim rg as Range
With Sheets(nomProfils)
set rg = .Range(.Cells(ligneNomProfil, 2), .Cells(ligneNomProfil, 1000))
rg.ClearContents
End With
set rg = NothingDans la fenêtre variables locales, rg apparait comme ceci :
Celui qui trouve d'où vient l'erreur me sauverait la vie ! :)
Merci d'avance
Bonjour Jacks
Et si au lieu de mettre
With Sheets(nomProfils)Vous mettiez
With ThisWorkbook.Sheets(nomProfils)Rassurez nous, vous avez bien une feuille nommée "Profils" ?
@+
Bonjour à tous,
tout à fait au hasard mais qui ne tente rien n'a rien.
A-priori tu as l'air de manipuler beaucoup de données sur tes feuilles.
Tu peux de temps en temps lui laisser le temps de finir son boulot surtout si tu as des formules lourdes.
Attente fin de calcul :
Do Until Application.CalculationState = xlDone
DoEvents
LoopSi c'est juste des écritures, tu peux oublier
eric
PS : DoEvents ralentis beaucoup, vas-y avec parcimonie...
Bonjour BrunoM45 et eriiic, merci pour votre aide
BrunoM45 : Oui je vous rassure BrunoM45 j'ai bien une feuille "Profils". D'ailleurs le code peut fonctionner plusieurs fois avant que le bug apparaisse. J'ai essayé en ajoutant "ThisWorkbook" mais le bug est toujours là.
eriic : Oui il y a en effet pas mal de calcul. J'ai essayé votre astuce, et aussi en passant les calculs à "Manuel" mais rien n'y fait.
Bonsoir,
et si tu le fermes systématiquement avant de le relancer, ça plante toujours ?
Si c'est suffisant, on pourrait imaginer un fichier principal qui le ferme si présent et l'ouvre à chaque nouvelle demande.
eric
Bonjour à tous,
Quelque chose que je ferais, c'est de déclarer une variable objet plutôt que de mettre des "With" (A chaque fois que ça bug)
'Reinitialise la feuille "Profils"
Public Sub ReinitialiserProfils()
Dim Sht As Worksheet
Set Sht = ThisWorkbook.Sheets(nomProfils)
Sht.Range(Sht.Cells(ligneNomProfil, 2), Sht.Cells(ligneNomProfil, 1000)).ClearContents
Sht.Range(Sht.Cells(ligne1Profil, 2), Sht.Cells(ligne1Profil + 10000, 1000)).ClearContents
Set Sht = Nothing
End SubJe l'accorde, ce n'est pas logique ou normal
@+
Bonjour,
eriic : si je ferme toutes les instances Excel avant de ré-ouvrir le fichier ça fonctionne mieux. Ça va plus loin dans l'exécution de la procédure et parfois ça arrive au bout, parfois le code tourne sans problème plusieurs fois, mais ça ne fonctionne pas systématiquement
BrunoM45 : j'ai essayé mais ça ne fonctionne pas
Quelque chose qui pourrait peut-être être une piste, dans le code VBA cette fonction est exécutée et charge une assez grande quantité de données en mémoire (25Mo environ) d'un fichier binaire vers un type défini par l'utilisateur. Cette fonction marche bien (même si je la suspecte de causer un "Microsoft Excel a cessé de fonctionner" de temps en temps). Mon ressenti est que ça prend peut-être de la place en mémoire qui ne se vide pas correctement. Peut-être est-ce lié au problème d'accès aux propriétés des Range qui semble provenir de la mémoire ?
Function LireBin(chemin As String) As MonUDT
'Renvoie les données du fichier binaire au format "MonUDT"
Dim Version As Long
Dim x As Integer
On Error GoTo HandleError
'Chargement du fichier
x = FreeFile
Open chemin For Binary Access Read As #x
Get #x, , Version
Get #x, , LireBin
Close #x
Exit Function
HandleError:
MsgBox Err.Description
Close
End FunctionMerci pour votre aide
Bonjour,
en théorie tu devrais pouvoir lire 2 Go, 25 Mo n'est pas tant que ça. Mais ça me donne une idée.
Si tu es sur office 32 bits, peux-tu faire un test en office 64 bits ?
Et une autre : tu as Erase pour nettoyer les gros tableaux lorsqu'ils ne servent plus.
Si tu en as des énormes, ca fera toujours ça de récupéré.
Sinon une fenêtre de VBE peu connue mais parfois utile dans ces cas c'est la 'Pile des appels...' Ctrl+L
Tu pourrais faire des captures de la pile au moments des plantages, et par recoupements voir s'il n'y a pas un point commun dans les appels précédents qui pourraient aiguiller ta recherche.
Je pense plus que c'est une accumulation et que les causes peuvent être très loin dans la pile mais bon, autant jeter un oeil.
eric
PS : 1004 peut recouvrer plusieurs types de causes.
Celles que j'avais repérées des fois que ça te donne une idée. Tu es sans doute hors de ces cas mais tu vois que des fois il faut élargir la recherche:
1) code dans Feuil1 pour un .sort en Feuil2. Mettre le code dans un module
2) 'Close' of object _Workbook failed sur fermeture d'un classeur à partir d'un userform :
Bug excel, décharger le userform avant de fermer le classeur
Unload Me : opened_workbook.Close
3) feuille protégée ou masquée (.Sort)
Et les variables utilisées dans les Cells() de tes .Range peuvent aussi être en cause. Si pas déjà fait contrôle que leur évaluation est correcte et correspondent à un existant.