是"如字典"和#34; As Scripting.Dictionary"等价(对于VBA早期绑定)?

时间:2018-01-24 18:18:48

标签: vba excel-vba dictionary excel

使用早期绑定和Microsoft Scripting Runtime Library创建字典对象时,看起来有两个相同的类型名称用于同一事物:

Dim dict as Dictionary
Set dict = New Dictionary

Dim dict as Scripting.Dictionary
Set dict = new Scripting.Dictionary

似乎做同样的事情(至少到目前为止)。

我看到使用了As Scripting.Dictionary语法by this resource,我看到As Dictionary使用了by this (really great) resource语法,但我还没有看到任何比较。有关字典的MSDN文档可以是a literal joke,也可以是not explicitly related to VBA

我不明白为什么我应该做额外的打字只是为了让我的函数声明更加拥挤如果我可以使用As Dictionary,但我已经了解到VBA中的某些东西看起来像是等效实际上可以有微妙但显着的差异(例如Application.InputBoxInputBox)。

这些之间是否真的没有区别,或者我应该注意哪些细微差别?

3 个答案:

答案 0 :(得分:9)

  

我不明白为什么我应该做额外的打字只是为了让我的函数声明更加拥挤[...]

它被称为完全限定类型。

执行此操作时:

Dim foo As Range

引用对话框中的优先级顺序确定的类型Range以非常特定的顺序解析:

Tools/References dialog

如果公开Range类型的最顶层类型库是Excel类型库,则Range代表Excel.Range

如果您的意思是Word.Range,那么您就会遇到错误,并且对您声明的类型进行完全限定可以避免这些错误。

Scripting库会公开Dictionary类。因此,当您引用Scripting类型库并执行此操作时:

Dim foo As Dictionary

您有权将该类型解析为Scripting.Dictionary。但是,如果添加一个类模块并将其命名为Dictionary,则突然所有这些非限定声明现在引用此自定义类,因为在查看外部引用之前,VBA类型解析将始终优先考虑当前项目中定义的类型。 / p>

当然你可以称之为“额外打字”。只要知道这两种方法都有利有弊。

  • 完全限定类型在引用公开同名类的类型库时避免了歧义:它增强了可读性。
  • 不是符合条件的类型可以更轻松地将一个类交换为另一个类,例如将Scripting.Dictionary替换为适用于Mac的portable Dictionary implementation

经验法则,编程与编写代码无关。这是关于阅读代码。编写易于阅读的代码,而不是编写速度快的代码。

答案 1 :(得分:4)

正如@braX在您的特定用例(早期绑定)中所说,它是相同的,因此Scripting.可以被取消。

但是,有些情况可能会有所帮助(甚至需要)。例如,如果您在另一个Office应用程序中操作Excel,则会(使用早期绑定)写入

Dim XL as Excel.Application

因为您需要告诉VBA具体使用哪个应用程序。

但你可以继续写

Dim myWB as Workbook

并且VBA将知道它的卓越工作。但是,编写

可能更加用户友好
Dim myWB as Excel.Workbook

这样,完全清楚发生了什么。

现在,对于大多数程序员而言,对于大多数程序员来说,它已经很清楚了,那很好,但是如果你在Word中进行编程并希望在Excel中操作Range对象该怎么办? 。写作

Dim myRange as Range

可能无法正常工作,因为VBA会将其解析为Word范围对象(因为您使用Word编写 - 请参阅MatMug的答案以获得更好的解释),这将导致错误进一步降低引用myRange.Offset(1)时的代码行,例如,因为Word范围对象没有Offset方法。因此,在这种情况下,它既是必要的又是用户友好的。

答案 2 :(得分:-3)

所有这些答案都说对了事,但最终都是错误的。让我们找出原因。以下是您可能会说Scripting.Dictionary和Dictionary相同的一些原因:

  • 两者均由Microsoft脚本运行时参考提供。
  • 两者都是托管字典,并且具有相似的界面

为什么我们会说它们不同?考虑:

Sub frontEnd()
    Dim dictA As Scripting.Dictionary
    Dim dictB As Dictionary

    Set dictA = backEnd()
    Set dictB = backEnd()
End Sub


Function backEnd() As Scripting.Dictionary
    Dim myDict As Scripting.Dictionary
    Set myDict = New Scripting.Dictionary

    myDict("foo") = "bar"
    myDict("bar") = "foo"

    Set backEnd = myDict
End Function

运行此代码,您将发现VBA给您“类型不匹配”错误。因此,显然,不能将Scripting.Dictionary分配给Dictionary类型的变量。仅凭这一点,我就有理由将这两种类型视为不同。请注意,这对于在阳光下使用Variant的所有用户都是透明的,但是对于使用Option Explicit进行编程的我们来说,这是我们应该将这两种类型视为不同的强烈原因。

此外,接口可能相似,但绝对不一样!考虑:

Sub frontEnd()
    Dim dictA As Scripting.Dictionary
    Dim dictB As Dictionary

    Set dictA = backEnd()
    Set dictB = altBackEnd()
End Sub


Function backEnd() As Scripting.Dictionary
    Dim myDict As Scripting.Dictionary
    Set myDict = New Scripting.Dictionary

    myDict("foo") = "bar"
    myDict("bar") = "foo"

    Set backEnd = myDict
End Function


Function altBackEnd() As Dictionary
    Dim myDict As Dictionary
    Set myDict = New Dictionary

    myDict("foo") = "bar"
    myDict("bar") = "foo"

    Set altBackEnd = myDict
End Function

哦,哦! altBackEnd()函数中出现“找不到密钥”错误。显然,通过Scripting.Dictionary,您可以使用dict(“ foo”)=“ bar”语义隐式创建键/项对,但是Dictionary需要您使用dict.add()方法。像这样:

Sub frontEnd()
    Dim dictA As Scripting.Dictionary
    Dim dictB As Dictionary

    Set dictA = backEnd()
    Set dictB = altBackEnd()
End Sub


Function backEnd() As Scripting.Dictionary
    Dim myDict As Scripting.Dictionary
    Set myDict = New Scripting.Dictionary

    myDict("foo") = "bar"
    myDict("bar") = "foo"

    Set backEnd = myDict
End Function


Function altBackEnd() As Dictionary
    Dim myDict As Dictionary
    Set myDict = New Dictionary

    myDict.Add Key:="foo", Value:="bar"
    myDict.Add Key:="bar", Value:="foo"

    Set altBackEnd = myDict
End Function

作为最后一个演示为什么这些类型不同的原因,请尝试使用此版本替换backEnd()并查看会发生什么:

Function backEnd() As Scripting.Dictionary
    Dim myDict As Scripting.Dictionary
    Set myDict = New Scripting.Dictionary

    myDict.Add Key:="foo", Value:="bar"
    myDict.Add Key:="bar", Value:="foo"

    Set backEnd = myDict
End Function

提示:显然词典使用键/值对,而脚本。字典使用键/项对。

作为最后的作业,使程序开始工作,发布一个断点,并使用VBE查看Scripting.Dictionary和Dictionary的结构。请注意,它们的实现方式有所不同!

结论:字典和脚本。字典...

  1. 与VBA调用语义不兼容。
  2. 没有相同的外部接口。
  3. 没有相同的内部接口。

Ergo,尽管两者都是Microsoft脚本运行时参考提供的,但它们是不同的。

最好使用Scripting.Dictionary,因为它的界面比Dictionary丰富得多(例如Scripting.Dictionary具有Remove()和RemoveAll()方法,而Dictionary没有。)