Самая странная проблема VBA, которую я когда-либо видел (Vbasigned возможная ошибка при Булевом условии)

в 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.VBASigned и isSigned как TRUE...
snapshot of my code running но если изменить isSigned = ThisDocument.VBASigned to 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
    

    производит этот (ожидаемый) выход:

    правда


Edit: интересная статья Раймонда Чена, которая может дать некоторые дополнительные идеи о том, как это произошло: https://blogs.msdn.microsoft.com/oldnewthing/20041222-00/?p=36923

короче говоря, по мере развития операционной системы Windows она включала различные типы логических значений: int > byte > variant

2 ответов


после игры с цифровой подписью версии документа, который SlowLearner предоставил мне, я определил, что Vbasigned Word возвращает 1 когда он подписан.

это затем приводит к проблемам в If, потому что Not 1 равна -2 и Not 0 равна -1 - таким образом, ведущие к Not VBASigned возврат ненулевого (т. е. ненулевого) значения во всех случаях.


на документация MSDN утверждает, что 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

тестирование этого против 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

результаты

True
Я подписан

но используя то же самое в 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

результаты

True
Я не подписал

это ясно показывает, что есть ошибка в слово.


Это было проверено с

  • Windows 10 для 64-разрядных
  • Office Профессиональный Плюс 2016
    • Версия 1703 Построить 7967.2139
    • немецкий
    • 64 Бит Office