VBA: Peut-on tester si une variable objet est "vide" ?

Guy_M

XLDnaute Occasionnel
Bonjour,

Dans un UserForm, j'ai des variables globales permettant de gérer des classeurs (Workbook) et des feuilles (WorkSheet).

Le UserForm n'étant pas modal, l'utilisateur peut librement supprimer des feuilles et fermer des classeurs. S'ils sont associés à une de mes variables, cette variable est "vide" car associée à un objet qui n'existe plus ; elle devient inutilisable : un test avec "Is Nothing" retourne faux mais si j'appelle un de ses membres ou une de ces méthodes, j'ai une erreur d'exécution.

Existe-t-il un test simple pour déterminer si une variable objet est "vide", c'est dire qu'elle a été associé à un objet et l'objet associé n'existe plus en mémoire ?

NB : on peut gérer ce problème en utilisant les évènements SheetActivate, SheetDeactivate et WorkbookBeforeClose

Par avance, merci pour vos réponses
Guy
 

Guy_M

XLDnaute Occasionnel
Re : VBA: Peut-on tester si une variable objet est "vide" ?

Bonjour,

Merci Pierrot93 de m'avoir fait remarquer qu'un programme vaut mieux qu'un long discours
VB:
Sub testvarobject()

Dim x As Workbook
Dim xEstNothing As String

Debug.Print "Travail avec X non initialisé"
xEstNothing = IIf(x Is Nothing, "Vrai", "Faux")
Debug.Print "  testvarobject:Début:x Is Nothing: " & xEstNothing
Debug.Print "  testvarobject:err.Number avant x.Name: " & Err.Number
On Error Resume Next
Debug.Print "  testvarobject:x.Name: " & x.Name
Debug.Print "  testvarobject:err.Number après x.Name: " & Err.Number
Debug.Print "  testvarobject:err.Description: " & Err.Description
On Error GoTo 0

Set x = Workbooks.Add

Debug.Print
Debug.Print "Travail avec X créé (initialisé)"
xEstNothing = IIf(x Is Nothing, "Vrai", "Faux")
Debug.Print "  testvarobject:AprèsCréation:x Is Nothing: " & xEstNothing
Debug.Print "  testvarobject:err.Number avant x.Name: " & Err.Number
Debug.Print "  testvarobject:x.Name: " & x.Name
Debug.Print "  testvarobject:err.Number après x.Name: " & Err.Number

x.Close

Debug.Print
Debug.Print "Travail avec X (initialisé) après fermeture"
xEstNothing = IIf(x Is Nothing, "Vrai", "Faux")
Debug.Print "  testvarobject:AprèsFermeture:x Is Nothing: " & xEstNothing
Debug.Print "  testvarobject:err.Number avant x.Name: " & Err.Number
On Error Resume Next
Debug.Print "  testvarobject:x.Name: " & x.Name
Debug.Print "  testvarobject:err.Number après x.Name: " & Err.Number
Debug.Print "  testvarobject:err.Description: " & Err.Description
On Error GoTo 0

Set x = Nothing

Debug.Print
xEstNothing = IIf(x Is Nothing, "Vrai", "Faux")
Debug.Print "testvarobject:Avant End Sub:x Is Nothing: " & xEstNothing
End Sub

ce qui donne cette trace, où l'on constate que X n'est pas Nothing après la fermeture et que l'appel à .Name à ce moment là provoque une erreur laconique. Y a-t-il un test simple (pas un "on error resume next (...) x.name (...) if err.number=) pour tester x afin d'éviter la deuxième erreur ?

Code:
Travail avec X non initialisé
  testvarobject:Début:x Is Nothing: Vrai
  testvarobject:err.Number avant x.Name: 0
  testvarobject:err.Number après x.Name: 91
  testvarobject:err.Description: Variable objet ou variable de bloc With non définie

Travail avec X créé (initialisé)
  testvarobject:AprèsCréation:x Is Nothing: Faux
  testvarobject:err.Number avant x.Name: 0
  testvarobject:x.Name: Classeur18
  testvarobject:err.Number après x.Name: 0

Travail avec X (initialisé) après fermeture
  testvarobject:AprèsFermeture:x Is Nothing: Faux
  testvarobject:err.Number avant x.Name: 0
  testvarobject:err.Number après x.Name: -2147221080
  testvarobject:err.Description: Erreur Automation

testvarobject:Avant End Sub:x Is Nothing: Vrai

En espérant que maintenant je sois plus clair.

Par avance, merci pour vos réponses
Guy
 

Pierrot93

XLDnaute Barbatruc
Re : VBA: Peut-on tester si une variable objet est "vide" ?

Re,

vois pas trop ton problème.... mais si tu fermes ton classeur et que tu as une variable "public", préférable de réinitialisée à "nothing" cette même variable...
 

Guy_M

XLDnaute Occasionnel
Re : VBA: Peut-on tester si une variable objet est "vide" ?

Bonjour,

Le programme est là pour montrer le problème, le "x.close" est fait à la main par l'utilisateur, les "x.Name" sont dans les différentes procédures du UserForm (bouton par exemple). Dans ce cas, existe-t-il un test simple à appliquer à x pour déterminer que l'objet associé n'est plus en mémoire ?

A bientôt
Guy
 

Guy_M

XLDnaute Occasionnel
Re : VBA: Peut-on tester si une variable objet est "vide" ?

Bonjour,

J'ai trouvé une première solution qui devrait me garantir que les variables de type workbook sont toujours à Nothing quand leur classeur a été fermé par l'utilisateur : dans le code du UserForm, j'associe les évènements à la variable globale classeur. Lors de l'évènement de fermeture du classeur intervient, j'associe Classeur à Nothing (faut faire attention aux Application.EnableEvents = False qui traineraient, mais ça normalement, c'est moi qui gère).

VB:
Option Explicit
Private WithEvents Classeur As Workbook

Private Sub ClasseurCollecte_BeforeClose(Cancel As Boolean)
Set Classeur = Nothing
End Sub

Maintenant, je dois trouver comment gérer la suppression d'une feuille associée à une variable, sachant que l'évènement de suppression n'existe pas :-( (c'est surtout pour ce cas là que j'ai besoin de d'avoir un test simple de la variable.)

A bientôt
Guy
 
Dernière édition:

eriiic

XLDnaute Barbatruc
Re : VBA: Peut-on tester si une variable objet est "vide" ?

Bonjour,

Maintenant, je dois trouver comment gérer la suppression d'une feuille associée à une variable, sachant que l'évènement de suppression n'existe pas :-(
Si, tu as l'événement d'application Application.SheetBeforeDelete
Voir ici pour comment les utiliser : Excel Application Events And VBA

Et sans doute d'autres événements vont t'intéresser dans le cadre de ton projet. Voir ici la liste : Ce lien n'existe plus

eric
 

Guy_M

XLDnaute Occasionnel
Re : VBA: Peut-on tester si une variable objet est "vide" ?

Bonjour,

Je n'ai pas trouvé de références antérieures à office 2013.

Dans Excel 2007, j'ai essayé quand même essayé bien que l'IDE de VBA ne me propose pas cet évènement et, cet évènement ne se déclenche jamais.

Merci.

A bientôt
Guy
 

eriiic

XLDnaute Barbatruc
Re : VBA: Peut-on tester si une variable objet est "vide" ?

Re,

Je pensais que tu parlais des événements Application.
Effectivement SheetBeforeDelete a l'air récent, désolé.

Une piste a explorer : pour supprimer une feuille il faut qu'elle soit active, et sa suppression entraîne un événement Deactivate.
Ouvre le fichier joint et supprime une feuille de n'importe quel fichier ouvert (oui, sur un fermé c'est plus dur).
eric
 

Guy_M

XLDnaute Occasionnel
Re : VBA: Peut-on tester si une variable objet est "vide" ?

Merci Eric,

C'est ce que je fait actuellement et SheetBeforeDelete m'aurais grandement simplifié la vie : pour capturer la suppression d'une feuille, j'utilise l'évènement SheetDeactivate puis SheetActivate sachant que cet évènement se produit toujours dans le même classeur après suppression d'une feuille et ne se produit pas lors du changement de classeur (je trouve cela étrange).

Je l'ai programmé ainsi (j'ai une fonction qui retourne vrai si une feuille existe dans un classeur) :
VB:
Private WithEvents Excel As Application
Private NomFeuilleDesactivee As String
Private NomFeuilleASurveiller As String

Private Sub Excel_SheetActivate(ByVal Sh As Object)
If Not FeuilleExiste(NomFeuilleDesactivee, Sh.Parent) Then
    Debug.Print "Excel_SheetActivate: Suppression de feuille détectée : " & NomFeuilleDesactivee
    If NomFeuilleASurveiller = NomFeuilleDesactivee Then
        'Actions lorsque la feuille surveillée a été supprimée
    End If
End If
End Sub

Private Sub Excel_SheetDeactivate(ByVal Sh As Object)
NomFeuilleDesactivee = Sh.Name
End Sub

Private Sub UserForm_Initialize()
Set Excel = Application
End Sub
 

eriiic

XLDnaute Barbatruc
Re : VBA: Peut-on tester si une variable objet est "vide" ?

Bonjour,

Je pensais plutôt contrôler l'existence d'une feuille après son deactivate pour mise à jour de tes variables si supprimée.
J'avais oublié le fichier...
Normalement voit les suppressions de feuille de tous les classeurs. Délai 1s après en espérant que ça suffise, sinon il faudra changer le système de timer.
eric

PS: j'ai oublié la désactivation du timer sur Close au cas où.
 

Pièces jointes

  • Suppression feuille - Détection.xls
    31.5 KB · Affichages: 48

Guy_M

XLDnaute Occasionnel
Re : VBA: Peut-on tester si une variable objet est "vide" ?

Bonjour,

Pas besoin de gérer le timer sur Close, l'évènement "App_SheetDeactivate" ne se produit pas à la fermeture du Workbook.

L'idée d'utiliser ".Index" pour tester la validité d'un objet WorkSheet (WorkBook, tout objet membre d'une collection ?) me plaît, cela me devrait me permettre d'écrire une fonction qui ferait ce que je cherche et dans ce cas, la gestion de ne serait plus nécessaire.

Merci Eric

A bientôt
Guy Marty
 

Discussions similaires

Statistiques des forums

Discussions
312 191
Messages
2 086 052
Membres
103 109
dernier inscrit
boso_vs_viking