VBA中可能的最大十进制值是多少?

Raw*_*lus 7 error-handling excel vba exception limit

我一直试图DEC_MAX创建类似于常量的东西.


问题是,它有点棘手,因为没有Decimal数据类型!
最接近有效十进制的CDec()函数是定义的函数:

将Decimal数据值返回到Decimal,该值是Expression被Let-coerced为Decimal的结果

很自然地,我认为任何潜在的过度价值都会被合并到最大可实现的价值Decimal.我尝试从MSDN文档中插入max Decimal

但是请注意这一点,因为尝试这样做会导致溢出:

在此输入图像描述

那么如何在这里计算最接近的十进制最大值?我试过这个"计算机砖"丑陋的代码循环:

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
Run Code Online (Sandbox Code Playgroud)

然而,这完全抑制了溢出,以几乎像字符串的方式打印x而不太注意计算.

所以,

  1. 如何计算它?
  2. 我们可以传递给CDec()函数的最大可能表达式是什么?

Com*_*ern 8

我能弄清楚如何做到这一点的唯一方法是完全绕过VBA并"构建"内存中的最大值. DECIMAL结构是16个字节,并且被定义为:

typedef struct tagDEC {
  USHORT    wReserved;
  BYTE      scale;
  BYTE      sign;
  ULONG     Hi32;
  ULONGLONG Lo64;
} DECIMAL;
Run Code Online (Sandbox Code Playgroud)

由于您无法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
Run Code Online (Sandbox Code Playgroud)

请注意,这显然不会让它成为Const你的,但它确实得到正确的最大值:

Public Sub Test()
    MsgBox MaxDecimal
End Sub
Run Code Online (Sandbox Code Playgroud)

最大十进制值

  • 令人印象深刻的二进制工作在这里. (4认同)