1

I am trying to avoid loop in the following code

Sub Demo()
    Dim v, en As ASCIIEncoding, myArr() As Byte, i As Long
    Set en = New ASCIIEncoding
    v = Array(89, 97, 115, 115, 101, 114)
    ReDim myArr(0 To UBound(v))
    For i = LBound(v) To UBound(v)
        myArr(i) = v(i)
    Next i
    Debug.Print en.GetString(myArr)
End Sub

I have used loops to convert the 1d array which is Variant v to Byte myArr. The code is working but I am trying to search for a way to avoid using loops.

YasserKhalil
  • 9,138
  • 7
  • 36
  • 95
  • 1
    What is your goal? To convert "Yasser" into a Byte array? – Brian M Stafford Oct 30 '20 at 18:53
  • 1
    @BrianMStafford - this goal should have been covered by [UCase for each statement](https://stackoverflow.com/questions/63289592/ucase-for-each-statement/63291236#63291236) – T.M. Oct 30 '20 at 19:02
  • Thanks a lot. But my question is different. Is it possible to store the bytes that are in the Variant array into Byte array directly? – YasserKhalil Oct 30 '20 at 19:17
  • 1
    Don't know how to solve it by pure VBA. - Possibly the system approach at [How to add a counter column to existing matrix](https://stackoverflow.com/questions/46712110/how-to-add-a-counter-column-to-existing-matrix-in-vba) of @FlorentB.](https://stackoverflow.com/users/2887618/florent-b) regarding an inserted integers' column might give you a starting idea. – T.M. Oct 31 '20 at 09:05

1 Answers1

2

The answer is No, you cannot just assign a Variant Array to a Byte Array without using a loop. A Byte occupies 1 byte in memory as the name suggests and a Variant holding a Byte will ocupy 16 bytes (x32) or 24 bytes (x64). The alignment in the SAFEARRAY (structure holding the array in COM) will not allow for a simple memory copy. Not to mention that the Variant can hold values outside the 0-255 range of a Byte.

I would suggest to use an auxiliary function to achieve your goal:

Public Function ArrayByte(ParamArray values() As Variant) As Byte()
    Dim b() As Byte
    Dim v As Variant
    Dim i As Long
    '
    ReDim b(LBound(values) To UBound(values))
    i = LBound(b)
    For Each v In values
        b(i) = CByte(v) 'This can throw an error. You might want to implement some checks in order to raise a custom error
        i = i + 1
    Next v
    ArrayByte = b
End Function

This way, your code would become:

Sub Demo()
    Dim en As ASCIIEncoding
    Dim myArr() As Byte

    Set en = New ASCIIEncoding
    myArr = ArrayByte(89, 97, 115, 115, 101, 114)

    Debug.Print en.GetString(myArr)
End Sub
Cristian Buse
  • 4,020
  • 1
  • 13
  • 34