web-dev-qa-db-fra.com

Quand une variable VBA Excel doit-elle être supprimée ou définie sur Nothing?

Je me suis enseigné Excel VBA au cours des deux dernières années, et j’ai l’idée qu’il est parfois approprié de disposer des variables à la fin d’un segment de code. Par exemple, je l'ai vu faire dans ce bit adapté de code de Ron de Bruin pour le transfert d'Excel en HTML :

Function SaveContentToHTML (Rng as Range)

        Dim FileForHTMLStorage As Object
        Dim TextStreamOfHTML As Object
        Dim TemporaryFileLocation As String
        Dim TemporaryWorkbook As Workbook

...

        TemporaryWorkbook.Close savechanges:=False
        Kill TemporaryFileLocation
        Set TextStreamOfHTML = Nothing
        Set FileForHTMLStorage = Nothing
        Set TemporaryWorkbook = Nothing

End Function

J'ai fait quelques recherches à ce sujet et ai trouvé très peu au-delà de la façon de le faire, et dans un post de forum affirmation qu'aucune variable locale ne doit être effacée , puisqu'elles cessent d'exister à End Sub. D'après le code ci-dessus, je suppose que ce n'est peut-être pas vrai à End Function, ou dans d'autres circonstances que je n'ai pas rencontrées.

Donc ma question se résume à ceci:

  • Existe-t-il quelque part sur le Web qui explique quand et pourquoi un nettoyage de variable, et que je ne l’ai tout simplement pas trouvé?

Et si ce n’est pas quelqu'un qui est ici, veuillez expliquer ...

  • Quand le nettoyage de variables pour Excel VBA est-il nécessaire et quand ce n'est pas le cas?
  • Et plus précisément ... Y a-t-il des utilisations de variables spécifiques (variables publiques? Variables définies par une fonction?) Qui restent chargées en mémoire plus longtemps que les subs, et pourraient donc causer des problèmes si je ne nettoie pas après moi-même?
29
Instant Breakfast

VB6/VBA utilise une approche déterministe d’objets déstabilisants. Chaque objet stocke le nombre de références à lui-même. Lorsque le nombre atteint zéro, l'objet est détruit.

Il est garanti que les variables d’objet sont nettoyées (définies sur Nothing) quand elles sortent de la portée, cela décrémente les compteurs de référence dans leurs objets respectifs. Aucune action manuelle requise.

Il n'y a que deux cas où vous souhaitez un nettoyage explicite:

  1. Lorsque vous souhaitez qu'un objet soit détruit avant que sa variable ne devienne hors de sa portée (par exemple, l'exécution de votre procédure prendra beaucoup de temps et l'objet contient une ressource. Vous souhaitez donc détruire l'objet le plus tôt possible pour libérer le contenu. Ressource).

  2. Lorsque vous avez une référence circulaire entre deux objets ou plus.

    Si objectA stocke une référence à objectB et que objectB enregistre une référence à objectA, les deux objets ne seront jamais détruits à moins que vous ne bloquiez la chaîne de manière explicite. réglage objectA.ReferenceToB = Nothing ou objectB.ReferenceToA = Nothing.

L'extrait de code que vous montrez est incorrect. Aucun nettoyage manuel n'est requis. Il est même dangereux de faire un nettoyage manuel, car cela vous donne un faux sens d’un code plus correct .

Si vous avez une variable au niveau classe, elle sera nettoyée/détruite lors de la destruction de l'instance de classe. Vous pouvez le détruire plus tôt si vous voulez (voir item 1.).

Si vous avez une variable au niveau du module, elle sera nettoyée/détruite à la fin du programme (ou, dans le cas de VBA, à la réinitialisation du projet VBA). Vous pouvez le détruire plus tôt si vous voulez (voir item 1.).

Le niveau d'accès d'une variable (public ou privé) n'affecte pas sa durée de vie.

46
GSerg

VBA utilise un ramasse-miettes implémenté par comptage de références .

Il peut y avoir plusieurs références à un objet donné (par exemple, Dim aw = ActiveWorkbook crée une nouvelle référence dans Active Workbook), de sorte que le ramasse-miettes nettoie un objet uniquement s’il est clair qu’il n’existe aucune autre référence. La définition de la valeur Nothing est un moyen explicite de décrémenter le nombre de références. Le compte est implicitement décrémenté lorsque vous quittez la portée.

Strictement parlant, dans les versions modernes d'Excel (2010+), définir sur Aucune n'est pas nécessaire, mais il existait des problèmes avec les versions antérieures d'Excel (pour lesquelles la solution de contournement devait être explicitement définie).

3
SheetJS

J'ai au moins une situation dans laquelle les données ne sont pas automatiquement nettoyées, ce qui pourrait éventuellement entraîner des erreurs "Mémoire insuffisante". Dans un UserForm j'avais:

Public mainPicture As StdPicture
...
mainPicture = LoadPicture(PAGE_FILE)

Quand UserForm a été détruit (après Unload Me) la mémoire allouée pour les données chargées dans mainPicture n'était pas désaffectée. Je devais ajouter un explicite

mainPicture = Nothing

dans l'événement de terminaison.

0
Tomasz