【问题标题】:VBA Visual Basic Editor (VBE) object .Saved Boolean bug? [duplicate]VBA Visual Basic 编辑器(VBE)对象。保存布尔错误? [复制]
【发布时间】:2020-09-20 09:23:14
【问题描述】:

tl;dr: 在下面的代码中,以下两个条件都评估为 True!!!如何?为什么?

  • If Not IsSaved Then
  • If IsSaved Then

我正在使用 VBA Visual Basic 编辑器 (VBE) 对象。 .Saved 属性让我感到困惑。

如果实际上保存了 VBComponent 对象,(.Saved)Not (.Saved) 都会返回 True。在评估条件之前,我什至尝试将属性显式强制为布尔值。以下是重现的步骤:

  1. 在新的 Excel 实例中打开一个空白工作簿
  2. 从标准模块(例如“Module1”)复制并运行以下代码:
Sub ListModules()
    Dim VBComp As Object  'VBComponent
    For Each VBComp In Application.VBE.ActiveVBProject.VBComponents
        
        Dim IsSaved As Boolean
        IsSaved = CBool(VBComp.Saved)
        
        If CStr(VBComp.Saved) = "True" Then
            Debug.Print vbNewLine; VBComp.Name; " saved? "; VBComp.Saved; " ("; TypeName(VBComp.Saved); ")"
            If Not IsSaved Then
                Debug.Print VBComp.Name; " is not saved"
            End If
            If IsSaved Then
                Debug.Print VBComp.Name; " is saved"
            End If
        End If
    Next VBComp
End Sub

'Sample output:
ListModules

ThisWorkbook saved? True (Boolean)
ThisWorkbook is not saved
ThisWorkbook is saved

Sheet1 saved? True (Boolean)
Sheet1 is not saved
Sheet1 is saved

注意:要运行此代码,您可能必须授予对 VBA 项目对象模型的访问权限:文件 -> 选项 -> 信任中心 -> [信任中心设置...] -> 宏设置 -> [x] 信任对 VBA 项目对象模型的访问

【问题讨论】:

  • 我很惊讶VBComponent.Saved 没有崩溃。该属性没有存在的逻辑权利,因为很明显您无法保存整体的任何部分,例如工作表。 Saved 属性仅与整个项目相关。也许像 VBComponent.Parent.Saved 这样的东西可以按您的预期工作。
  • 根据文档,该属性返回一个布尔值,指示对象自上次保存后是否被编辑 True 表示对象自上次保存后未被编辑。我不确定它对项目有多大意义。
  • @Ron Rosenfeld 这对一个项目很有意义。对于其中的一个组件来说是没有意义的。我没有找到 MSDN 对 VBComponent 对象的定义,我希望在其中找到它是否甚至具有 Saved 属性,因为它显然不应该。如果你找到了,可以发个链接吗?在我看来,您的解释通常只是指Saved 属性。
  • 这可能会有所帮助 - 对于模块 Saved 的行为符合预期,对于 Type 100,'True' 是 1 和 'False' 是 -2,但都不等于布尔值 @ 987654341@或FalseDim VBComp As Object 'VBComponent Debug.Print For Each VBComp In Application.VBE.ActiveVBProject.VBComponents IsSaved = CInt(VBComp.Saved) Debug.Print VBComp.Name; VBComp.Type; IsSaved; Not IsSaved; IsSaved = True; IsSaved = False Next VBComp
  • THIS 解释它。请参阅讨论的部分,首先,了解逻辑操作和测试是两个不同的东西。Dim IsSaved As Boolean: IsSaved = 1 是一个经典的例子。虽然Debug.Print IsSavedDebug.Print True = -1Debug.Print IsSaved= -1 会给你TrueDebug.Print IsSaved = 1 会给你False

标签: excel vba


【解决方案1】:

@JMP 和@SiddharthRout cmets 揭晓了答案。

这是一个非标准的布尔实现,其中True1not -1

但是,logical operations 失败了。

例如,Not A 操作是 A 的按位反转(布尔值存储为 long)。如果A=-1 它的位是1111111111111111 并且反转是0000000000000000

但是如果A=1 那么它的位是0000000000000001 并且反转得到1111111111111110 代表-2。所以Not 1-2 什么是True,因为它是<> 0

这就是为什么Not VBComponent.Saved = True (=-2) 而VBComponent.Saved = True (=1) 也是!

| Assignment (a As Boolean) | Bits             | Value As Integer | Value As Boolean |
|---------------------------|------------------|------------------|------------------|
| a = True                  | 1111111111111111 | -1               | TRUE             |
| Not a                     | 0000000000000000 | 0                | FALSE            |
|                           |                  |                  |                  |
| a = False                 | 0000000000000000 | 0                | FALSE            |
| Not a                     | 1111111111111111 | -1               | TRUE             |
|                           |                  |                  |                  |
| VBComponent.Saved = True  | 0000000000000001 | 1                | TRUE             |
| Not VBComponent.Saved     | 1111111111111110 | -2               | TRUE             |
|                           |                  |                  |                  |
| VBComponent.Saved = False | 0000000000000000 | 0                | FALSE            |
| Not VBComponent.Saved     | 1111111111111111 | -1               | TRUE             |
Sub TestInversion()
Dim VBComp As Object  'VBComponent
Debug.Print
For Each VBComp In Application.VBE.ActiveVBProject.VBComponents
IsSaved = CInt(VBComp.Saved)
Debug.Print VBComp.Name; VBComp.Type; VBComp.Saved; CInt(VBComp.Saved); Not VBComp.Saved; Not CInt(VBComp.Saved); VBComp.Saved = True; VBComp.Saved = False
Next VBComp
End Sub

现在我们错过了这种奇怪实现的原因,也许有人知道?

【讨论】:

  • 我认为原因太复杂了,我无法理解。我希望看到的是文档,其中详细说明了此特定属性可以保存的值。 MSDN 通常有非常好的对象文档,其中列出了方法和属性,并且可以深入了解属性的值。我没有找到有关 VBComponent 对象的此类文档,只是这让我在原来是错误的地方寻找有关 Saved 属性的启示。我赞成您的回答,如果有人告诉我在哪里可以做到这一点,我会否决 MS 缺少的答案。
  • @Variatus 你知道office365.uservoice.com?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-12-28
  • 1970-01-01
相关资源
最近更新 更多