【问题标题】:Why am I having issues assigning a Range to an Array of Variants为什么我在将范围分配给变体数组时遇到问题
【发布时间】:2014-02-18 15:22:05
【问题描述】:

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

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

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

这正如预期的那样,arr 被分配了 A1:A10 的值

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

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

我得到一个运行时错误“13”类型不匹配,即使相同的范围已成功分配给数组,只是没有工作表值。

但是

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 进行测试。我还没有在任何其他机器上测试过它,但我计划在 2003 年和 2010 年在 Windows 7 和 8 上进行测试,只是还没有机会。

更新: 不能 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")))

【问题讨论】:

  • 我认为这与引用 Range 的默认行为有关。通常Range(X) 可用于引用范围X 的内容。如果我们将它实例化为工作表的 Range 属性,我想我们指的是它的硬编码“范围”。但是,这并不能解释为什么将其设置为变量会绕过它。希望有人能过来解释一下。不过,Value 可以为我解决这个问题。 Win7,XL2010。
  • 我不知道为什么第二种方法在第一种方法有效时不起作用。但是,这通常不是您将范围直接分配给数组的方式:通常您会将arr 声明为Variant,而不是作为变量数组,这就是您在这里所拥有的。仅使用常规 Variant 您将看不到此行为。将.Value 添加到第二种方法的末尾也可以解决问题,因此必须与依赖两种方法之间不同的默认属性有关。
  • @user2140261,将Dim arr() As Variant 更改为Dim arr As Variant 为我解决了问题,arr = Worksheets(1).Range("A1:A10") 工作正常!
  • @simoco 是正确的。删除 () 并离开 Dim arr As Variant 将更正 Worksheets... 部分的问题。现在,如何理解这一切。 :D
  • @simoco 是的,以这种方式调暗它也为我解决了问题,据记录,我所说的文章是 Here

标签: arrays vba excel


【解决方案1】:

不,这不是错误。

关键是 Value 是 Range 对象的默认属性,那为什么不隐式使用呢?你看过我链接的问题吗? (来自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 让 Watch 显示类型,我一直在使用 TypeName 和 VarType,每个项目都返回 Range
  • 希望澄清.Value 何时是默认属性,何时不是:)
  • because Excel is not a mind reader or let's say intelligent enough 加一。这是最重要的事实。
  • 为什么 Worksheets("Sheet1").Range("A1:A10") 会被视为变体,而不是 Range("A1:A10")?
【解决方案2】:

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

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
No.1 示例是直接的,无需访问Sheets Collection Object

No.2 也是如此,因为您使用的是 Sheet1,它是 Sheet 对象,但不是 Collection of Sheet Objects
No.3 是不言自明的,您将 .Value 分配给 arr 数组。
No.4 有效,因为rng 已经是SetRange 对象,这又不是Collection of Objects

所以这个:

Dim arr() As Variant

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

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

【讨论】:

  • Range("A1:A3")Sheets("Sheet1").Range("A1:A3") 都是 Range Objects,不管你怎么说这是事实。您可以通过多种方式对它们进行类型转换,并且测试两个版本的每种方式都将返回Range 类型。并且正因为如此 BOTH 应该隐式工作或失败。此外,您说 Sheets("Sheet1") 返回工作表对象的集合是错误的。 Sheets 本身 IS 是工作表的集合,当传递工作表名称的参数时,Sheets 类返回 Sheet 对象而不是其整个集合。和 Mehow 一样,我认为这只是一个错误。
  • 我认为@Siddharth Rout 已经在他的帖子中明确了这一点。对不起,我解释事情的方式很草率。 :) 但我很高兴我们以某种方式消除了我们的困惑。
【解决方案3】:

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

当事情出乎我们的意料时,我相信是内置的数据类型转换让我们大部分时间都变得轻松。这种转换可能必须是直接对象,而不是对象的属性。

例如,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 会使用该 Range 的值将 Range 转换为 Array。

但是,如果 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").ValueVariant()类型)。

【讨论】:

  • 加一。再次归结为@Tim Williams 声明,将变量声明为变体不同于声明变体类型的数组变量。
  • 这是错误的!我不明白为什么你不能理解。因为?typename(Worksheets("Sheet1").Range("A1:A10")) ALSO 为您提供 Range 但它确实 NOTDim arr() As Variant 一起工作,这很烦人有多少人可以在没有实际事实证据的情况下获取信息来支持声明,除了说它就是这样。然后使用一个认为它是事实陈述的陈述。
猜你喜欢
  • 1970-01-01
  • 2012-10-25
  • 2016-02-28
  • 2018-11-25
  • 2019-08-25
  • 2023-01-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多