Excel的VBA——设置范围

9

我有一个关于设置范围的问题。我正在尝试某些方法,但是它没有起作用。假设我有一个范围r,例如我写了:

set r = range("a1")

但是这个范围只在当前工作表中有效。例如,如果我在工作表1上并且写入 r.value = 1,则会更改活动工作表中该单元格的值。现在我想要更改另一个工作表上特定范围的值。所以我写下:

worksheets("specificworksheet").r.value =1

但是当我写这个时,它显示对象不支持此属性或方法。为什么会这样?我如何为另一个工作表分配已经设置的范围?在这种情况下,可以这样写:

worksheets("specificworksheet").range("a1").value=1 

这解决了我的问题,但有时我有更复杂的范围,例如如果我将一个单元格分配给r,而我在其中使用了cells.find(...)。


1
赞赏你没有默认使用 SelectActivate,因为意识到未经限定的 Range 调用会隐式地引用活动工作表。 - Mathieu Guindon
3个回答

8
当你执行以下操作时:
Set r = Range("A1")

你实际上正在做的是这个:

真正所做的是:

Dim r As Variant
Set r = Application.ActiveSheet.Range("A1")

所以,声明所有变量,并且在每个模块的顶部始终指定Option Explicit - 这样VBA将拒绝编译使用未声明变量(或打字错误)的代码。并使用显式类型声明您的变量:

Dim r As Range

一个 Range 对象知道它所属的工作表,这就是为什么,正如你所注意到的那样,这个范围对于活动工作表有效。即使您激活另一个工作表(99.999% 的情况下您不需要这样做),它也会保留在该工作表上。

这就是为什么您不能这样做的原因:

Worksheets("Sheet42").r.Value = 1

因为r不是Worksheet对象的成员 - 它是一个指向非常具体的工作表地址的本地对象变量。现在,当您执行Worksheets("Sheet42")时,实际上访问的是Worksheets集合类的默认属性,即其Item属性:

Dim sheet As Worksheet
Set sheet = Worksheets.Item("Sheet42")

Worksheets 集合的 Item 属性返回一个 Object,这意味着在此后添加的任何成员调用都将是晚期绑定/在运行时解析的:

Dim obj As Object
Set obj = Worksheets.Item("Sheet42")
obj.AnythingYouWantHereWillCompileAnyway

在运行时,VBA查询对象的接口以寻找AnythingYouWantHereWillCompileAnyway,但未找到该成员 - 这就是出现运行时错误438“对象不支持此属性或方法”的原因。
您可以通过使用早期绑定调用将该类型安全性移回编译时(而不是运行时),即使用Worksheet接口/类而不是Object来工作。
Dim obj As Worksheet
Set obj = Worksheets.Item("Sheet42")
obj.AnythingYouWantHereWillCompileAnyway 'nope. that won't compile anymore.

当你询问“如何为另一个工作表分配已经设置的区域?”时,你认为Range对象仅仅是一个地址,这个假设是错误的。 Range不仅仅只是一个地址,如果它只是一个地址,那么它将成为一个字符串文字,而不是一个对象。
如果你想要一个代表地址的变量,你可以使用String变量来实现:
Dim a As String
a = "A1"

Dim r1 As Range
Set r1 = Sheet1.Range(a)

Dim r2 As Range
Set r2 = Sheet2.Range(a)

2
@Downvoter,我很想改进这个答案。能告诉我哪里有问题吗? - Mathieu Guindon
2
再次,解释和解决方案都更好了。我曾考虑过添加字符串方法,但后来忙了起来,现在回来了,我会保持原样,并希望OP改用你的方法。 - Scott Craner
1
编辑以包括更完整的解释OP的运行时错误438。 - Mathieu Guindon
1
我猜想 @Downvoter 想要一个快速的“试一下这个”的复制粘贴答案 - 那就去给我所有的回答点踩吧,因为我不会那样做。 - Mathieu Guindon
1
太好了,谢谢。我因为你的回答学到了一些东西。+1 - Alex M
显示剩余4条评论

5
你可以使用地址:

worksheets("specificworksheet").range(r.Address).value=1 

2

使用With-End With语法,并在每个Range()(和Cells())规范前加上一个点

With Worksheets("specificworksheet")
    .Range("a1").Value = 1
    .Range("B3:C5").Value = 2
End With

投票者,我很想改进这个答案。能告诉我哪里有问题吗?(希望@Mat'sMag不介意我借用他美丽的措辞) - user3598756

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接