# How to convert numeric string to packed decimal (unsigned)

• ### Question

• I have a numeric string like this: "123456" .  I need to have that data in packed decimal format (unsigned).  The result would look like this if it were in a byte array:  &H12 , &H34, &H56 .  No conversion from decimal to hex, just packing as shown.
Monday, January 18, 2016 10:17 PM

• I have a numeric string like this: "123456" .  I need to have that data in packed decimal format (unsigned).  The result would look like this if it were in a byte array:  &H12 , &H34, &H56 .  No conversion from decimal to hex, just packing as shown.

AFAICT .Net doesn't support packed decimal directly.  All the COM import functions seem to rely on helper tools.

Packed decimal can be created using code like this

```        Dim Source As String = "123456"
Dim S As Char() = Source.ToArray

Dim R(2) As Byte

For I As Integer = 0 To 2
Dim Temp As Byte = (Val(S(I * 2)) And &HFF) << 4
Temp = Temp Or (Val(S((I * 2) + 1)) And &HFF)
R(I) = Temp
Next```

• Proposed as answer by Tuesday, January 19, 2016 12:43 AM
• Marked as answer by Tuesday, January 19, 2016 12:54 AM
Tuesday, January 19, 2016 12:19 AM
•  I am not really sure what you are asking or want as the outcome.  There are only 3 bytes in your example which is not enough to convert it to an unsigned integer or a Decimal value.  There would need to be 1 more byte to make an unsigned Integer which has 4 bytes and a Decimal value has 16 bytes.

If you just want to split a string into the 3 numbers and add them to a byte array or a List(Of Byte) then perhaps this will do what you want.  You could pad the list with a zero to make up for the missing byte and then convert the bytes to a UInteger using the BitConverter class but,  there is not a method for getting a Decimal value from 16 bytes.

If you need to use an Array of the bytes from the List,  you can simply use the ToArray method to do that like "Bts.ToArray".

```    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim s As String = "123456"
Dim bts As New List(Of Byte)

For i As Integer = 0 To s.Length - 1 Step 2
Next

For Each b As Byte In bts
RichTextBox1.AppendText(b.ToString & vbNewLine) 'just to show the 3 numbers from the list of bytes in a RichTextBox
Next
End Sub```

If this is not what you want then please give us a little more detail as to what you want as an outcome.  An actual Decimal value or whatever.

If you need an actual Decimal type then you can look at the link below.  There is an example of how you can convert a Byte Array to a Decimal and a Decimal to a Byte Array.

Convert System.Decimal to and from Byte Arrays (VB & C#)

If you say it can`t be done then i`ll try it

• Edited by Monday, January 18, 2016 11:40 PM
• Marked as answer by Tuesday, January 19, 2016 12:54 AM
Monday, January 18, 2016 11:35 PM

### All replies

• May I suggest this GetBytes function described here: "How to: Convert Strings into an Array of Bytes in VB" found here: https://msdn.microsoft.com/en-us/library/ms172828.aspx

The GetBytes method is described in details here: https://msdn.microsoft.com/en-us/library/ds4kkd55.aspx

Cyrille Precetti
Bonne Année! Happy New Year!

Monday, January 18, 2016 10:42 PM
•  I am not really sure what you are asking or want as the outcome.  There are only 3 bytes in your example which is not enough to convert it to an unsigned integer or a Decimal value.  There would need to be 1 more byte to make an unsigned Integer which has 4 bytes and a Decimal value has 16 bytes.

If you just want to split a string into the 3 numbers and add them to a byte array or a List(Of Byte) then perhaps this will do what you want.  You could pad the list with a zero to make up for the missing byte and then convert the bytes to a UInteger using the BitConverter class but,  there is not a method for getting a Decimal value from 16 bytes.

If you need to use an Array of the bytes from the List,  you can simply use the ToArray method to do that like "Bts.ToArray".

```    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim s As String = "123456"
Dim bts As New List(Of Byte)

For i As Integer = 0 To s.Length - 1 Step 2
Next

For Each b As Byte In bts
RichTextBox1.AppendText(b.ToString & vbNewLine) 'just to show the 3 numbers from the list of bytes in a RichTextBox
Next
End Sub```

If this is not what you want then please give us a little more detail as to what you want as an outcome.  An actual Decimal value or whatever.

If you need an actual Decimal type then you can look at the link below.  There is an example of how you can convert a Byte Array to a Decimal and a Decimal to a Byte Array.

Convert System.Decimal to and from Byte Arrays (VB & C#)

If you say it can`t be done then i`ll try it

• Edited by Monday, January 18, 2016 11:40 PM
• Marked as answer by Tuesday, January 19, 2016 12:54 AM
Monday, January 18, 2016 11:35 PM
• I thought I'd been pretty clear, but apparently not.  I have string of numbers, let's say "123456" which will be sent to a hardware device over a serial port.  The device requires that the numbers be in what we used to call "packed decimal" format.  So, the first two numbers, "12" will be represented as a single byte with the binary value of 12 or like this in binary - 0001 0010.  The second byte will have a binary value of 34 and the third byte will have a binary value of 56.  Forget the unsigned integer business.  A signed packed decimal number as I described above would appear in hex as - 123456F where F is the sign.  An unsigned packed decimal number would be 123456 and that's what I need.

I could do it all with bit shifts and associated manipulation, but there's probably a better way to do it.

Tuesday, January 19, 2016 12:09 AM
• I have a numeric string like this: "123456" .  I need to have that data in packed decimal format (unsigned).  The result would look like this if it were in a byte array:  &H12 , &H34, &H56 .  No conversion from decimal to hex, just packing as shown.

AFAICT .Net doesn't support packed decimal directly.  All the COM import functions seem to rely on helper tools.

Packed decimal can be created using code like this

```        Dim Source As String = "123456"
Dim S As Char() = Source.ToArray

Dim R(2) As Byte

For I As Integer = 0 To 2
Dim Temp As Byte = (Val(S(I * 2)) And &HFF) << 4
Temp = Temp Or (Val(S((I * 2) + 1)) And &HFF)
R(I) = Temp
Next```

• Proposed as answer by Tuesday, January 19, 2016 12:43 AM
• Marked as answer by Tuesday, January 19, 2016 12:54 AM
Tuesday, January 19, 2016 12:19 AM
• Excellent!  I couldn't find any reference to packed decimal in the online documentation, so suspected it wasn't supported directly.  I didn't know how to accomplish the bit shifting, but now I see.  I had to modify the code just slightly to get the right result (see last line before Next):

```        Dim Source As String = "123456"
Dim S As Char() = Source.ToArray

Dim R(2) As Byte

For I As Integer = 0 To 2
Dim Temp As Byte = (Val(S(I * 2)) And &HFF) << 4
Temp = Temp Or (Val(S((I * 2) + 1)) And &HFF)
R(I) = hex(Temp)
Next```

The R array was thus: R(0) = 12, R(1) = 34 and R(2) = 56.   Many thanks for your help.

• Marked as answer by Tuesday, January 19, 2016 12:38 AM
• Unmarked as answer by Tuesday, January 19, 2016 12:54 AM
Tuesday, January 19, 2016 12:38 AM
• "Packed decimal can be created using code like this"

Very interesting.  I knew you would know how to do this.   8)

If you say it can`t be done then i`ll try it

Tuesday, January 19, 2016 12:39 AM

If you say it can`t be done then i`ll try it

Tuesday, January 19, 2016 12:43 AM
• I had to modify the code just slightly to get the right result (see last line before Next)

That change means the code no longer conforms to your original description, or to the usual meaning of packed decimal.  This is the original result:

which agrees with what you originally posted. Packed decimal means that each digit is represented in one nibble.   Your change has converted the two nibbles to a byte value.

Tuesday, January 19, 2016 1:11 AM
• You are correct.  My brief test was faulty.  The code you provided stands as correct.
Tuesday, January 19, 2016 2:39 AM
• Another solution, and FWIW I am not a fan of Val().

```    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim buf() As Byte = StrToPckd("123456789")
End Sub

Public Function StrToPckd(StrToPck As String) As Byte()
Dim buf As New List(Of Byte)
'make source even, pad left or right
If (StrToPck.Length And 1) = 1 Then
StrToPck = StrToPck.Insert(0, "0") 'left
'Source &= "0" 'right
End If

Dim pckd As Byte
For x As Integer = 0 To StrToPck.Length - 1
Dim b As Byte
If Byte.TryParse(StrToPck(x), b) Then
If (x And 1) = 0 Then
pckd = b << 4
Else
pckd = pckd Or b
End If
Else
'todo error - not a number
Stop
End If
Next
Return buf.ToArray
End Function```

"Those who use Application.DoEvents() have no idea what it does and those who know what it does never use it." - MSDN User JohnWein    Multics - An OS ahead of its time.

• Edited by Tuesday, January 19, 2016 12:43 PM
Tuesday, January 19, 2016 12:25 PM