【问题标题】:VBA, Excel, use Range to fill 2D-Array [duplicate]VBA,Excel,使用范围填充二维数组[重复]
【发布时间】:2016-01-16 05:51:37
【问题描述】:

我不明白这种行为:

Sub tuEs()
    Dim A() As Variant
    A = Range("A1:A10") ' works

    Dim B() As Variant
    B = ActiveSheet.Range("A1:A10") ' Type mismatch
End Sub

第一个版本有效,第二个版本无效。为什么?有什么区别?

【问题讨论】:

  • 是否有可能没有工作表处于活动状态?尝试使用Sheets(sheet_name)
  • 如果你把.Value放在后面,它们都可以工作。
  • 这很奇怪。这可能更奇怪:将 C 声明为一个变体(C 后面没有括号)并将行 B = ActiveSheet.Range("A1:A10") 替换为 C = ActiveSheet.Range("A1:A10") 行,然后是 B=C 行,它将按预期工作。 @ScottCraner 是正确的,有一些变通方法,但它似乎仍然有些神秘。
  • 鉴于 Excel 不是开源的,这可能是任何人所能做的最好的事情之一就是做出有根据的猜测。变体如何处理动态类型与 VBA 如何决定是否需要使用默认属性之间似乎存在一种奇怪的交互。
  • @GSerg 如果有的话——分配给B() 应该可以工作(因为B() 不能保持一个范围——所以它必须是你的值试图分配)但分配给B 应该会触发歧义(因为它可以保持一个范围)。因此,我同意您对重复问题的接受答案(令人印象深刻,就像 Siddharth Rout 的大多数答案一样)并不能完全解释发生了什么。

标签: vba excel


【解决方案1】:

解决方法是在范围末尾添加“.value”。这通常是一个让事情变得非常明确的好主意(你可以省略它的原因是因为 value 是 range 对象的默认属性)

我将所有值添加到手表以查看发生了什么,显然存在 Excel 无法有效(和隐式)动态转换对象的问题。请注意图片中“ActiveSheet.Range("A1:A10") 失败的表达式的类型是:Variant/Object/Range;从 Variant 到对象的转换最有可能导致问题。

强制它正确转换的一种方法是将过程分成两部分,第一部分转换为范围,第二部分转换为变量数组。看我的例子

还要注意,如果您将变量单独声明为变量而不是变量数组(dim E 而不是dim E()),它将得到它,因为它会适应需要的内容。

Sub tuEs()

    'Works
    Dim A() As Variant
    A = Range("A1:A10")

    ' Type missmatch
    Dim B() As Variant
    B = ActiveSheet.Range("A1:A10")

    ' Fix to make it cast properly
    Dim C() As Variant
    Dim r As Range
    Set r = ActiveSheet.Range("A1:A10")
    C = r

    ' Best of all options
    Dim d As Variant
    d = ActiveSheet.Range("A1:A10").Value    

End Sub

希望这有点清楚。

【讨论】:

  • 经过反思,+1。 Variant/Object/RangeVariant/Range 之间的区别很有趣。我认为你强调它是正在发生的事情的核心是正确的,尽管在某些方面它只会加深谜团。
  • 这是 VB 有时有时不能处理后期绑定、默认属性和数组的组合的另一个例子。模拟ActiveSheet.Range 行为的一种方法是执行Dim O as Variant, A() as Variant: Set O = Range("A1:A10") : A = O
【解决方案2】:

这确实是个谜!但这有效(无需声明变体对象数组,只需声明一个变体)。至于为什么它在你的代码中不起作用,我恐怕无法回答。

Dim B As Variant ' instead of Dim B() as Variant
B = ActiveSheet.Range("A1:A10")

【讨论】:

  • 这已经是answered
  • 我很抱歉,没有阅读完整的帖子
【解决方案3】:

起初我认为这是一个语法问题 - 一些隐藏的歧义导致解释器对不同的语句做出不同的响应。但令我沮丧的是,以下代码完美运行:

Dim B() as Variant
B = Application.Range("A1:A10")

由于它在语法上与问题中的崩溃行相同,因此唯一可能的结论是,AFAIK 是工作表和应用程序类中 Range 的实现返回不同类型的对象,即使它们本质上包含相同的信息。大多数强制转换将呈现相同的结果,但对于某些实现怪癖,只有应用程序版本可以强制转换为变体数组。这一结论得到以下事实的支持:在调试模式下检查表达式 Range("A1:A10")ActiveSheet.Range("A1:A10") 的结果会导致 不同类型 信息 - 第一种情况下为“对象/范围”,而“变量/对象” /范围”在第二个。

如果这是真的,那么差异的确切原因(如果根本不是意外的话)可能只有 MS 的编码人员或其他人知道。我很好奇这是否与不同版本的 Office 保持一致。

【讨论】:

  • Application.Range("A1:A10")Range("A1:A10") 相同。 ActiveSheet.Range("A1:A10") 调用不同的属性,Worksheet.Range。除了它们是不同类的属性之外,它们的名称也不同——Application.Range 使用早期绑定,ActiveSheet.Range 使用后期绑定。
  • 我看到,loannis 评论指出了似乎是正确的答案。但是,downvotes 似乎还是有点粗糙。无论如何,我从来没有说过“Application.Range”和“ActiveSheet.Range”在语义上是相同的——只是在语法上是相同的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-06-28
  • 2014-07-15
  • 1970-01-01
  • 2014-12-23
  • 2020-03-20
  • 1970-01-01
  • 2019-02-26
相关资源
最近更新 更多