在全局变量中存储范围引用

时间:2015-04-09 11:45:04

标签: excel vba excel-vba named-ranges

我使用位于不同工作表中的多个命名范围。在整个VBA代码中,我需要在许多情况下读取和写入这些范围。

所以我的问题是:在全局变量中存储这些范围引用以便快速访问的正确方法是什么?或者有更好的方法吗?

我尝试声明全局变量:

Public WS_BOARD As Worksheet
Public RNG_BOARD As Range

并在Workbook_Open上初始化它们:

Private Sub Workbook_Open()
    Set WS_BOARD = Worksheets("BOARD")
    Set RNG_BOARD = WS_BOARD.Range("NR_BOARD")
End Sub

这没关系,除非我的代码崩溃,这些全局变量重置为Nothing并且不能再使用(即在工作表事件处理程序中)。

当然,我总是可以使用像

这样的东西
Worksheets("BOARD").Range("NR_BOARD")

我的代码中到处都是,但我认为它会影响性能,因为它显然需要使用字符串名称查找对象,更不用说它不是DRY了。

3 个答案:

答案 0 :(得分:0)

一种方法是将它们“加载”到内存中,然后将它们作为参数传递到其他子/函数中。
Passing Variables By Reference And By Value

其次,您可以将它们声明为模块范围变量(类似于public,但仅在您声明它们的模块中)。
Scope of variables in Visual Basic for Applications

第三,你的方式
Scope of variables in Visual Basic for Applications

答案 1 :(得分:0)

每个工作表都有一个Name属性(标题标题)和一个CodeName属性。如果在代码中使用CodeName,则不需要变量。与userform一样,工作表的代码名称在您使用时会自动实例化。在项目浏览器中选择项目下的工作表(Ctrl + R),转到Propeties(F4)并将(Name)更改为一个有意义的CodeName。然后,Project Explorer将把工作表显示为

wshDataEntry (Data Entry)

如果您创建了CodeName wshDataEntry,并且标签显示为Data Entry

对于Ranges,我在电子表格中使用了已定义的名称。它就像一个永远不会超出范围的全局变量。如果您有需要在各种程序中阅读的利息单元,请将其命名为Interest_Rate。然后在您需要的每个程序的顶部

Set rInterest = wshDataEntry.Range(gsNMINTEREST)

其中gsNMINTEREST是一个保存“Interest_Rate”的全局字符串变量。如果单元格移动,您只需移动命名范围即可使代码生效。如果将名称更改为“LiborPlusFour”,则只需更新全局变量。很干。

是的,性能略有下降,VBA每次都会查找指定的范围。除非你计算出一个性能问题并将其识别为阻力,否则我不会担心。

我在范围内保留全局变量(当然我非常明智地使用它们)的一种方法是初始化过程。

Public Sub Initialize()

    If gclsApp Is Nothing Then
        Set gclsApp = New CApp
        'do some other setup
    End If

End Sub

然后我在我需要的任何模块的顶部调用Initialize过程。如果它不是什么,那么它不会重置变量。不过,我不确定检查Nothing和查找命名范围的性能影响。

答案 2 :(得分:0)

全局变量通常不是一个好主意。在某些情况下,他们是必要的,但这不是其中之一。

我认为您不应该担心通过字符串名称查找几个范围会对性能产生影响。我有数百个命名范围的工作表,我从来没有,永远观察到这会对性能产生负面影响。

您是否有具体证据表明这会降低您的代码速度?如果没有,那就不要浪费时间担心它。

我经常这样做来定义范围:

Type RangesType
    board As Range
    plank As Range
    wood As Range
End Type

Function GetRanges() As RangesType
    With GetRanges
        Set .board = Range("board")
        Set .plank = Range("plank")
        Set .wood = Range("wood")
    End With
End Function

然后我像这样使用它们:

Sub something()
    Dim rngs As RangesType: rngs = GetRanges

    rngs.board = "My favourite board"
    rngs.wood = "Chestnut"
    'etc.

End Sub

是的,如果你有很多潜艇,范围会被他们的名字重复提取,不,这不会对性能产生任何明显的影响。