我遇到了一些非常简单的代码问题。让我详细说明事实,看看是否有其他人可以复制这种行为。如果有人可以复制,我想解释它为什么会发生。
因此,让我从一个非常简单的代码行开始:
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
因此,当我将其分配给范围变量时,使用在同一张纸上以相同方式定义的相同方法。并使用它!正如预期的那样,这适用于WorkSheets
和Sheets
函数,无论我如何定义工作表(我可以使用索引或工作表的名称,所有工作正常)
如果它可以帮助任何人,我在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")))
答案 0 :(得分:31)
不,这不是一个错误。
重点是Value是Range Object的默认属性,为什么不隐式使用它?你看过我链接的问题了吗? (来自CHAT)
发布以前答案的专家已经详细解释过了。我会将解释保持在最低限度,因此如果您还有任何问题,请告诉我。
让我们先了解我们的对象。我创建了这个小桌子,清楚地显示了我们处理的内容,这样就没有混淆了。
您还可以添加Watch
以查看特定对象的Type
,如下图所示。
所以当你说
时arr = Range("A1:A10")
Excel知道默认属性为.Value
。但是在其他情况下,它不知道,因为Excel不是读者,或者说足够智能,以了解您是否要将Worksheets("Sheet1").Range("A1:A10")
用作Range
或Variant
将对象明确指定为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
类型
这不包括Objects
或Collection 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())。