转换十六进制(A-F)数字

时间:2019-03-19 10:11:53

标签: excel vba

我做了一个转换数字的函数。例如从5到15的基数-表示除基本2、8、10、16之外的其他类型。它们基于将数字转换为10(通过使用幂),然后再从10转换为其他基数(mod,div)。 / p>

输入值A-F(十六进制是顶部)时出现问题。

这是将数字转换为10的代码的单独部分。

Function prevdeset(base As Integer, ipt As String) As String
Dim x As Integer
Dim s As Integer
Dim u As Integer
Dim p As Integer
c = Str(ipt)
x = Len(ipt)
u = 0
For i = x To 1 Step -1
    If Mid(c, i, 1) = "A" Then
        p = 10
    ElseIf Mid(c, i, 1) = "B" Then
        p = 11
    ElseIf Mid(c, i, 1) = "C" Then
        p = 12
    ElseIf Mid(c, i, 1) = "D" Then
        p = 13
    ElseIf Mid(c, i, 1) = "E" Then
        p = 14
    ElseIf Mid(c, i, 1) = "F" Then
        p = 15
    Else: p = Val(Mid(c, i, 1))
    End If
    p = p * (base ^ (x - i))
    u = u + p
Next i
prevdeset = u
End Function

该函数从右侧选择第i个字符,然后首先检查字符串值是否为A-如果不是,则为B,C,D,E,F,如果没有,则应将该字符转换为a数字(我不尝试输入其他字母作为G,H ..)。

如果输入不是字符串,则输出没有问题,完整的代码(此处未显示)可以输出字母(例如:以10为底的10将是以14为底的A)。

2 个答案:

答案 0 :(得分:1)

由于VBA受到Integers的限制,您收到了溢出错误。将您的变量更改为Long,您的代码将正常工作

| Type    | Storage | Range of Values                 |
|---------|---------|---------------------------------|
| Byte    | 1 byte  | 0 to 255                        |
| Integer | 2 bytes | -32,768 to 32,767               |
| Long    | 4 bytes | -2,147,483,648 to 2,147,483,647 |

Option Explicit
Function prevdeset(base As Integer, ipt As String) As String
    Dim x As Long, s As Long, u As Long, p As Long
    Dim i As Long
    Dim c As String

    c = ipt
    x = Len(ipt)
    u = 0
    For i = x To 1 Step -1
        If Mid(c, i, 1) = "A" Then
        p = 10
        ElseIf Mid(c, i, 1) = "B" Then
        p = 11
        ElseIf Mid(c, i, 1) = "C" Then
        p = 12
        ElseIf Mid(c, i, 1) = "D" Then
        p = 13
        ElseIf Mid(c, i, 1) = "E" Then
        p = 14
        ElseIf Mid(c, i, 1) = "F" Then
        p = 15
        Else: p = Val(Mid(c, i, 1))
        End If
        p = p * (base ^ (x - i))
        u = u + p
    Next i
    prevdeset = u
End Function

Sub test()
    Dim HexVal As String
    HexVal = "7B19AB"

    Debug.Print CLng("&H" & HexVal)
    Debug.Print prevdeset(16, HexVal)
End Sub

此外,您无需将ipt转换为String-您已经将ipt声明为String。您可以通过简单地声明c来将其强制为字符串(应始终将所有变量声明为方便的习惯,以确保此操作确保所有模块的顶部都带有Option Explicit

实际上,您的代码可以简化为:

Function prevdeset(base As Integer, ipt As String) As String
    Dim i As Long, u As Long
    Dim p As Long
    Dim HexCode As String

    For i = Len(ipt) To 1 Step -1
        HexCode = UCase(Mid(ipt, i, 1))

        If Not IsNumeric(HexCode) Then
            p = Asc(HexCode) - Asc("A") + 10
            If p >= base Then Err.Raise Number:=999, Source:="prevdeset", Description:="Invalid Hex"
        Else
            p = Val(HexCode)
        End If

        p = p * (base ^ (Len(ipt) - i))
        u = u + p
    Next i
    prevdeset = u
End Function

答案 1 :(得分:0)

下面的代码是您的简化版本和更正版本。您的代码无法正常工作的原因是使用整数而不是至少是长整数。我建议使用LongPtr。

Function Prevdeset(ByVal base As Integer, ByVal ipt As String) As LongPtr
    ' pass the arguments ByVal to avoid having them changed by the code
    ' in this way you wouldn't need the variable ipt
    ' Add Option Explicit at the top of your code module
    ' to ensure that you don't forget to declare variables

    Dim u As LongPtr
    Dim p As Integer
    Dim x As Integer
    Dim i As Integer
    ' the Dim statement sets all values to 0

    x = Len(ipt)
    For i = x To 1 Step -1
        p = InStr("0123456789ABCDEF", Mid(ipt, i, 1)) - 1
        If p < 0 Then
            MsgBox "invalid characer " & Mid(ipt, i, 1) & "." & vbCr & _
                   "The returned result may not be correct."
        End If

        u = u + (p * (base ^ (x - i)))
    Next i
    Prevdeset = u
End Function

请注意,函数的返回类型必须与分配给变量u的返回类型相同(在我的代码中为LongPtr,但至少为Long)。如果希望函数返回字符串,则可以在函数的最后一行代码中分配Prevdeset = CStr(u)