elu*_*oad 41 vba ms-word boolean-operations
这让我完全不知所措。
Sub testChangeBoolean()
Dim X As Boolean ' default value is False
X = True ' X is now True
X = Not X ' X is back to False
End Sub
Run Code Online (Sandbox Code Playgroud)
但我试图在表格单元格(在 Word 中)中切换 .FitText 属性。.FitText 以 True 开头。
如果我将它分配给 X:
Sub testChangeBoolean()
Dim X As Boolean ' again, default is False
X = Selection.Cells(1).FitText ' does set X to True
X = Not X ' X is still True!
End Sub
Run Code Online (Sandbox Code Playgroud)
我只是不明白我做错了什么。
Cin*_*ter 41
我相信这个解释与旧的编程语言(WordBasic 和早期的 VBA)如何存储 True 和 False 的整数值有关。在那些日子里,True = -1 和 False = 0。
较新的编程语言仍然使用 0 表示 False,但 1 表示 True。
Word 的大多数布尔类型属性继续使用 -1 表示 True(例如,Font.Bold),这让使用新语言的 Interop 的程序员感到困惑和沮丧。因此,在某些时候,Microsoft 的一些开发人员决定使用新方法并将整数值 1 分配给 True 以实现某些新功能。比如FitText。
考虑以下代码示例,其中X是 typeBoolean和ytype Integer:
FitText为 True,则整数值为 1Not表明布尔值保持“真”,因为它的整数值不是 0,它是 -2这确实令人困惑,但确实解释了为什么Not没有给出预期的结果。
Sub testChangeBoolean()
Dim X As Boolean ' again, default is False
Dim Y As Integer
X = Selection.Cells(1).FitText ' does set X to True
Y = Selection.Cells(1).FitText
Debug.Print X, Y ' result: True 1
X = Not X ' X is still True!
Y = Not Y
Debug.Print X, Y ' result: True -2
X = False
Y = True
Debug.Print X, Y ' result: False -1
End Sub
Run Code Online (Sandbox Code Playgroud)
为了补充 Cindy 的出色回答,我想指出,虽然 VBA 通常在分配给Boolean数据类型时具有强制执行值的保护措施,但这是可以规避的。基本上,如果您将一个随机值写入一个不属于您的内存地址,那么您应该预期会出现未定义的行为。
为了帮助证明这一点,我们将 (ab)useLSet本质上允许我们在不实际分配的情况下复制值。
Private Type t1
b As Boolean
End Type
Private Type t2
i As Integer
End Type
Private Sub Demo()
Dim i1 As t2
Dim b1 As t1
Dim b As Boolean
i1.i = 1
LSet b1 = i1
b = b1.b
Debug.Print b, b1.b, i1.i
Debug.Print CInt(b), CInt(b1.b), i1.i
End Sub
Run Code Online (Sandbox Code Playgroud)
请注意,该行b = b1.b基本上等同于我们在 OP 代码中所做的
X = Selection.Cells(1).FitText
Run Code Online (Sandbox Code Playgroud)
也就是说,将 a 分配Boolean给 another Boolean。但是,因为我写到b1.busing LSet,绕过 VBA 运行时检查,它不会被强制。在阅读 时Boolean,VBA 确实隐式地将其强制为Trueor False,这似乎具有误导性,但它是正确的,因为任何虚假结果都是等于0(又名False)的结果,而任何真实结果都是不相等的结果。请注意,truthy 的否定表示1和-1都是真的。
如果我直接将分配1给一个Boolean变量,VBA 就会将它强制转换为-1/ True,因此不会有问题。但显然使用FitTextor LSet,我们基本上是以不受控制的方式写入内存地址,因此 VBA 开始对这个特定变量表现出奇怪的行为,因为它期望该Boolean变量的内容已经被强制但没有被强制。
正如 Cindy Meister 所解释的那样,这是因为来自该属性的内部 Long 值。我们应该始终使用 CInt 来避免这种情况。
Sub testChangeBoolean2()
Dim X As Boolean ' again, default is False
X = CInt(Selection.Cells(1).FitText) ' [Fixed] does set X to True
X = Not X ' X is False!
End Sub
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1876 次 |
| 最近记录: |