什么时候应该杀死Excel VBA变量或将其设置为Nothing?

时间:2013-09-26 20:44:12

标签: variables excel-vba vba excel

在过去的两年里,我一直在教自己Excel VBA,我认为有时候在代码段的末尾处理变量是合适的。例如,我已经看到它在Ron de Bruin's code for transferring Excel to 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

我已经对此进行了一些搜索,发现除了如何做之外,在a statement that no local variables need to be cleared的一个论坛帖子中发现的很少,因为它们不再存在于End Sub。基于上面的代码,我猜测在End Function可能不正确,或者在其他情况下我没有遇到过。

所以我的问题归结为:

  • 网上有什么地方可以解释变量清理的时间和原因,而我还没找到它?

如果没有,请有人在这里解释......

  • 什么时候需要Excel VBA的变量清理,什么时候不可以?
  • 更具体地说......是否有特定的变量用途(公共变量? 函数定义的变量?)仍然在内存中加载更长时间 如果我不清洁,可能会造成麻烦 在我自己之后?

3 个答案:

答案 0 :(得分:44)

VB6 / VBA使用确定性方法来处理令人讨厌的对象。每个对象存储自身的引用数。当数字达到零时,对象将被销毁。

当对象变量超出范围时,它们保证被清除(设置为Nothing),这会减少各自对象中的引用计数器。无需手动操作。

只有两种情况需要明确清理:

  1. 如果希望在变量超出范围之前销毁对象(例如,您的过程将花费很长时间来执行,并且对象拥有资源,那么您希望将对象销毁为尽快释放资源)。

  2. 当两个或多个对象之间有循环引用时。

    如果objectA存储对objectB的引用,而objectB存储对objectA的引用,则除非您通过明确设置制动链,否则这两个对象永远不会被销毁objectA.ReferenceToB = NothingobjectB.ReferenceToA = Nothing

  3. 您显示的代码段错误。无需手动清理。进行手动清理甚至是有害的,因为它会为您提供false sense of more correct code

    如果在类级别有变量,则在销毁类实例时将清除/销毁它。如果需要,可以提前销毁它(参见项目1.)。

    如果模块级别有变量,则在程序退出时将清除/销毁该变量(或者,如果是VBA,则重置VBA项目时)。如果需要,可以提前销毁它(参见项目1.)。

    变量的访问级别(公共与私有)不会影响其生命周期。

答案 1 :(得分:3)

VBA使用由reference counting实现的垃圾收集器。

可以有多个对给定对象的引用(例如,Dim aw = ActiveWorkbook创建对Active Workbook的新引用),因此垃圾收集器只有在清楚没有其他引用时才清理对象。设置为Nothing是递减引用计数的明确方法。退出范围时,计数会隐式递减。

严格地说,在现代Excel版本(2010+)中,设置为Nothing不是必需的,但是旧版本的Excel存在问题(其解决方法是明确设置)

答案 2 :(得分:0)

我至少有一种情况不会自动清理数据,最终将导致“内存不足”错误。 在UserForm中,我有:

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

在销毁用户窗体(在Unload Me之后)时,未取消分配为在mainPicture中加载的数据分配的内存。我必须添加一个明确的

mainPicture = Nothing

在终止事件中。

相关问题