为什么我在将一个范围分配给变量数组时遇到问题

时间:2014-01-27 16:56:00

标签: arrays excel vba excel-vba

我遇到了一些非常简单的代码问题。让我详细说明事实,看看是否有其他人可以复制这种行为。如果有人可以复制,我想解释它为什么会发生。

因此,让我从一个非常简单的代码行开始:

Dim arr() As Variant
arr = Range("A1:A10")

这样做符合预期,arr被赋予A1:A10

的值

现在为什么以下代码行不起作用?

Dim arr() As Variant
arr = WorkSheets("Sheet1").Range("A1:A10")

我得到运行时错误'13'类型不匹配,即使成功地为数组分配了相同的范围,只是没有Worksheet值。

但是

Dim arr As Variant
arr = Worksheets("Sheet1").Range("A1:A10")

并且

Dim arr() As Variant
arr = Application.Transpose(Application.Transpose(Worksheets("Sheet1").Range("A1:A10")))

工作

现在,在你回答之前,请允许我给你一些更多的事实。

Dim arr() As Variant
arr = Worksheets(1).Range("A1:A10")

不起作用

并使用Sheets代替Worksheets也会产生同样的错误。

通过使用Range("A1:A10").Worksheet.Name确保它与活动引用表相同,在输出代码后确实显示Sheet1

没有其他工作簿是打开的,因此也无法引用其他工作簿。

现在最后一点代码只会增加我的困惑,因为它完全有效!

Dim arr() As Variant
Dim SampleRange As Range

Set SampleRange = Worksheets("Sheet1").Range("A1:A10")
arr = SampleRange

因此,当我将其分配给范围变量时,使用在同一张纸上以相同方式定义的相同方法。并使用它!正如预期的那样,这适用于WorkSheetsSheets函数,无论我如何定义工作表(我可以使用索引或工作表的名称,所有工作正常)

如果它可以帮助任何人,我在Windows XP计算机上使用Excel 2007进行测试。我还没有在任何其他机器上测试它,但我计划在Windows 7和8上测试2003年和2010年,但还没有机会。

更新: 不是100%确定这是否与数组完全相同,但从浅视图看似乎是:

 Range("B1:B3") = Range("A1:A3") 

上面的代码不起作用,即使A1:A3填充,日期,数值,字符串,公式任何东西,它都会将空白写入B1:B3

但是

Range("B1:B3").Value = Range("A1:A3").Value

并且

Range("B1") = Range("A1")

工作!

还有以下工作:

Range("B1:B3") = Application.Transpose(Application.Transpose(Range("A1:A3")))

3 个答案:

答案 0 :(得分:31)

不,这不是一个错误。

  

重点是Value是Range Object的默认属性,为什么不隐式使用它?你看过我链接的问题了吗? (来自CHAT

发布以前答案的专家已经详细解释过了。我会将解释保持在最低限度,因此如果您还有任何问题,请告诉我。

让我们先了解我们的对象。我创建了这个小桌子,清楚地显示了我们处理的内容,这样就没有混淆了。

enter image description here

您还可以添加Watch以查看特定对象的Type,如下图所示。

enter image description here

所以当你说

arr = Range("A1:A10")

Excel知道默认属性为.Value。但是在其他情况下,它不知道,因为Excel不是读者,或者说足够智能,以了解您是否要将Worksheets("Sheet1").Range("A1:A10")用作RangeVariant

将对象明确指定为Range后,Excel就会知道您想要的内容。例如,这有效。

Dim arr() As Variant
Dim Rng As Range  
Set Rng = Worksheets("Sheet1").Range("A1:A10")
arr = Rng

答案 1 :(得分:3)

让我澄清一下我的评论 它不适合评论我发布它作为答案只是为了至少清楚我的观点。

Dim arr As Variant '~~> you declare arr as Variant as what Tim said
这是什么意思?
这意味着arr可以采用任何形式(例如整数,字符串,数组,对象和所有其他形式Variable Type

Dim arr() as Variant '~~> you declare arr() as array which may contain Varying `Data Type`
这是什么意思?
这意味着arr()数组变量可以存储不同的Data类型 这不包括ObjectsCollection of Objects

现在,为什么以下有效:

1. Dim arr() As Variant: arr = Range("A1:A10")
2. Dim arr() As Variant: arr = Sheet1.Range("A1:A10")
3. Dim arr() As Variant: arr = Sheets("Sheet1").Range("A1:A10").Value

这也有效:

4. Dim arr() as Variant
   Dim rng as Range

   Set rng = Sheets("Sheet1").Range("A1:A10")
   arr = rng

以上是有效的,因为您没有尝试将Collections of Objects分配到数组中 相反,您要分配特定的实体或价值 Range是一个对象,但不是Collection of Objects 第1个示例是直接访问Sheets Collection Object 因为你使用的是Sheet1对象而不是Sheet,所以你的Collection of Sheet Objects也是如此。 No.3是不言自明的,您将.Value分配给arr数组 No.4有效,因为rng已经是Range的{​​{1}}对象,而Set又不是Collection of Objects

所以这个:

Dim arr() As Variant

arr = Sheets("Sheet1").Range("A1:A10")

不起作用,因为Excel会将其视为尝试从Object分配Sheets Collection of Objects,从而发生错误。
我希望这有点道理。

答案 2 :(得分:2)

我会说某个东西的数组与某个东西不同,因为这个东西可以是一些其他的东西。如果将某些内容定义为数组,则为其分配的内容必须是数组,无论是数字,文本,范围,图表对象等数组。

当我们不期望的事情发生时,我相信它是内置的数据类型转换,它使我们大多数时间都很容易。此转换可能必须是直接对象,而不是对象的属性。

例如,Rows和Cols的类型为 Long ,但您可以在其中抛出Byte / Double类型:

Cells(1,1.5)给出Cells(1,2)

的值

您不必将1.5转换为Long; Excel在后台为您完成所有工作。

当您定义某个数组并为其分配内容时,Excel会在场景后面键入匹配并尽可能设置值。

在立即窗口中查看这些:

?typename(Range("A1:A10").Value)为您提供Variant()< - 这就是为什么它可以在Dim arr() As Variant上运行而没有任何问题

?typename(Range("A1:A10"))为您提供Range。但是当您将arr分配给Dim arr() As Variant时,Excel会使用该范围的值将范围转换为数组。

但是,如果Excel无法直接访问该对象,则Excel似乎无法转换,除非您为其创建了内存。例如:

Dim arr() As Variant, oRng As Range
Set oRng = Range("A1:A10")
arr = oRng
Set oRng = Worksheets("Sheet1").Range("A1:A10")
arr = oRng

上面的代码都很好,但它不能一次转换和分配arr = ThisWorkbook.Worksheets("Sheet1").Range("A1:A10"),除非你向它抛出一个数组(ThisWorkbook.Worksheets("Sheet1").Range("A1:A10").Value的类型为 Variant())。