我见过的最奇怪的VBA问题(在布尔条件下VBASigned可能的错误)

时间:2017-05-10 03:57:13

标签: vba excel-vba ms-word word-vba excel

在MS Word中,我添加了一些代码,以查看文档是否缺少其数字签名,或者至少我认为我做过。在我在其他系统上测试之前,我决定分享。

Sub test()
    If Not ThisDocument.VBASigned Then
        Debug.Print "I am NOT signed"
    End If
End Sub

问题:无论文档是否具有数字签名,上述代码都会产生相同的结果。如果我通过删除Not来修改代码,我仍然会得到意想不到的结果。

我试图通过以下方式来强迫事情:

If Not CBool(ThisDocument.VBASigned) Then

但更令人惊讶的是,以下代码也失败了:

Sub test()
    Dim isSigned As Boolean
    isSigned = ThisDocument.VBASigned

    If Not isSigned Then
        Debug.Print "I am NOT signed"
    End If
End Sub

即使ThisDocument.VBASignedisSigned都是TRUE ...
snapshot of my code running 但如果将isSigned = ThisDocument.VBASigned更改为isSigned = True,那么一切都会按预期进行。

任何人都可以证实吗? 有什么想法吗?

以下编辑回答了一些问题:

  1. 是的,使用Option Explicit,是也尝试过调试 这段代码:

    Option Explicit
    
    Sub test()
        Dim isSigned As Boolean
        isSigned = ThisDocument.VBASigned
        Debug.Print ThisDocument.VBASigned
        If Not isSigned Then
            Debug.Print "I am NOT signed"
        End If
    End Sub
    

    生成此输出:

      


        我没有签名

  2. 测试:True * 0 - 1

    Sub test()
        Dim isSigned As Boolean
        isSigned = ThisDocument.VBASigned
        Debug.Print ThisDocument.VBASigned
        If Not (isSigned * 0 - 1) Then
            Debug.Print "I am NOT signed"
        End If
    End Sub
    

    生成此(预期)输出:

      

  3. 编辑:Raymond Chen撰写的有趣文章,可能会对这种情况提供进一步的见解:https://blogs.msdn.microsoft.com/oldnewthing/20041222-00/?p=36923

    简而言之,随着Windows操作系统的发展,它包含了不同类型的布尔值:int>字节>变体

2 个答案:

答案 0 :(得分:6)

使用SlowLearner提供给我的文档的数字签名版本后,我确定Word的VBASigned在签名后返回1

这会导致If语句出现问题,因为Not 1等于-2,而Not 0等于-1 - 从而导致Not VBASigned在所有情况下都返回非零(即非假)值。

MSDN documentation表示VBASigned是只读布尔值,并且已确认返回的变量类型(TypeName(ThisDocument.VBASigned))为Boolean,但它看来它应该被视为数值。

另一个有趣的事实是,CBool(ThisDocument.VBASigned) * 1给出了1的答案,而CBool(1) * 1给出了-1的答案。因此,当VBA决定某个值已经是Boolean(例如ThisDocument.VBASigned时)时,它似乎并不需要进行任何转换。但是,当CBool的参数不是Boolean时,它会将非零值转换为-1

可行的代码:

Sub test()
    Dim myVBASigned As Integer
    Dim isSigned As Boolean
    myVBASigned = ThisDocument.VBASigned 'Store as Integer
    isSigned = myVBASigned               'Convert to a "true" Boolean

    If Not isSigned Then                 'Use the "true" Boolean
        Debug.Print "I am NOT signed"
    End If

End Sub

答案 1 :(得分:2)

对Excel进行测试表明这是Word中的错误。

假设我们有启用VBA和VBA签名的新文档:

在Excel中使用:

Sub testExcel()
    Dim isSigned As Boolean
    isSigned = ThisWorkbook.VBASigned
    Debug.Print ThisWorkbook.VBASigned
    If Not isSigned Then
        Debug.Print "I am NOT signed"
    Else
        Debug.Print "I AM signed"
    End If
End Sub

结果

  


  我签了

但在Word中使用相同的

Sub testWord()
    Dim isSigned As Boolean
    isSigned = ThisDocument.VBASigned
    Debug.Print ThisDocument.VBASigned
    If Not isSigned Then
        Debug.Print "I am NOT signed"
    Else
        Debug.Print "I AM signed"
    End If
End Sub

结果

  


  我没有签名

这清楚地表明Word中存在错误。

进行了测试
  • Windows 10 x64
  • Office Professional Plus 2016
    • 版本1703 Build 7967.2139
    • 德国
    • 64位办公室