用字符串变量替换字符串-错误91

Jvd*_*vdV 5 string excel vba namespaces

背景

最近,我回答了一个问题,其中涉及在寻找一个文件的属性。最终,我提出的代码运行良好,但是有一点让我感到困惑。

问题

我想在两行中用一个变量替换一个字符串(在我看来是这样),更具体地说,请尝试以下操作:

Sub TestForSO()

Dim oDir As Object: Set oDir = CreateObject("Shell.Application").Namespace("C:\Users\...\")
Debug.Print oDir.GetDetailsOf(oDir.Items, 1)

End Sub
Run Code Online (Sandbox Code Playgroud)

将路径名替换为包含excel文件的目录,它应该可以正确返回属性值。

现在,当我尝试用变量替换完整路径时,以下内容会在debug.print行上引发“运行时错误91:对象变量或未设置块变量”:

Sub TestForSO()

Dim MainPath As String: MainPath = "C:\Users\...\"
Dim oDir As Object: Set oDir = CreateObject("Shell.Application").Namespace(MainPath)
Debug.Print oDir.GetDetailsOf(oDir.Items, 1)

End Sub
Run Code Online (Sandbox Code Playgroud)

对我而言,以下功能确实有用:

Sub TestForSO()

Dim MainPath As String: MainPath = "C:\Users\...\"
Dim oDir As Object: Set oDir = CreateObject("Shell.Application").Namespace(CStr(MainPath))
Debug.Print oDir.GetDetailsOf(oDir.Items, 1)

End Sub
Run Code Online (Sandbox Code Playgroud)

我不了解其本质上的区别,因为下面的代码将通过“ Watches”给出相同的结果:

Sub test()

Dim check1 As String, check2 As String

check1 = "Hello"
check2 = CStr("Hello")

End Sub
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

有人知道为什么字符串变量本身不够用并会引发错误吗?Cstr()当看起来是相同的数据类型时,为什么要添加代码才能使代码正常工作?

Fox*_*rns 3

根据有关Namespace的文档,它需要一个参数,该参数必须是 Variant 或可以是指定文件夹路径的字符串。

这解释了为什么这两种方法没有问题:

Set oDir = CreateObject("Shell.Application").Namespace("C:\Users\...\ 'string path
Run Code Online (Sandbox Code Playgroud)

或者定义一个 Variant 变量:

Dim MainPath As Variant: MainPath = "C:\Users\...\"
Dim oDir As Object: Set oDir = CreateObject("Shell.Application").Namespace(CStr(MainPath))
Run Code Online (Sandbox Code Playgroud)

但定义MainPath为字符串会导致错误运行时错误 91:未设置对象变量或块变量

OP找到了解决方案。如果MainPath声明为字符串并与Cstr组合,则代码可以工作。

这只是一个理论,但一些非官方来源(与 VBA 没有直接关系)提到Cstr将值转换为具有子类型的变体。

http://www.csidata.com/custserv/onlinehelp/vbsdocs/vbs89.htm https://docs.oracle.com/cd/E57185_01/HFMAD/ch10s06s04s03.html

实际上,官方文档有点令人困惑,因为第一行它说:

每个函数将表达式强制为特定的数据类型。

后来它说

函数名决定返回类型

但如果我们仔细阅读的话,还有一些重要的信息是这样的:

“......一般来说,您可以使用数据类型转换函数记录代码,以表明某些操作的结果应表示为特定数据类型而不是默认数据类型......”

并且:

“...该技术与所有其他内在类型到其等效 Variant 子类型的转换是一致的...”

因此,在过去 24 小时内进行了一些研究和思考,并多次阅读了我之前发布的段落之后,我敢说所有转换函数都会返回带有子类型的 Variant。在这种情况下,CStr确实返回一个 Variant,该 Variant 被强制表示为 string子类型,但数据是 Variant。

这可以解释为什么这样做Cstr(MainPath)会使代码有效。