Variable qui prend une valeur sans raison
Salut,
Je cherche le premier jour d'ouverture de la bourse après une date donnée, en excluant les WE et les jours de fermeture qui sont listés dans une feuille. J'ai le code suivant qui se lance avec un bouton
Public Ws As Worksheet
Public NbValeurs, LigneDébutCalculRendement As Integer
Public DernièreDate As Date
Public DateAReporter As Variant
Public Abandon As Boolean
Public ValorisationNette As Currency
Sub Importer()
Application.ScreenUpdating = False
'Définition des paramètres
DernièreDate = Sheets("Nb actions").Cells(1, WorksheetFunction.CountA(Sheets("Nb actions").Rows(1)))
i = 1
HeureOuverture = 1 / 24 * 9 '9 h 00
HeureFermeture = 1 / 24 * 17.6 '17 h 36
'Définition de la date à reporter
Do While DernièreDate + i <= Date
'Contrôle du jour suivant WE
If Weekday(DernièreDate + i, vbMonday) >= 6 Then
WE = True
JourWE = DernièreDate + i
End If
'Contrôle du jour suivant fermé
If Application.WorksheetFunction.CountIf(Sheets("Jours de fermeture").Columns(1), DernièreDate + i) > 0 Then
Fermé = True
JourFermé = DernièreDate + i
End If
'Définition du jour suivant
If WE = False And Fermé = False Then DateAReporter = DernièreDate + i
WE = False
Fermé = False
If DateAReporter = "" Then i = i + 1 Else Exit Do
Loop
....Je lance la macro par un bouton 5 fois par semaine et dans la très grande majorité des cas tout se passe comme prévu, la macro identifie correctement le jour suivant qui n'est ni un WE ni un jour de fermeture.
Mais aléatoirement (il semblerait) la variable DateAReporter prend par défaut la valeur DernièreDate (je ne sais pas s'il y a un rapport entre les variables ou si c'est une simple coincidence) dès le lancement de la macro. Ca se reproduit à chaque lancement suivant de la macro, que ce soit par le bouton ou par F5 (avec un point d'arrêt sur Application.ScreenUpdating = False, donc avant toute affectation de valeurs aux variables, l'espion confirme que la variable DateAReporter n'est pas vide au lancement de la macro).
Pour trouver ce qui cloche je lance la macro en pas à pas, et là systématiquement la variable DateAReporter reste bien vide jusqu'à ce que la condition If WE = False And Fermé = False soit vraie. Et quand ensuite je relance la macro, par le bouton ou par F5, elle s'exécute normalement et la variable DateAReporter répond bien à la condition If WE = False And Fermé = False comme prévu alors que je n'ai rien changé dans la macro.
Est ce que vous avez déjà eu ce genre de réaction ? Et qu'elle peut en être la cause ? C'est loin d'être la première fois que ça m'arrive (une macro qui plante aléatoirement et qui se remet à fonctionner comme prévu après une exécution en pas à pas, sans modification), j'avais déjà ouvert un thread sur le sujet il y a quelques années : https://forum.excel-pratique.com/excel/instabilite-d-excel-153519.
Manu
Bonjour,
c'est le comportement normal de variables déclarée en t^te de module et hors Sub.
Leur valeur doit rester disponible pour d'autres sub.
Fais une recherche sur portée et visibilité des variables.
eric
" Leur valeur doit rester disponible pour d'autres sub. "
C'est le but, j'ai besoin de la variable DateAReporter dans la macro qui recherche le cours correspondant. Mais le code que j'ai mis ici est celui qui est lancé par le bouton, il n'y a aucune macro exécutée avant qui pourrait venir " polluer " la variable en lui affectant une valeur, celles dont j'ai besoin sont appelées APRES cette recherche de la date à reporter.
Ce que je ne comprends pas c'est
- comment une valeur peut être affectée à une variable sans qu'à aucun moment il n'y ait d'instruction pour ça,
- pourquoi c'est (apparemment) aléatoire, puis systématique après une première occurence,
- pourquoi passer la macro en pas à pas résoud le problème pour les exécutions suivantes.
" Fais une recherche sur portée et visibilité des variables. "
Là par contre j'ai pas compris.
Manu
Bonjour,
"C'est le comportement normal d'une variable déclarée hors sub" : Elle est déclarée mais VIDE.
Elle n'a une valeur que si une macro lui affecte une valeur...
Pourquoi c'est aléatoire ? Je pense qu'une erreur d'exécution mal gérée est susceptible d'effacer cette valeur de la mémoire.
Mon conseil : Utilisez Option Explicit systématiquement et déclarez vos variables dans chaque macro.
A+
bonjour Galopin01,Manu31,Eriiic,
la date suivante, on sait la calculer comme ceci (PS. j'ai souvent des problèmes avec les accents dans les variables dans VBA, je les ai supprimé)
Sub Importer()
Dim DerniereDate, DateAReporter
DerniereDate = Sheets("Nb actions").Cells(1, WorksheetFunction.CountA(Sheets("Nb actions").Rows(1))).Value2
DateAReporter = WorksheetFunction.WorkDay_Intl(DerniereDate, 1, 1, Sheets("Jours de fermeture").Columns(1))
If DateAReporter <= Date Then
...
End Suboubie,n
Sub Importer()
Dim WE, Fermé, DateAReporter As Long
Application.ScreenUpdating = False
'Définition des paramètres
DernièreDate = Sheets("Nb actions").Cells(1, WorksheetFunction.CountA(Sheets("Nb actions").Rows(1)))
i = 1
HeureOuverture = 1 / 24 * 9 '9 h 00
HeureFermeture = 1 / 24 * 17.6 '17 h 36
'Définition de la date à reporter
Do While DernièreDate + i <= Date
WE = (Weekday(DernièreDate + i, vbMonday) >= 6) 'Contrôle du jour suivant WE
Fermé = (Application.WorksheetFunction.CountIf(Sheets("Jours de fermeture").Columns(1), DernièreDate + i) > 0) 'Contrôle du jour suivant fermé
'Définition du jour suivant
If Not WE And Not Fermé Then
DateAReporter = DernièreDate + i
Exit Do
End If
i = i + 1
Loop
If DateAReporter = 0 Then MsgBox "problème": Exit Sub
....
End SubBonjour,
je m'étais axé sur "Ca se reproduit à chaque lancement suivant de la macro" qui me parait normal.
Si ça se produit au 1er lancement c'est effectivement étrange. Contrôle déjà que sa déclaration soit unique, et tous les endroits où elle est affectée.
J'ai du mal à imaginer ça possible sans une erreur. Une erreur de nom quelque part peut arriver.
Portée et visibilité d'une variable sont 2 caractéristiques d'une variable qui dépendent de comment et où tu la déclares.
"La portée se réfère à la disponibilité d'une variable en vue d'une utilisation par une autre procédure. Il existe trois niveaux de portée : niveau de procédure, niveau de module privé et niveau de module public.
Une variable ou une constante définie dans une procédure n'est pas visible à l'extérieur de celle-ci."
eric
PS : plutôt qu'une boucle tu pourrais utiliser WorksheetFunction.WorkDay()
Salut,
Bon désolé pour le délai j'étais pas revenu sur le forum depuis mon dernier message.
Je vais regarder tout ça et voire ce que ça donne. Juste pour info tout fonctionnait bien depuis mon message du 14 et avant hier j'ai encore eu le bug. Et comme d'hab j'ai passé la macro en pas à pas et ça l'a solutionné.
Merci des réponses.
Manu