首页 > 解决方案 > “ThisWorksheet”等价物?

问题描述

在 Excel 中,我有一些属于Worksheet模块的宏。

在代码中,我想确保引用的范围是该工作表的一部分。

例如,在我的Main Sheet工作表模块中,假设我有:

Sub test()
Dim rng as Range
Set rng = Range("A1")
End Sub

当然,我想明确地给工作表指定范围。通常,我会做

Set rng = Worksheets("Main Sheet").Range("A1")

但我很好奇,因为我的代码在工作表模块中,我该如何引用该工作表?我在想类似的东西,ThisWorksheet但这不是VBA中的方法(但是ThisWorkbook,这就是我想尝试的原因)。

我唯一的其他想法是,由于我的宏位于工作表模块内,因此“未分配”范围变量隐式引用Main Sheet并且不能引用任何其他工作表的单元格。

我是否理解正确,或者有什么方法可以参考存储运行代码的工作表?

标签: vbaexcel

解决方案


工作表模块是一个文档模块,它和其他任何模块一样是类,除了它从接口继承(是的,继承,如类继承!)成员Worksheet,并且作为文档模块,创建它的实例的唯一方法是通过宿主应用程序的对象模型(即ThisWorkbook.Worksheets.Add本质上是一个工厂方法)。

作为一个类模块,该模块的工作表对象是该类的一个实例,例如,Sheet1该类包含您放入其中的任何成员,以及从接口继承的每个成员Worksheet......包括一个Range属性。

因此,Range工作表模块中的不合格调用引用该工作表原因仅仅是因为 VBA 语言的范围规则 - 给定以下代码:

foo = Range("B12").Value2
  1. 如果该范围内有一个名为 的局部变量Range,那么这就是Range所指的。

  2. 如果该模块中有一个名为 的成员Range,那么这就是Range所指的。

  3. 如果当前项目中有一个名为 的全局变量Range,那么这就是Range所指的。

  4. 如果在引用的项目或名为 的类型库中有一个全局范围的标识符Range,那么这就是Range所指的。

“Sheet1”的成员包括一个“范围”属性,它是“工作表”类的成员

您可以Range通过使用关键字限定调用来消除歧义,该Me关键字返回对当前对象的引用,在这种情况下通过Sheet1接口(仍然假设您在 的代码隐藏中Sheet1):

foo = Me.Range("B12").Value2

如果您在 , 的代码隐藏中,则该代码将起作用,Sheet1如果您在 , 的代码隐藏中Sheet1Sheet2则该代码Sheet2将无法在标准模块中编译。

但它的性质和含义Me值得更多关注。


关于我'

Me是一个保留名称(您不能使用该名称的变量),它指的是只能在运行时存在于过程范围内的东西:当前对象。在幕后,当您DoSomething针对Class1对象进行成员调用时,调用本质上是这样的:

Set obj = New Class1
Class1.DoSomething obj

这意味着DoSomething在 VBA 中看起来像这样:

Public Sub DoSomething()
End Sub

但是 VBA 是这样看的:

Public Sub DoSomething(ByVal Me As Class1)
End Sub

这使得typeMe的隐式局部范围ByVal参数Class1,并且在DoSomething范围内它包含对调用者当前正在使用的任何对象的引用。

这基本上是我理解“我”(没有花,没有蜜蜂)文章的症结=)

相关语言规范


当您在标准模块中时,不合格的Range调用遵循完全相同的范围规则:

  1. 如果该范围内有一个名为 的局部变量Range,那么这就是Range所指的。

  2. 如果该模块中有一个名为 的成员Range,那么这就是Range所指的。

  3. 如果当前项目中有一个名为 的全局变量Range,那么这就是Range所指的。

  4. 如果在引用的项目或名为 的类型库中有一个全局范围的标识符Range,那么这就是Range所指的。

(假设该模块/项目中没有出现标识符的阴影)Range

在这种情况下,全局范围的标识符可以在隐藏Global模块中找到:

'_Global' 的成员包括一个 'Range' 属性


推荐阅读