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
* 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.
Copyright © Madis Kaal 2000-