2016-10-24 7 views
2

In MSACCESS VBA, konvertiere ich eine HEX-String durch das Vorsetzen die Zeichenfolge mit "& h"Convert HEX String Unsigned INT (VBA)

?CLng("&h1234") 
4660 
?CLng("&h80000000") 
-2147483648 

Was soll ich es auf eine ganze Zahl ohne Vorzeichen zu konvertieren tun in Dezimalzahlen ?

CDbl nicht verwenden nicht funktionieren:

?CDbl("&h80000000") 
-2147483648 
+1

VBA nicht über unsigne - Decimal kann bis zu 16^12 für Werte verwendet werden, d ganze Zahlen, nur _Long_ und _Integer_, beide signiert. – Gustav

+0

... und das ist die größte positive Ganzzahl, die 32-Bit-VBA weiß: '? CLng ("& h7FFFFFFF") 2147483647' – Andre

+0

Es ist merkwürdig, dass Sie mit 'Decimal' höher gehen können, aber die Konvertierung verwendet 32-Bit, wenn Ihr Hex 32 8 Ziffern oder kürzer ist. Wenn Sie 'CDec' mit einem 9-stelligen Hex verwenden, funktioniert es. – arcadeprecinct

Antwort

2

Ihre Version scheint die beste Antwort, kann aber ein wenig verkürzt werden:

Function Hex2Dbl(h As String) As Double 
    Hex2Dbl = CDbl("&h0" & h) ' Overflow Error if more than 2^64 
    If Hex2Dbl < 0 Then Hex2Dbl = Hex2Dbl + 4294967296# ' 16^8 = 4294967296 
End Function 

Double wird Rundungsgenauigkeit Fehler oben für die meisten Werte 2^53-1 (about 16 decimal digits), aber 1 (16 Bytes Decimal verwendet, aber nur 12 von ihnen für die Anzahl)

Function Hex2Dec(h) 
    Dim L As Long: L = Len(h) 
    If L < 16 Then    ' CDec results in Overflow error for hex numbers above 16^8 
     Hex2Dec = CDec("&h0" & h) 
     If Hex2Dec < 0 Then Hex2Dec = Hex2Dec + 4294967296# ' 2^32 
    ElseIf L < 25 Then 
     Hex2Dec = Hex2Dec(Left$(h, L - 9)) * 68719476736# + CDec("&h" & Right$(h, 9)) ' 16^9 = 68719476736 
    End If 
End Function 
+0

Oder mit anderen Worten:' links (h, len (h) -1) * 16 + ("& h" & rechts (h, 1)) 'where' h = "& h80000000" ' – SBF

+0

@SBF Ich habe festgestellt, dass * 16 zu viel ist, als ich deine Antwort sah:] – Slai

+0

Sorry, ich verstehe nicht, warum es übertrieben sein sollte - Können Sie erklären? – SBF

0

einen Vorschlag, in h führen

sh = "&H80000000" 
h = CDbl(sh) 
If h < 0 Then 
fd = Hex$(CDbl(Left(sh, 3)) - 8) 
sh = "&h" & fd & Mid(sh, 4) 
h = CDbl(sh) + 2^31 
End If 
2

Wenn Sie höher gehen wollen als 2^31 Sie Decimal oder LongLong nutzen könnten. LongLong und CLngLng funktionieren jedoch nur auf 64-Bit-Plattformen. Da ich zur Zeit nur 32 Bit Office habe, ist dies für Decimal und CDec.

Es scheint ein Problem bei der Konvertierung von 8-stelligen Hex-Zahlen zu geben, da offensichtlich signierte 32-Bit irgendwo im Prozess verwendet wird, was zu dem Zeichenfehler führt, obwohl Decimal die Zahl verarbeiten kann.

'only for positive numbers 
Function myHex2Dec(hexString As String) As Variant 
    'cut off "&h" if present 
    If Left(hexString, 2) = "&h" Or Left(hexString, 2) = "&H" Then hexString = Mid(hexString, 3) 

    'cut off leading zeros 
    While Left(hexString, 1) = "0" 
     hexString = Mid(hexString, 2) 
    Wend 

    myHex2Dec = CDec("&h" & hexString) 
    'correct value for 8 digits onle 
    If myHex2Dec < 0 And Len(hexString) = 8 Then 
     myHex2Dec = CDec("&h1" & hexString) - 4294967296# 
    'cause overflow for 16 digits 
    ElseIf myHex2Dec < 0 Then 
     Error (6) 'overflow 
    End If 

End Function 

Test:

Sub test() 
    Dim v As Variant 
    v = CDec("&H80000000")    '-2147483648 
    v = myHex2Dec("&H80000000")   '2147483648 
    v = CDec("&H7FFFFFFFFFFFFFFF")  '9223372036854775807 
    v = myHex2Dec("&H7FFFFFFFFFFFFFFF") '9223372036854775807 
    v = CDec("&H8000000000000000")  '-9223372036854775808 
    v = myHex2Dec("&H8000000000000000") 'overflow 

End Sub 
+0

Obwohl Ihre Antwort viel zu komplex ist, +1 für CLngLng auf 64-Bit-Office. Das funktioniert wirklich! – SBF

+0

@SBF Du hast Recht, meistens ist es nicht nötig, 'Decimal' zu verwenden und die Funktion ist zu kompliziert :) – arcadeprecinct

2

Mit Bemerkung von @arcadeprecinct ich in der Lage war, eine Funktion für sie zu schaffen:

Function Hex2UInt(h As String) As Double 
    Dim dbl As Double: dbl = CDbl("&h" & h) 

    If dbl < 0 Then 
     dbl = CDbl("&h1" & h) - 4294967296# 
    End If 

    Hex2UInt = dbl 
End Function 

Einige Beispielausgabe:

?Hex2UInt("1234") 
4660 
?Hex2UInt("80000000") 
2147483648 
?Hex2UInt("FFFFFFFFFFFF") 
281474976710655 

Maximum Wert, der als Ganzzahl dargestellt wird, ist 0x38D7EA4C67FFF

?Hex2UInt("38D7EA4C67FFF") 
999999999999999 
?Hex2UInt("38D7EA4C68000") 
1E+15