我一直在尝试DEC_MAX
在vba中创建类似于常量的内容。
问题是,这有点棘手,因为没有Decimal
数据类型!
您可以最接近的十进制CDec()
是定义的函数:
返回作为让表达式强制转换为小数的结果的小数数据值
很自然地,我认为任何潜在的过度价值都将被强制达到可实现的最大价值Decimal
。我尝试从MSDN文档插入最大Decimal vb.net值
但是请注意,这是正确的,因为这样做会导致溢出:
那么在这里如何去计算十进制最大值的最接近的近似值呢?我尝试了代码的“计算机中断”丑陋循环:
Private Sub brick_my_Excel()
On Error Resume Next
x = 79228162514264337593543950335 'let's let it auto-coerce i guess
Do
Debug.Print(x)
x = x - 1
Loop
End Sub
但是,这完全阻止了溢出,以几乎像字符串的方式打印x,而无需过多地关注计算。
所以,
CDec()
函数的最大表达式是什么?我能弄清楚如何做到这一点的唯一方法是完全绕过VBA并“构建”内存中的最大值。的DECIMAL
结构是16个字节,并且被定义为:
typedef struct tagDEC {
USHORT wReserved;
BYTE scale;
BYTE sign;
ULONG Hi32;
ULONGLONG Lo64;
} DECIMAL;
由于您不能Decimal
在VBA中显式声明一个,因此CDec(0)
将为您提供一个具有正确Variant
类型的选项。符号和小数位与12个字节的值无关,因此仅设置该内存区域中的所有位将为您提供最大值(最大小数位为0):
#If VBA7 Then
Private Declare PtrSafe Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (Destination As LongPtr, Source As Any, _
ByVal length As Long)
#Else
Private Declare Sub CopyMemory Lib "kernel32" Alias _
"RtlMoveMemory" (Destination As Long, Source As Any, _
ByVal length As Long)
#End If
Private Const VT_DECIMAL As Integer = &HE
Private Const BIT_MASK As Long = &HFFFFFFFF
Private Const DATA_OFFSET = 4
Private Const SIZEOF_LONG = 4
Public Function MaxDecimal() As Variant
'Get a decimal to work with.
Dim dec As Variant
dec = CDec(0)
Dim vtype As Integer
'First 2 bytes are the VARENUM.
CopyMemory ByVal VarPtr(vtype), ByVal VarPtr(dec), LenB(vtype)
'Make sure the VARENUM is a VT_DECIMAL.
If vtype = VT_DECIMAL Then
'Fill the top 12 bytes of it's data area with truthy bits
CopyMemory ByVal VarPtr(dec) + DATA_OFFSET, BIT_MASK, SIZEOF_LONG
CopyMemory ByVal VarPtr(dec) + DATA_OFFSET + SIZEOF_LONG, BIT_MASK, SIZEOF_LONG
CopyMemory ByVal VarPtr(dec) + DATA_OFFSET + SIZEOF_LONG * 2, BIT_MASK, SIZEOF_LONG
End If
MaxDecimal = dec
End Function
请注意,这显然不会Const
为您带来好处,但确实会为您提供正确的最大值:
Public Sub Test()
MsgBox MaxDecimal
End Sub
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句