patternMinor
Hex encoding and decoding of ASCII strings in VBA
Viewed 0 times
hexasciidecodingencodingandstringsvba
Problem
I needed to convert some Ascii text to binary in Hex format
I've written an
I've avoided using concatenation in favour of performance.
I'm assuming that assigning the results of
I need to use this in Excel, so I'm using
Sample usage
VBA Code
```
Option Explicit
Const HEX_STRING_PREFIX As String = "0x"
Const VBA_HEX_PREFIX As String = "&h"
Public Function HexEncode(AsciiText As String, Optional HexPrefix As String = HEX_STRING_PREFIX) As String
If AsciiText = vbNullString Then
HexEncode = AsciiText
Else
Dim asciiChars() As Byte
asciiChars = StrConv(AsciiText, vbFromUnicode)
ReDim hexChars(LBound(asciiChars) To UBound(asciiChars)) As String
Dim char As Long
For char = LBound(asciiChars) To UBound(asciiChars)
hexChars(char) = Right$("00" & Hex$(asciiChars(char)), 2)
Next char
HexEncode = HexPrefix & Join(hexChars, "")
End If
End Function
Public Function HexDecode(HexString As String, Optional HexPrefix As String = HEX_STRING_PREFIX)
'Check if there's anything to decode
If HexString = vbNullString Then
HexDecode = vbNullString
Exit Function
Else
If Not StrComp(Left$(HexString, Len(HexPrefix)), HexPrefix, vbTextCompare) = 0 Then
'Unexpected string format
GoTo DecodeError
End If
Dim hexRaw As String
hexRaw = Mid$(HexString, 1 + Len(HexPrefix))
'Check if the string is valid for decoding
If Len(hexRaw) Mod 2 = 1 Then
GoTo DecodeError
End If
Dim numHexChars As Long
numHex
0x00FF....I've written an
EncodeHex and a DecodeHex function to do the conversion.I've avoided using concatenation in favour of performance.
I'm assuming that assigning the results of
CByte("&h80") to a byte array, and then using StrConv to convert the array to a Unicode string, is more efficient than assigning the results of Chr$("&h80") to a string array, and then using Join to concatenate the strings.I need to use this in Excel, so I'm using
CVErr(xlErrValue) to return errors, but this could maybe benefit from being more generic.Sample usage
?HexEncode("FooBar")
0x466F6F426172
?HexDecode("0x466F6F426172")
FooBarVBA Code
```
Option Explicit
Const HEX_STRING_PREFIX As String = "0x"
Const VBA_HEX_PREFIX As String = "&h"
Public Function HexEncode(AsciiText As String, Optional HexPrefix As String = HEX_STRING_PREFIX) As String
If AsciiText = vbNullString Then
HexEncode = AsciiText
Else
Dim asciiChars() As Byte
asciiChars = StrConv(AsciiText, vbFromUnicode)
ReDim hexChars(LBound(asciiChars) To UBound(asciiChars)) As String
Dim char As Long
For char = LBound(asciiChars) To UBound(asciiChars)
hexChars(char) = Right$("00" & Hex$(asciiChars(char)), 2)
Next char
HexEncode = HexPrefix & Join(hexChars, "")
End If
End Function
Public Function HexDecode(HexString As String, Optional HexPrefix As String = HEX_STRING_PREFIX)
'Check if there's anything to decode
If HexString = vbNullString Then
HexDecode = vbNullString
Exit Function
Else
If Not StrComp(Left$(HexString, Len(HexPrefix)), HexPrefix, vbTextCompare) = 0 Then
'Unexpected string format
GoTo DecodeError
End If
Dim hexRaw As String
hexRaw = Mid$(HexString, 1 + Len(HexPrefix))
'Check if the string is valid for decoding
If Len(hexRaw) Mod 2 = 1 Then
GoTo DecodeError
End If
Dim numHexChars As Long
numHex
Solution
I think you have an opportunity for using
Instead of
First, because we're raising an error in several places, I'd make a little utility procedure:
And then the error-handling subroutine could do this:
That way the calling code can handle a runtime error 5 (aka invalid procedure call or argument) with a useful description:
And now you have a function that's just as friendly to use as a UDF as it is in plain VBA code.
This doesn't strike me as intuitive:
"Is value a multiple of X" is usually written as:
That way you're not assuming what the remainder might be - of course here it's either 1 or 0, but the point is that the way the comparison is written in
Application.Caller in that error-handling subroutine, and make the function behave differently when it's used as a UDF vs. when it's called from VBA code.Instead of
GoTo-jumping when there's an invalid argument to early-return an Excel error value that's only really useful when the function is used as a UDF (and confusing when it's called from VBA code), you could be raising an actual meaningful error (which would still be jumping to the DecodeError label).First, because we're raising an error in several places, I'd make a little utility procedure:
Private Sub OnHexDecodeError(ByVal message As String)
Err.Raise 5, "HexDecode", message
End SubIf Not StrComp(Left$(HexString, Len(HexPrefix)), HexPrefix, vbTextCompare) = 0 Then
OnHexDecodeError "Parameter value '" & HexString & "' is not in the expected format."
End IfIf Len(hexRaw) Mod 2 = 1 Then
OnHexDecodeError "Parameter value '" & HexString & "' is invalid."
End IfIf Not IsNumeric(hexchar) Then
OnHexDecodeError "Hex character '" & hexchar & "' is not a valid hexadecimal digit."
End IfAnd then the error-handling subroutine could do this:
DecodeError:
If TypeName(Application.Caller) = "Range" Then
'function is used as a UDF
HexDecode = CVErr(xlErrValue)
Else
'function is called by other VBA code
Err.Raise Err.Number 'rethrow
End IfThat way the calling code can handle a runtime error 5 (aka invalid procedure call or argument) with a useful description:
?HexCode("test")And now you have a function that's just as friendly to use as a UDF as it is in plain VBA code.
This doesn't strike me as intuitive:
If Len(hexRaw) Mod 2 = 1 Then"Is value a multiple of X" is usually written as:
If value Mod x <> 0 ThenThat way you're not assuming what the remainder might be - of course here it's either 1 or 0, but the point is that the way the comparison is written in
foo Mod bar {comparison} never has to change, regardless of what the value of bar is.Code Snippets
Private Sub OnHexDecodeError(ByVal message As String)
Err.Raise 5, "HexDecode", message
End SubIf Not StrComp(Left$(HexString, Len(HexPrefix)), HexPrefix, vbTextCompare) = 0 Then
OnHexDecodeError "Parameter value '" & HexString & "' is not in the expected format."
End IfIf Len(hexRaw) Mod 2 = 1 Then
OnHexDecodeError "Parameter value '" & HexString & "' is invalid."
End IfIf Not IsNumeric(hexchar) Then
OnHexDecodeError "Hex character '" & hexchar & "' is not a valid hexadecimal digit."
End IfDecodeError:
If TypeName(Application.Caller) = "Range" Then
'function is used as a UDF
HexDecode = CVErr(xlErrValue)
Else
'function is called by other VBA code
Err.Raise Err.Number 'rethrow
End IfContext
StackExchange Code Review Q#140703, answer score: 5
Revisions (0)
No revisions yet.