Единственный способ выяснить, как это сделать, - полностью обойти 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