首页 > 解决方案 > 用字符串变量替换字符串 - 错误 91

问题描述

背景

最近我回答了一个涉及查看文件属性的问题。最终我提交的代码运行良好,但有一点让我感到困惑。

问题

有两个特定的行我想用一个变量替换一个(对我来说看起来像)一个字符串,更具体地说,尝试以下操作:

Sub TestForSO()

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

End Sub

将路径名替换为包含 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

解决方案

我有点奇怪,以下确实有效:

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

我不明白它们本身的区别,因为下面的代码将通过“Watches”给出相同的结果:

Sub test()

Dim check1 As String, check2 As String

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

End Sub

在此处输入图像描述

问题

有人明白为什么字符串变量本身不够而且会引发错误吗?当看似相同的数据类型时,为什么添加Cstr()会使代码工作?

标签: excelvbastringnamespaces

解决方案


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

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

Set oDir = CreateObject("Shell.Application").Namespace("C:\Users\...\ 'string path

或者定义一个 Variant 变量:

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

但是定义MainPath为字符串会导致错误Runtime Error 91: Object variable or with block variable not set

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确实返回一个变体,该变体被强制表示为作为字符串子类型的字符串,但数据是变体。

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


推荐阅读