Despite the lack of a built-in way to do this, the calculation is simple:
Public Function coerceLongToInt(toCoerce As Long) As Integer Const MIN_INT As Long = -32768 Const MAX_INT As Long = 32767 Const NUM_INTS As Long = MAX_INT - MIN_INT + 1 Dim remainder As Long remainder = toCoerce Mod NUM_INTS If remainder > MAX_INT Then coerceLongToInt = remainder - NUM_INTS ElseIf remainder < MIN_INT Then coerceLongToInt = remainder + NUM_INTS Else coerceLongToInt = remainder End If End Function
Is this the behavior you want right?
?coerceLongToInt(-32769) 32767 ?coerceLongToInt(-32768) -32768 ?coerceLongToInt(-1) -1 ?coerceLongToInt(0) 0 ?coerceLongToInt(1) 1 ?coerceLongToInt(32767) 32767 ?coerceLongToInt(32768) -32768
You would use it as follows:
Function FnGetStringHashCode(ByVal str As String) As Integer Dim result, i FnGetStringHashCode = 17 For i = 1 To Len(str) Dim c, a c = Mid(str, i, 1) a = AscW(c) FnGetStringHashCode = coerceLongToInt(31 * CLng(FnGetStringHashCode) + a) Next i End Function
You need a "CLng" call to prevent the VBA from raising an overflow error when calculating an intermediate value (31 * [some integer> = 1058]).
source share