This occasionally comes up when we need to get a UDT into a String, and back again. We may want to do this for inter-process communications, or maybe to easily get it into a Variant or Collection, or several other reasons.
One way is to serialize it with a named pipe. This is effectively the same as writing the UDT to a file, and then opening the file as Binary and reading in the bytes, and then stuffing them into a String.
However, it doesn't need to be this complicated. We can just directly copy the UDT into our string. And that's what I've outlined. As a note, any internal and/or external padding should be handled just fine, as LenB picks that up.
Here's some code for a BAS module to do this:
And here's a bit of test code you can put into a Form1:
Ok yes, I understand that this is specific to any particular UDT. But that's sort of always the case with these UDTs. To use this, just patch in your UDT declaration (instead of the "Public Type TestUdtType" declaration), and then search-and-replace all occurrences of TestUdtType with the name of your UDT, and you're all set.
In fact, if you've got several UDTs you wish to do this with, you can just make multiple copies of the StringFromUdt and UdtFromString functions, and name them different names to denote your UDT names.
-----------
This isn't complicated stuff, but it is something that comes up somewhat often.
Also, as a caveat, you probably shouldn't do this with UDTs that contain pointers (to BSTR Strings, objects, and/or dynamic arrays). It will still work, but UDTs with pointers must be handled with great care when copying them in any way other than a regular Let statement.
One way is to serialize it with a named pipe. This is effectively the same as writing the UDT to a file, and then opening the file as Binary and reading in the bytes, and then stuffing them into a String.
However, it doesn't need to be this complicated. We can just directly copy the UDT into our string. And that's what I've outlined. As a note, any internal and/or external padding should be handled just fine, as LenB picks that up.
Here's some code for a BAS module to do this:
Code:
Option Explicit
'
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (ByRef Destination As Any, ByRef Source As Any, ByVal Length As Long)
'
Public Type TestUdtType
s1 As String * 5
s2 As String * 5
i1 As Long
d1 As Double
End Type
'
Public Function StringFromUdt(u As TestUdtType) As String
StringFromUdt = String$((LenB(u) + 1&) \ 2&, vbNullChar)
CopyMemory ByVal StrPtr(StringFromUdt), u, LenB(u) ' On odd length UDTs, it won't completely fill the last Unicode character, but that's fine.
End Function
Public Function UdtFromString(s As String) As TestUdtType
If Len(s) <> (LenB(UdtFromString) + 1&) \ 2& Then Err.Raise 13&, , "String isn't correct length for this UDT"
CopyMemory UdtFromString, ByVal StrPtr(s), LenB(UdtFromString)
End Function
Code:
Option Explicit
Private Sub Form_Load()
Dim u As TestUdtType
u.s1 = "asdf"
u.s2 = "qwer"
u.i1 = 1234
u.d1 = 5.678
Dim s As String
s = StringFromUdt(u)
Debug.Print s
Dim u2 As TestUdtType
u2 = UdtFromString(s)
Debug.Print u2.s1, u2.s2, u2.i1, u2.d1
End Sub
In fact, if you've got several UDTs you wish to do this with, you can just make multiple copies of the StringFromUdt and UdtFromString functions, and name them different names to denote your UDT names.
-----------
This isn't complicated stuff, but it is something that comes up somewhat often.
Also, as a caveat, you probably shouldn't do this with UDTs that contain pointers (to BSTR Strings, objects, and/or dynamic arrays). It will still work, but UDTs with pointers must be handled with great care when copying them in any way other than a regular Let statement.