测试字符串是否为空

10
我是一名刚接触VBA的新手,还没有完全习惯语法,如果我的问题听起来很愚蠢,请见谅。
我正在使用RequisitePro40和Word 2010中的VBA 7.0。在我的一个模块中,我有以下循环和If条件:
Dim rqRequirements As ReqPro40.Requirements
Dim rqRequirement As ReqPro40.Requirement
Const eAttrValueLookup_Label = 4
Dim a As Integer
...

For Each vReqKey In rqRequirements
    Set rqRequirement = rqRequirements(vReqKey)

    If rqRequirement.AttrValue("MyAttreName", eAttrValueLookup_Label).text <> Null Then
        a = 1
    End If

    If rqRequirement.AttrValue("MyAttreName", eAttrValueLookup_Label).text = Null Then
         a = 2
    End If

 Next

在循环的每次迭代中,都会执行a = 1a = 2两个语句。
根据这里所述,等于和不等于运算符分别是"="和"<>"。因此,我预期字符串中要么执行a = 1,要么执行a = 2。我的语法有问题吗?还是与ReqPro相关的问题?
我也尝试使用"Is"和"IsNot"运算符,但结果是编译器错误:类型不匹配。
有人能帮我解决这个问题吗?
更新:实际目标是查看

rqRequirement.AttrValue("MyAttreName", eAttrValueLookup_Label).text

是否为空。我添加了第二个if来显示该语句似乎没有按照我的预期工作的问题。
将"Null"替换为"vbNullString"没有任何改变。
我也尝试了@Slai建议的IsNull函数,结果基本相同:
    If IsNull(rqRequirement.AttrValue(att, eAttrValueLookup_Label).text) Then
        a = 3
    End If

    If Not IsNull(rqRequirement.AttrValue(att, eAttrValueLookup_Label).text) Then
        a = 4
    End If

语句a=3a=4都是真的且被执行。


你是如何声明a的?作为字符串吗? - QHarr
1
  1. rqRequirement.AttrValue("MyAttreName", eAttrValueLookup_Label).text 返回的对象类型是什么?(您可以查看 ReqPro40 对象模型文档来了解)
  2. 您的实际目的是什么?(我无法理解您代码中的 If-Then 结构)
- DisplayName
4
使用 VBA 时,通常不会测试字符串是否为 “Null”。而是测试它是否为空,最有效的方法是:Len(stringVariable)>0。如果 strVariable = "" 也是可能的,但执行效率不如前者高。 - Cindy Meister
@DisplayName 实际目标是查看文本是否为空。我添加了第二个if语句来展示这个问题,即该语句的工作方式与我的预期不同。 - dieKoderin
根据这个SO问题.text可能是问题所在。答案建议使用.value代替。 - IQV
显示剩余4条评论
5个回答

14

VBA不支持测试字符串是否为"Null"。VBA与.NET语言或JavaScript(例如)不同。所有基本变量类型都有一个默认值,String从变量声明时就是零长度("")——它没有未实例化的状态。您还可以测试vbNullString。

如果您进行测试:

Dim s as String
Debug.Print s = Null, s <> Null, s = "", s = "a", IsNull(s), s = vbNullString

回报是

Null  Null  True  False  False  True

所以如果你想测试是否向一个字符串变量分配了任何内容,你只能做以下几件事:

Debug.Print Len(s), s = "", Len(s) = 0, s = vbNullString

返回哪个值

0  True  True True
注意,这些可能性中最慢的是s = "",尽管它似乎是最简单易记的。

s = " " 和 vbNullString 测试不是一样的吗? - QHarr
1
实际上,首选针对 vbNullString 进行测试。虽然 vbNullString = "",但最好使用内置名称而不是空引号。 - Brandon Barney
我也是这么想的,所以才加了那个表情 :-( - QHarr
谢谢 - 已添加到列表中 :-) - Cindy Meister
1
vbNullString 不同于 ""。这种差异可能很重要。 - GSerg
@GSerg 您是正确的,这就是为什么我最初没有包括它的原因。它适用于特定的测试 - 如何确定字符串是否为空。但是,在其他情况下,这可能是一个重要的区别。只有在处理已知字符串时(例如VBA中的字符串变量,如我们在此问题中所看到的(.text属性)),才不会出现这种情况。与您链接的主题的InputBox(控件)可以具有Null状态,而不是String。 - Cindy Meister

2

正如其他人所指出的那样,您需要针对字符串的空版本 vbNullString 进行测试,而不是特定的 Null。除此之外,您还需要确保对象本身不为空。例如:

Dim rqRequirements As ReqPro40.Requirements
Dim rqRequirement As ReqPro40.Requirement
Const eAttrValueLookup_Label = 4
Dim a As Long ' Avoid Integer since it has a strong habit of causing overflow errors.
...

For Each vReqKey In rqRequirements
    Set rqRequirement = rqRequirements(vReqKey)

    If Not rqRequirement Is Nothing Then
        If rqRequirement.AttrValue("MyAttreName", eAttrValueLookup_Label).text <> vbNullString Then
            a = 1
        End If

        If rqRequirement.AttrValue("MyAttreName", eAttrValueLookup_Label).text = vbNullString Then
             a = 2
        End If
    End If
 Next

现在,我之前没有使用过这种特定的对象类型,但我相当确定AttrValue("MyAttreName", eAttrValueLookup_Label)正在返回某种对象。如果是这种情况,那么下面的模式将是首选:

    Dim rqRequirements As ReqPro40.Requirements
    Dim rqRequirement As ReqPro40.Requirement
    Const eAttrValueLookup_Label = 4
    Dim a As Long ' Avoid Integer since it has a strong habit of causing overflow errors.
    ...

    For Each vReqKey In rqRequirements
        Set rqRequirement = rqRequirements(vReqKey)

        If Not rqRequirement Is Nothing Then
            Dim Attribute as Object ' Or whatever type it should be
            Set Attribute = rq.Requirement.AttrValue("MyAttreName", eAttrValueLookup)
            If Not Attribute is Nothing Then
                If Attribute.text <> Null Then
                    a = 1
                End If

                If Attribute.text = Null Then
                     a = 2
                End If
            End If
        End If
     Next

这样,我们只有在实际设置了Attribute时才会调用Attributetext属性。这样可以避免后续出现424错误。

最后,如果您想弄清楚代码中导致两个if都运行的原因,请执行以下操作:

Debug.Print "Attribute Text: ", Attribute.Text

这将允许您看到您的代码所看到的内容。您还可以考虑使用断点。


1

1) 我认为您可以使用vbNullString来测试空字符串。否则,如果是实际的字符串值,请使用“Null”。

2) 确保a被声明为long。

If rqRequirement.AttrValue("MyAttreName", eAttrValueLookup_Label).text <> vbNullString Then

     a = 1

End If

If rqRequirement.AttrValue("MyAttreName", eAttrValueLookup_Label).text = vbNullString Then
     a = 2
Else
     a = 3
End If

1
if结构就是这样的!我只想检查字符串是否为空。当然,我不需要全部三个条件语句。我只是添加它们来展示我的问题,即我的字符串同时为空和非空。 - dieKoderin

1
我来到这里是为了寻找一个关于“VBA:如何测试字符串是否为空”的答案。
虽然这个答案可能不适用于这个特定用户的情况,但它确实适用于主题问题。
Dim s As String, s2 As String
s = ""
s2 = vbNullString
Debug.Print StrPtr(s) = 0, StrPtr(s2) = 0

which returns

False   True

因为vbNullString是用于处理COM对象的C风格NULL指针,所以当通过未记录的StrPtr函数返回其内存地址时,它总是为0。


0
为确保互斥性,请仅提出该问题一次。
a = IIf(rqRequirement.AttrValue("MyAttreName", eAttrValueLookup_Label).text = vbNullString , 2, 1)

如果您还有其他操作需要执行,可以使用If-Then-Else结构。

上述代码示例假定~.text调用是正确的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接