From: grw@*clark.net* (George Waddell) Newsgroups: comp.databases.btrieve Subject: VB 5 and BTRIEVE (long) Date: Sat, 12 Dec 1998 16:00:09 GMT Organization: Verio Mid-Atlantic
Recently, there has been considerable traffic on this NG about BTRIEVE and
VB5.0. The problem with accessing BTRIEVE this way is that VB has some "optimization"
characteristics that will make you pull your hair out.
The problem is that VB5 (or VB4 32-bit) pads the user defined types to fit
on addressing boundaries. These are the rules:
* Integers - must be on even (WORD) boundaries.
* Longs - must be on DWORD boundaries
* Floats - must be on DWORD boundaries
Look at the following UDT:
Type USELESS_UDT
sKey As String * 7
sDesc As String * 36
iData As Integer
End Type
This is gauranteed to give problems. VB5 will secretly add a byte after sDesc.
The iData member will be incorrect and so will every member after that. If you
have long or float data then the problem is only compounded. Oh, well. Thats
what we get for using a language that has no international standard.
I've seen two solutions to this. I believe Jim Kyle has a solution on his web
site where he loads the entire record into a string and then uses MID$ to pull
the individual columns out. Thats the kind of stuff I used to do when
I was writing Quickbasic 1.0 programs. Not something I want to recall.
The second solution is from Pervasive. That idea is to use strings and use
LSET on the data. This is in fact part of the solution but it doesn't work that
way under VB5.
The first thing you have to do is to make all of your integers, longs, and
floats in your UDT to fixed length
strings.Like this:
* integers - String * 2
* longs - String * 4
* singles - String * 4
* doubles - String * 8
Next define these UDTs. This is what we will use to do the conversion.
Public Type UdtByte2
bBuffer(1) As Byte
End Type
Public Type UdtByte4
bBuffer(3) As Byte
End Type
Public Type UdtByte8
bBuffer(7) As Byte
End Type
Public Type UdtLong
lBuffer As Long
End Type
Public Type UdtDouble
dfBuffer As Double
End Type
Public Type UdtSingle
fBuffer As Single
End Type
Public Type UdtInteger
iBuffer As Integer
End Type
Then you need to define routines for saving and reading the data. Here's an
example.
Public Function String4ToLong(sIn As String) As Long
Dim i As Integer
Dim oByte As UdtByte4
Dim oLong As UdtLong
'Loop for each character
For i = 1 To 4
oByte.bBuffer(i - 1) = Asc(Mid$(sIn, i, 1))
Next i
'the bytes in the long are reversed
'The Lset function takes care of this
LSet oLong = oByte
'Set the return value
String4ToLong = oLong.bBuffer
End Function
And the reverse
Public Function LongToString4(lIn As Long) As String
Dim sOut As String * 4
Dim oByte As UdtByte4
Dim oLong As UdtLong
Dim i As Integer
'Set the long equal to the User-defined type for Long
oLong.bBuffer = lIn
'LSet to reverse the bytes
LSet oByte = oLong
'Copy the CHR value for each byte into the string to return
For i = 1 To 4
Mid(sOut, i, 1) = Chr(oByte.bBuffer(i - 1))
Next
'Set the return value
LongToString4 = sOut
End Function
Do the same for the other types.
I've had to transcribe some code to show this. Any mistakes I have made I hope
are obvious and easily fixable.But the general idea is here and it does work.
Hope I've helped.
George
Copyright © Madis Kaal 2000-