これは私を完全に困惑させました。
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
しかし、私は(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
私は何が間違っているのか理解できません。
説明は、古いプログラミング言語(WordBasicと初期のVBA)がTrueとFalseの整数値をどのように格納したかに関係していると思います。当時、True = -1およびFalse = 0でした。
新しいプログラミング言語では、Falseに0を使用していますが、Trueには1を使用しています。
Wordのブール型プロパティの大部分は、True(たとえば、Font.Bold)に-1を引き続き使用します。これは、新しい言語でInteropを使用するプログラマーに混乱とフラストレーションの原因となってきました。したがって、ある時点で、Microsoftの一部の開発者は新しい方法を使用することを決定し、いくつかの新しい機能のために整数値1をTrueに割り当てました。 FitText
など。
次のコードサンプルを考えてみましょう。ここで、X
はBoolean
タイプで、y
はInteger
タイプです。
FitText
がTrueの場合、整数値は1ですNot
を使用すると、ブール値は整数値が0ではないため「True」のままであることが示され、-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
これは、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
Cindyの優れた答えに付け加えると、VBAは通常、Boolean
データ型に割り当てるときに値を強制する保護手段を備えていますが、これは回避できることを指摘しておきます。基本的に、自分ではないメモリアドレスにランダムな値を書き込むと、予期しない動作が予想されます。
これを実証するために、LSet
を(ab)使用します。これにより、実際に割り当てることなく値をコピーできます。
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
b = b1.b
という行は、基本的にはOPコードで行ったものと同じです。
X = Selection.Cells(1).FitText
つまり、Boolean
を別のBoolean
に割り当てます。ただし、私はLSet
を使用してb1.b
に書き込みを行ったため、VBAランタイムチェックをバイパスし、強制されません。 Boolean
を読み取ると、VBAは暗黙的にそれをTrue
またはFalse
のいずれかに強制的に変換します。これは誤解を招くように見えますが、不正な結果は0
(別名False
)と等しい結果であり、真の結果はそうではないためです。真実の否定は、1
と-1
の両方が真実であることを意味することに注意してください。
1
をBoolean
変数に直接割り当てた場合、VBAはそれを-1
/True
に強制変換していたため、問題はありませんでした。しかし、明らかにFitText
またはLSet
を使用すると、基本的には制御されていない方法でメモリアドレスに書き込みます。そのため、VVARは、Boolean
変数の内容が強制されているが、そうではなかったため、この特定の変数で奇妙な動作を開始します。