The weirdest VBA issue I have ever seen (VBASigned Possible Bug on Boolean Condition)

excel, ms-word, vba

Solution

After playing with a digitally signed version of a document that SlowLearner supplied me, I have determined that Word's VBASigned is returning a `1` when it is signed.

This then leads to problems in the `If` statement, because `Not 1` is equal to `-2`, and `Not 0` is equal to `-1` - thus leading to `Not VBASigned` returning a non-zero (i.e. non-False) value in all cases.

The MSDN documentation states that `VBASigned` is a read-only Boolean, and the type of variable returned has been confirmed (by `TypeName(ThisDocument.VBASigned)`) to be `Boolean`, but it appears it should be treated as a numeric value instead.

An additional interesting fact is that `CBool(ThisDocument.VBASigned) * 1` gives an answer of `1`, while a `CBool(1) * 1` gives an answer of `-1`. So it seems that, when VBA decides that a value is already a `Boolean` (such as `ThisDocument.VBASigned` is meant to be), it doesn't bother to do any conversions. But, when the parameter to `CBool` is not a `Boolean`, it converts a non-zero value to be `-1`.

Code that would work:

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

Problem

In MS Word I added some code to see if a document is missing its digital signature, or at least I thought I did. I've decided to share before testing this on other systems. ``` Sub test() If Not ThisDocument.VBASigned Then Debug.Print "I am NOT signed" End If End Sub ``` Problem: The code above produces the same result irrespective of whether or not the document has a digital signature. If I modify the code by removing the `Not` I still get unexpected results. I've tried to coerce things by doing things like: ``` If Not CBool(ThisDocument.VBASigned) Then ``` But more surprisingly, the following code also fails: ``` Sub test() Dim isSigned As Boolean isSigned = ThisDocument.VBASigned If Not isSigned Then Debug.Print "I am NOT signed" End If End Sub ``` Even though `ThisDocument.VBASigned` AND `isSigned` are both `TRUE`... but if change `isSigned = ThisDocument.VBASigned` to `isSigned = True` then everything works as expected. Can anyone confirm this? Any thoughts? Edits below answer some of the questions: Yes, using `Option Explicit`, Yes also tried Debug. This code: ``` 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 ``` Produces this output: True I am NOT signed Testing: `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 ``` Produces this (expected) output: True Edit: interesting article by Raymond Chen that might provide some further insights as to how this happened: https://blogs.msdn.microsoft.com/oldnewthing/20041222-00/?p=36923 In short, as the Windows operating system evolved it included different types of booleans: int > byte > variant

Original source