Results 1 to 33 of 33

Thread: Dynamic UDT's saving to Random Access File *Help*

  1. #1

    Thread Starter
    New Member
    Join Date
    Oct 2014
    Posts
    13

    Angry Dynamic UDT's saving to Random Access File *Help*

    So we have the following UDT's defined:

    ***************

    Public Type Student
    udtAccount As Account 'Student account information
    udtPracticeQuizResults() As PracticeQuizResults 'Student results on practice quiz
    udtFinalQuizResults As FinalQuizResults 'Student results on final quiz
    End Type

    Private Type PracticeQuizResults
    intNumAttempts As Integer 'Number of attempts on quiz
    blnCorrect() As Boolean 'Number of correct answers on quiz
    intNumCorrect As Integer 'Number of correct answers on quiz
    intQuestionIDs() As Integer 'ID of questions used on quiz
    End Type


    **************

    I am now trying to write a random access file using this, however it gives us a bad record length. I think this might be because we are using ReDim on the arrays in the udt we created in the form, not the overall 'type', however I don't know if there is a way to resize the original arrays in the type statement. Thanks in advance Here's what we have done:

    Dim intFreeFile As Integer
    Dim lngRecLength As Long
    Dim udtStudent As Student
    Dim intI As Integer
    Dim intJ As Integer

    ' ** resize arrays **
    ReDim udtStudent.udtPracticeQuizResults(1 To 10)

    For intI = 1 To 10
    ReDim udtStudent.udtPracticeQuizResults(intI).blnCorrect(1 To 10)
    ReDim udtStudent.udtPracticeQuizResults(intI).intQuestionIDs(1 To 10)
    Next

    '** give a value to the elements of the array **
    For intI = 1 To 10
    For intJ = 1 To 10
    udtStudent.udtPracticeQuizResults(intI).blnCorrect(intJ) = True
    udtStudent.udtPracticeQuizResults(intI).intQuestionIDs(intJ) = intJ
    Next

    udtStudent.udtPracticeQuizResults(intI).intNumAttempts = intI
    udtStudent.udtPracticeQuizResults(intI).intNumCorrect = 10
    Next

    '** write to file **
    intFreeFile = FreeFile
    lngRecLength = LenB(udtStudent)

    Open strAppPath & "\Students.dat" For Random As #intFreeFile Len = lngRecLength


    Put #intFreeFile, 1, udtStudent '*************PRODUCES BAD RECORD LENGTH ERROR****************

    Close #intFreeFile

  2. #2
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: Dynamic UDT's saving to Random Access File *Help*

    A random access file can be used for many reasons, but it is important for reading to have redim anything to the size that you save before. To do that you can save UDT as parts and for those parts that you have a variable length as an array you can export the number of items and then the array, so in reading you take that number you redim the array and you can load it. For all of this you have to remember that every binary files start from position 1, so an empty file has LOF(f)=0 and you can write to LOF(f)+1, so to position 1, You can ask for position using a SEEK(f), but not needed because you write at the end (LOF(f)+1), and before the writing you can pass this number to a helper file that can give us the length of file, if you have standard length, or you can write the position of the next record in a list, so you can read the file reading first the positions. A better solution is to write at the end of record, the offset for seek that you subtract to find the previous record.
    So for your example...The Len is a buffer not a record...in the Open statement that help the system to allocate memory. You can ignore that Len. Break the parts of udtStudent to pieces for saving. For strings use byte arrays. For arrays (so for strings too) use a long before to indicate the size to be fixed before you read. If you want make a second file for writing the indexes to those records, maybe you can write a key together with the seek pointer, and use it to find in memory, and then pick the record with one moving of the head of the disk..

  3. #3
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: Dynamic UDT's saving to Random Access File *Help*

    Dill,

    First, I hope you realize that you didn't give us the full UDT definitions. The "Public Type Student" UDT has nested UDTs (Account, PracticeQuizResults, & FinalQuizResults). You did give us PracticeQuizResults but not the other two. But maybe it's enough to get things sorted out.

    First, a variable declared with a UDT containing a dynamic array is not going to have the length you think. The dynamic array is only going to take up four bytes in the UDT (the pointer to the array) no matter how many elements are ultimately placed into the array. If you're going to use UDTs in conjunction with Random Access, I'd strongly recommend that you make everything in the UDTs static (both strings and arrays). That way, all the data will actually be IN the UDT, and it will never change length. Also, a variable declared with your UDT will report the correct length.

    If you actually have fixed record sizes (as is required for random access), then you should know your array lengths before you need to use them.

    Here's an example of your problem:

    Code:
    Option Explicit
    
    Private Type test
        b() As Long
    End Type
    
    Private Sub Form_Load()
        Dim t As test
        '
        ReDim t.b(1 To 100)
        '
        MsgBox Len(t)
        '
        Unload Me
    End Sub
    The above MsgBox is always going to report "4" because all the Len sees is the "pointer" to the dynamic array, and not the actual data. Whereas the following would be different:

    Code:
    Option Explicit
    
    Private Type test
        b(1 To 100) As Long
    End Type
    
    
    Private Sub Form_Load()
        Dim t As test
        '
        MsgBox Len(t)
        '
        Unload Me
    End Sub
    This time (immediately above), the Len(t) will report 400, 4 bytes per long times 100. Also this time, the data is actually IN the UTD as opposed to elsewhere in memory.

    I think that's the bulk of your problem.

    As a comment, is this just some exercise? Because, if not, I'd strongly recommend that you use the DAO (or ADO) and write your data into an MDB (Microsoft Access) data file. It's just MUCH more manageable that way.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  4. #4

    Thread Starter
    New Member
    Join Date
    Oct 2014
    Posts
    13

    Re: Dynamic UDT's saving to Random Access File *Help*

    Alright thank you. We will just set an array size when we create the udt. We were just wondering if there was a more efficient way of doing this :P Thank you!

  5. #5
    VB-aholic & Lovin' It LaVolpe's Avatar
    Join Date
    Oct 2007
    Location
    Beside Waldo
    Posts
    19,541

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by DillPickleSwimmer View Post
    Alright thank you. We will just set an array size when we create the udt. We were just wondering if there was a more efficient way of doing this :P Thank you!
    As Elroy mentioned a database screams, "Pick Me" here. Databases are easy to adjust if your data requirements change.

    A multi-file CSV format might work, but sounds a bit complicated to me.

    Other options if you really don't want to use a database is to create your own custom file structure, but you will have to spend time to figure out how you can write it and read it reliably, along with dealing with potential of structure expansion down the road.
    Insomnia is just a byproduct of, "It can't be done"

    Classics Enthusiast? Here's my 1969 Mustang Mach I Fastback. Her sister '67 Coupe has been adopted

    Newbie? Novice? Bored? Spend a few minutes browsing the FAQ section of the forum.
    Read the HitchHiker's Guide to Getting Help on the Forums.
    Here is the list of TAGs you can use to format your posts
    Here are VB6 Help Files online


    {Alpha Image Control} {Memory Leak FAQ} {Unicode Open/Save Dialog} {Resource Image Viewer/Extractor}
    {VB and DPI Tutorial} {Manifest Creator} {UserControl Button Template} {stdPicture Render Usage}

  6. #6
    PowerPoster
    Join Date
    Aug 2011
    Location
    B.C., Canada
    Posts
    2,887

    Cool Re: Dynamic UDT's saving to Random Access File *Help*

    Instead of using an array you could use single variable/element in the udt and use a coma to split your answers. Then saving to file would be easy.

    Here is an example
    http://www.vbforums.com/showthread.p...inary-file-vb6

    Edit:
    It does not show how to split using a comma but that is easy to add use Split()

  7. #7
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: Dynamic UDT's saving to Random Access File *Help*

    Oh geez. LMAO. Maybe I should dust off some of my old B-TREE routines. Heck, I had one that had doubly-linked record transaction loops as children on BTREE indices. All fixed record sizes though. hahaha, geez, I haven't thought of that code in AGES.

    Gotta love: rs.Seek "=", "Bob", "Smith"
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  8. #8
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: Dynamic UDT's saving to Random Access File *Help*

    VB is perfectly capable to save an UDT in one go - no matter what it's contents are
    (dynamic strings, dynamic arrays, other nested UDTs or UDT-Arrays).

    So in your case, if you want to hold one student per File, you only have to use:
    Code:
    Sub WriteStudent(udtStudent As Student, FileName as String)
    Dim FNr as Long: FNr = FreeFile
      Open FileName For Binary As FNr
         Put FNr, , udtStudent
      Close FNr
    End Sub
    That's all what's needed.

    And to read the single student-UDT back you would use:
    Code:
    Function ReadStudent(FileName as String) As Student
    Dim FNr as Long: FNr = FreeFile
      Open FileName For Binary As FNr
         Get FNr, , ReadStudent
      Close FNr
    End Sub
    If it's about many students you want to save this way, then just define an outer UDT:
    Code:
    Type tStudents
      Students() As Student
    End Type
    The appropriate Filehandling-Code for dealing with that aggregating UDT would be the same,
    only the TypeName needs to be adjusted:

    Code:
    Sub WriteStudents(Students As tStudents, FileName as String)
    Dim FNr as Long: FNr = FreeFile
      Open FileName For Binary As FNr
         Put FNr, , Students 
      Close FNr
    End Sub
    That's all what's needed.

    And to read the multiple-students-UDT back you would use:
    Code:
    Function ReadStudents(FileName as String) As tStudents
    Dim FNr as Long: FNr = FreeFile
      Open FileName For Binary As FNr
         Get FNr, , ReadStudents
      Close FNr
    End Sub
    Olaf
    Last edited by Schmidt; Nov 1st, 2014 at 01:11 AM.

  9. #9
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by Schmidt View Post
    VB is perfectly capable to save an UDT in one go - no matter what it's contents are
    (dynamic strings, dynamic arrays, other nested UDTs or UDT-Arrays).

    So in your case, if you want to hold one student per File, you only have to use:
    Code:
    Sub WriteStudent(udtStudent As Student, FileName as String)
    Dim FNr as Long: FNr = FreeFile
      Open FileName For Binary As FNr
         Put FNr, , udtStudent
      Close FNr
    End Sub
    That's all what's needed.

    And to read the single student-UDT back you would use:
    Code:
    Function ReadStudent(FileName as String) As Student
    Dim FNr as Long: FNr = FreeFile
      Open FileName For Binary As FNr
         Get FNr, , ReadStudent
      Close FNr
    End Sub
    If it's about many students you want to save this way, then just define an outer UDT:
    Code:
    Type tStudents
      Students() As Student
    End Type
    The appropriate Filehandling-Code for dealing with that aggregating UDT would be the same,
    only the TypeName needs to be adjusted:

    Code:
    Sub WriteStudents(Students As tStudents, FileName as String)
    Dim FNr as Long: FNr = FreeFile
      Open FileName For Binary As FNr
         Put FNr, , Students 
      Close FNr
    End Sub
    That's all what's needed.

    And to read the single student-UDT back you would use:
    Code:
    Function ReadStudents(FileName as String) As tStudents
    Dim FNr as Long: FNr = FreeFile
      Open FileName For Binary As FNr
         Get FNr, , ReadStudents
      Close FNr
    End Sub
    Olaf
    We all know Open command is not Unicode compatible. What is the workaround for such UTD saving ?

    Code:
    Type tStudents
         Students() As Student
    End Type

  10. #10
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by Jonney View Post
    We all know Open command is not Unicode compatible. What is the workaround for such UTD saving ?

    Code:
    Type tStudents
         Students() As Student
    End Type
    There's two issues with Unicode and VBs old FileFunctions.

    One is, that the Open command doesn't support Unicode-Pathnames.
    Well, for that we have a relative easy workaround, which would be:

    Code:
    Private Declare Function GetShortPathNameW& Lib "kernel32" (ByVal lpLongPath&, ByVal lpShortPath&, ByVal nBufLen&)
    
    Function GetShortPath(PathName As String) As String
    Dim S As String
      S = Space$(260)
      GetShortPath = Left$(S, GetShortPathNameW(StrPtr(PathName), StrPtr(S), Len(S)))
    End Function
    Meaning, that within the Open Statement, you would not directly pass the Unicode-PathVariable, but:
    Code:
      Open GetShortPath(UnicodeFileName) For Binary As FNr
    instead use an indirection per GetShortPath...

    The second issue is, that VB does an ANSI-conversion on all Strings and String-Arrays before writing to disk,
    no matter how "deeply hidden" (or nested in "inner UDTs") within the outer UDT those are.

    One (not soo slick, but bearable) workaround for that would be, to define any String-Member within the UDT(s)
    as a dynamic Bytearray - since those wouldn't be touched by the automatic ANSI-reduction - and the conversion
    between VBs Unicode-Strings and ByteArrays is handled quite smooth and direct by the VB-compiler.

    e.g. if you had a Type:

    Code:
    Type tStudent 
         StudentName As String
        ...
    End Type
    And redefine it (for proper Unicode-saving) as:
    Code:
    Type tStudent 
         StudentName() As Byte
        ...
    End Type
    You wouldn't need to change all that much in cour code, since assignments like below:
    Dim Student As tStudent, strStudentName As String
    strStudentName = "SomeName"
    Student.StudentName = strStudentName

    Would work without hickup - as would do the opposite assignment-direction:
    Dim Student As tStudent, strStudentName As String
    Student.StudentName = "SomeName"
    strStudentName = Student.StudentName

    What's not working directly is ByRef-Passing to VB-routines which expect String-Arguments,
    whilst ByVal-Passing would still work without any issues.

    'Into a Form
    Code:
    Option Explicit
    
    Private Type tStudent
      StudentName() As Byte
    End Type
    
    Private Sub Form_Load()
    Dim Student As tStudent
      Student.StudentName = "SomeName"
      TestByValPassing Student.StudentName 'works without problems
      TestByRefPassing CStr(Student.StudentName) 'needs a CStr-Wrapping
    End Sub
    
    Private Sub TestByValPassing(ByVal S As String)
      MsgBox S
    End Sub
    
    Private Sub TestByRefPassing(S As String)
      MsgBox S
    End Sub

    HTH - otherwise I'd agree with the others, who mentioned to use DBs instead (which nowadays
    have no problem with Unicode-String-Storage).


    Olaf
    Last edited by Schmidt; Nov 1st, 2014 at 02:23 AM.

  11. #11
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by Schmidt View Post
    There's two issues with Unicode and VBs old FileFunctions.

    One is, that the Open command doesn't support Unicode-Pathnames.
    Well, for that we have a relative easy workaround, which would be:

    Code:
    Private Declare Function GetShortPathNameW& Lib "kernel32" (ByVal lpLongPath&, ByVal lpShortPath&, ByVal nBufLen&)
    
    Function GetShortPath(PathName As String) As String
    Dim S As String
      S = Space$(260)
      GetShortPath = Left$(S, GetShortPathNameW(StrPtr(PathName), StrPtr(S), Len(S)))
    End Function
    Meaning, that within the Open Statement, you would not directly pass the Unicode-PathVariable, but:
    Code:
      Open GetShortPath(UnicodeFileName) For Binary As FNr
    instead use an indirection per GetShortPath...

    The second issue is, that VB does an ANSI-conversion on all Strings and String-Arrays before writing to disk,
    no matter how "deeply hidden" (or nested in "inner UDTs") within the outer UDT those are.

    One (not soo slick, but bearable) workaround for that would be, to define any String-Member within the UDT(s)
    as a dynamic Bytearray - since those wouldn't be touched by the automatic ANSI-reduction - and the conversion
    between VBs Unicode-Strings and ByteArrays is handled quite smooth and direct by the VB-compiler.

    e.g. if you had a Type:

    Code:
    Type tStudent 
         StudentName As String
        ...
    End Type
    And redefine it (for proper Unicode-saving) as:
    Code:
    Type tStudent 
         StudentName() As Byte
        ...
    End Type
    You wouldn't need to change all that much in cour code, since assignments like below:
    Dim Student As tStudent, strStudentName As String
    strStudentName = "SomeName"
    Student.StudentName = strStudentName

    Would work without hickup - as would do the opposite assignment-direction:
    Dim Student As tStudent, strStudentName As String
    Student.StudentName = "SomeName"
    strStudentName = Student.StudentName

    What's not working directly is ByRef-Passing to VB-routines which expect String-Arguments,
    whilst ByVal-Passing would still work without any issues.

    'Into a Form
    Code:
    Option Explicit
    
    Private Type tStudent
      StudentName() As Byte
    End Type
    
    Private Sub Form_Load()
    Dim Student As tStudent
      Student.StudentName = "SomeName"
      TestByValPassing Student.StudentName 'works without problems
      TestByRefPassing CStr(Student.StudentName) 'needs a CStr-Wrapping
    End Sub
    
    Private Sub TestByValPassing(ByVal S As String)
      MsgBox S
    End Sub
    
    Private Sub TestByRefPassing(S As String)
      MsgBox S
    End Sub

    HTH - otherwise I'd agree with the others, who mentioned to use DBs instead (which nowadays
    have no problem with Unicode-String-Storage).


    Olaf
    Sir, you save me from annoying problems on UDT's saving which disturbed me for many years.

    I have to use CreateFile,WriteFile,ReadFile APIs and more complicated codes for Unicode saving instead of VB MAGIC PUT command which is very smart for UDT data.

    I mark this thread and verify further if I got chance. Thank you,Sir.

  12. #12
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: Dynamic UDT's saving to Random Access File *Help*

    So I learn something here..about saving UDT. I think the use of udt is something from the past, like a retro programming. The problem as stated is for saving and reading data. So why a database isn't good enough? Because there is the unicode issue. So how we can use unicode with a DAO3.5, an easy database system, that has only one field that we can put unicode data, the OLE? That field is all we need. When we would to search for a key...that key can be exist in an ole type filed as a series of a srting and a unique number. So all the data have to stored by using ole field and the key with the unique number. All we have to do is to get the keys like that chr$(1)+name$+chr$(2)+position$+chr$(1), so when we search for a key an INSTR(allKey$, chr$(1)+name$) give the position of first chr$(1). So we have our own search utility (not from the database) and we set the searching from database only in arithmetic variables (and indexes). Using database we can get more from using binary files and setting arrays and do all the data management. And for a second reason...a database can be read after years..as a standard format...but a binary file has no way to say what it is...if we loose the specific reading routine.

  13. #13
    Frenzied Member
    Join Date
    Jan 2010
    Posts
    1,103

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by georgekar View Post
    So I learn something here..about saving UDT. I think the use of udt is something from the past, like a retro programming. The problem as stated is for saving and reading data. So why a database isn't good enough? Because there is the unicode issue. So how we can use unicode with a DAO3.5, an easy database system, that has only one field that we can put unicode data, the OLE? That field is all we need. When we would to search for a key...that key can be exist in an ole type filed as a series of a srting and a unique number. So all the data have to stored by using ole field and the key with the unique number. All we have to do is to get the keys like that chr$(1)+name$+chr$(2)+position$+chr$(1), so when we search for a key an INSTR(allKey$, chr$(1)+name$) give the position of first chr$(1). So we have our own search utility (not from the database) and we set the searching from database only in arithmetic variables (and indexes). Using database we can get more from using binary files and setting arrays and do all the data management. And for a second reason...a database can be read after years..as a standard format...but a binary file has no way to say what it is...if we loose the specific reading routine.
    I agree database is suiable for DillPickleSwimmer's project.
    PSC got the similar project on examine Q&A. DillPickleSwimmer can give a search for reference.

  14. #14
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by georgekar View Post
    So I learn something here..about saving UDT. I think the use of udt is something from the past, like a retro programming.
    An UDT is a fast and memory-efficient (compared to Classes) structuring-element which has its place, nothing "retro" about it.

    Quote Originally Posted by georgekar View Post
    The problem as stated is for saving and reading data. So why a database isn't good enough? Because there is the unicode issue.
    No, Databases these days have no "Unicode-issue", if you choose the right Type-Definition for your Text-Fields.

    Quote Originally Posted by georgekar View Post
    So how we can use unicode with a DAO3.5, an easy database system, that has only one field that we can put unicode data, the OLE? That field is all we need.
    Hmm, a Database with only one Blob-Field, where we put all our Data in?
    Where is the difference then to a ByteArray which gets written to (or read from) a normal File with 3 lines of code (and no DB-Overhead)?

    Quote Originally Posted by georgekar View Post
    When we would to search for a key...that key can be exist in an ole type filed as a series of a srting and a unique number.
    So all the data have to stored by using ole field and the key with the unique number. All we have to do is to get the keys like that chr$(1)+name$+chr$(2)+position$+chr$(1), so when we search for a key an INSTR(allKey$, chr$(1)+name$) give the position of first chr$(1). So we have our own search utility (not from the database)
    George, this is horrible - DBs are thought for easy retrieval, easy filtering, grouping, fast searching, joining entities, sorting etc. -
    you will loose all those features which make DB-Systems so wonderfully easy to use when you don't define appropriate Fields
    (on well-designed Tables/Relations).

    Quote Originally Posted by georgekar View Post
    ...a database can be read after years..as a standard format...but a binary file has no way to say what it is...if we loose the specific reading routine.
    Why can't you see that your idea of how to use Databases (single Blob-Fields, which can only be read by a specific reading routine)
    would have exactly the same problem?

    Olaf
    Last edited by Schmidt; Nov 1st, 2014 at 07:58 AM.

  15. #15
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: Dynamic UDT's saving to Random Access File *Help*

    You read mine text in the wrong way. Thats a man way...so I have to explain. Where I write that all data are held in one blob field?? OLE container can be expanded but isn't a blob from the start, and I never wrote that I would merge fields in one field. I wrote about the "unicode" string, for a key, to replaced with an id, so we can have many tables where keys maybe with more than one field , can have alphanumeric type, and for that we can use a long as an index to a unicode string. So I wrote for using a database and tables of data.
    I would like to know if I can use a ADO with the easy of DAO 3.5. (I have in my m2000 interpreter only the DAO 3.5. I never use ADO, and i can't remember why I dislike it; Can we redistribute the needed dll? Can you elaborate me for what we can do to add database functionality with no dependencies for some other applications, or external setup?

  16. #16
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by georgekar View Post
    You read mine text in the wrong way. Thats a man way...so I have to explain. Where I write that all data are held in one blob field?? OLE container can be expanded but isn't a blob from the start, and I never wrote that I would merge fields in one field. I wrote about the "unicode" string, for a key, to replaced with an id, so we can have many tables where keys maybe with more than one field , can have alphanumeric type, and for that we can use a long as an index to a unicode string. So I wrote for using a database and tables of data.
    Without a concrete example I cannot really understand what you mean, sorry...
    Would be nice, when you'd put some more efforts into your translation into the english-language,
    or come up with code which demonstrates what you had in mind in "VB6-language".

    Quote Originally Posted by georgekar View Post
    I would like to know if I can use a ADO with the easy of DAO 3.5.
    Sure - from my experience yes.


    Quote Originally Posted by georgekar View Post
    (I have in my m2000 interpreter only the DAO 3.5. I never use ADO, and i can't remember why I dislike it; Can we redistribute the needed dll? Can you elaborate me for what we can do to add database functionality with no dependencies for some other applications, or external setup?
    ADO/JET is a fixed part - and shipping with the Win-OS since Win98-SE IMO (at least it's on board from XP onwards).

    You can use it earlybound, when you check-in the reference to "Microsoft ActiveX Data Objects 2.5" (2.8 is the currently highest Typelib).

    But the below example is using ADO LateBound (demonstrating the Unicode-capabilities of the Text-FieldType,
    in conjunction with the MSHFlexGrid, which you would need to check-in over the Component-Dialogue).

    Code:
    Option Explicit
    
    Const JetPrefix = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source="
    
    Private Cnn, Rs, DBFileName As String
    
    Private Sub Form_Load()
      DBFileName = Environ("temp") & "\test.mdb"
      On Error Resume Next
        Kill DBFileName 'Kill our test.mdb-File in the temp-directory (if there is one)
      On Error GoTo 0
      CreateObject("ADOX.Catalog").Create JetPrefix & DBFileName 'create a new, empty *.mdb-File
      
      Set Cnn = CreateObject("ADODB.Connection")
      Cnn.CursorLocation = 3 'adUseClient
      Cnn.Open JetPrefix & DBFileName 'open the Connection
      Cnn.Execute "Create Table Test(ID AutoIncrement, UnicodeField Text)" 'create a new Table-Def
     
      'add a few new records (Unicode-samples from: http://www.cyberactivex.com/unicodetutorialvb.htm)
      Set Rs = CreateObject("ADODB.Recordset")
      Rs.Open "Select * From Test Where 1=0", Cnn, 3, 4 'adOpenStatic, adLockBatchOptimistic
        Rs.AddNew: Rs!UnicodeField = "GRK: " & ChrW$(&H39A) & ChrW$(&H3B1) & ChrW$(&H3BB) & ChrW$(&H3CE) & ChrW$(&H3C2) & " " & ChrW$(&H3AE) & ChrW$(&H3BB) & ChrW$(&H3B8) & ChrW$(&H3B1) & ChrW$(&H3C4) & ChrW$(&H3B5)
        Rs.AddNew: Rs!UnicodeField = "ARA: " & ChrW$(&H645) & ChrW$(&H640) & ChrW$(&H631) & ChrW$(&H62D) & ChrW$(&H628)
        Rs.AddNew: Rs!UnicodeField = "THA: " & ChrW$(&HE01) & ChrW$(&HE32) & ChrW$(&HE23) & ChrW$(&HE15) & ChrW$(&HE49) & ChrW$(&HE2D) & ChrW$(&HE19) & ChrW$(&HE23) & ChrW$(&HE31) & ChrW$(&HE1A)
        Rs.AddNew: Rs!UnicodeField = "CHS: " & ChrW$(&H6B22) & ChrW$(&H8FCE)
      Rs.UpdateBatch
      
      'render Unicode-content of the Rs with a capable TrueType-Font in the MSHFlexGrid
      With MSHFlexGrid1
        .Font.Name = "Arial"
        .ColWidth(-1) = 700
        .ColWidth(2) = 2100
        Set .DataSource = Cnn.Execute("Select * From Test")
      End With
    End Sub
    The above produces the following output in the MSHFlexGrid:


    Olaf

  17. #17
    Frenzied Member
    Join Date
    May 2014
    Location
    Kallithea Attikis, Greece
    Posts
    1,289

    Re: Dynamic UDT's saving to Random Access File *Help*

    Thank you Olaf, I give one day to make master it...

  18. #18
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: Dynamic UDT's saving to Random Access File *Help*

    *laughs and shakes my head*

    I love it. Dill has yet to reply back and we've solved all the problems of databases vs writing our own files, fixed length versus binary files, unicode in either of those files, UDTs in either of those files, unicode filenames, unicode using DAO, and unicode in keys. LMAO.

    Actually, I made an assumption from OP that may or may not have been correct. I assumed he wanted to use a fixed record length file and that it was that criteria we were working with. If that's the case, we do have to be careful about how we define our UDTs.

    Another kind of file structure I once wrote was one with a header, but also an index tacked onto the end. The index had key and pointer pairs. The pointers were to variable length records. The records also also had forward and backward pointers in it. With that scheme, you could use UDTs with dynamic arrays that varied in length. The only major problem was when you wanted to update a record and it was longer than the previous writing of it. You had to either move the entire rest of the file or write it to the end and abandon the space. It was assumed that the keys/pointers was always being pushed out. There was also a routine to re-compact, much like the string garbage collector, or the DAO re-compact routine.

    Heck, many of those schemes got a lot of use. And an "open" file structure (like MS-Access) has both advantages and disadvantages. Without messing with security, one of the problems with MS-Access is that someone else can open your files and muck around in them, possibly corrupting them in a way that makes them unreadable by your program.

    You know? Something I haven't thought about but is worth thinking about is assigning unicode to a standard text field. It's my understanding that they're actually unicode in the MDB file. And, of course, their unicode in the VB6 strings. However, when doing the LETs, VB6 converts them to ASCII. I think I'll start a separate thread for someone to outline it.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  19. #19
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by Elroy View Post
    *laughs and shakes my head*

    I love it. Dill has yet to reply back and we've solved all the problems of databases vs writing our own files, fixed length versus binary files, unicode in either of those files, UDTs in either of those files, unicode filenames, unicode using DAO, and unicode in keys. LMAO.
    Yep - aint that the beauty of an open forum?

    Quote Originally Posted by Elroy View Post
    Actually, I made an assumption from OP that may or may not have been correct. I assumed he wanted to use a fixed record length file and that it was that criteria we were working with. If that's the case, we do have to be careful about how we define our UDTs.
    Exactly - and since the OP had a lot of dynamic arrays in his UDT-defs, this somehow ruled out fixed-length-record writing in VBs random File-Mode.

    Quote Originally Posted by Elroy View Post
    Heck, many of those schemes got a lot of use. And an "open" file structure (like MS-Access) has both advantages and disadvantages. Without messing with security, one of the problems with MS-Access is that someone else can open your files and muck around in them, possibly corrupting them in a way that makes them unreadable by your program.
    Well - "messing around" is possible with basically any file - either per Notepad - or by simply pressing the delete-Key in Explorer...

    Quote Originally Posted by Elroy View Post
    You know? Something I haven't thought about but is worth thinking about is assigning unicode to a standard text field. It's my understanding that they're actually unicode in the MDB file. And, of course, their unicode in the VB6 strings.
    Sure, my last example demonstrated that quite clearly I thought.

    Quote Originally Posted by Elroy View Post
    However, when doing the LETs, VB6 converts them to ASCII. I think I'll start a separate thread for someone to outline it.
    Not sure what you mean by "doing the LETs" - an example would be nice (maybe using the small codebase I posted above in #16).

    Olaf

  20. #20
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: Dynamic UDT's saving to Random Access File *Help*

    Ohhh, LETs? I'm showing my age.

    Code:
    Private Sub Form_Load()
        Dim A As Long
        Dim B As Long
        
        A = 1234
        
        Let B = A
    
    End Sub
    It's an implicit (or explicit, if you like) keyword indicating an assignment. Similar to Set for objects.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  21. #21
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Dynamic UDT's saving to Random Access File *Help*

    No, a Let statement doesn't do anything about String encoding.

    And VB6 doesn't support ASCII at all, I think you have it confused with ANSI which is not the same thing.

  22. #22
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: Dynamic UDT's saving to Random Access File *Help*

    Oh gosh, sorry I wasn't clear enough. And I do tend to use ASCII and ANSI a bit interchangeably, and know there's a difference. Codepages and all of that. I just used the "Let" keyword as an example of what I'm trying to do. I guess, if you thought of it in terms of a "Property Let", VB6 actually could do a Unicode Let. But let's not quibble. Also, I started another thread regarding this issue.

    EDIT: Also, in the strictest of terms, I am clear (as I'm sure everyone is), that a string Let is always a Unicode Let, although it often gets converted to 8 bit data (staying out of ASCII/ANSI terminology) when passing to API calls, file I/O, and other things. That's actually sort of the problem for all of us trying to push Unicode everywhere.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  23. #23

    Thread Starter
    New Member
    Join Date
    Oct 2014
    Posts
    13

    Re: Dynamic UDT's saving to Random Access File *Help*

    Oh my gosh, I was away yesterday and did not expect so many people to reply!

    Me and my project partner are relatively new to Visual Basic & programming in general, having only learned about file structure and such this past month. In our class we have only talked about sequential files and random access files. I don't really know much about databases and other types of files. I believe our instructor is expecting us to work with the file types that he informed us about so that we can demonstrate our ability to use them, which is why we would prefer to use the random access file method here. I realize that this means that each record must be the same size, so is my only option to declare the array sizes when we make the UDT. Example:

    Code:
    Private Type PracticeQuizResults
        intNumAttempts As Integer 'Number of attempts on quiz
        blnCorrect(1 to 10) As Boolean 'Number of correct answers on quiz
        intNumCorrect As Integer 'Number of correct answers on quiz
        intQuestionIDs(1 to 10) As Integer 'ID of questions used on quiz
    End Type
    instead of:

    Code:
    Private Type PracticeQuizResults
        intNumAttempts As Integer 'Number of attempts on quiz
        blnCorrect() As Boolean 'Number of correct answers on quiz
        intNumCorrect As Integer 'Number of correct answers on quiz
        intQuestionIDs() As Integer 'ID of questions used on quiz
    End Type
    It would be nice to be able to modify the maximum number of "questions" available here, however we can set it to this static amount if this is the only option in order to use the random access file method. It just means we have to waste a little bit of file memory.

    Thanks everyone for replying to this thread and dealing with our stupidity resulting from lack of experience. xD
    Cheers,
    Dill

  24. #24
    PowerPoster
    Join Date
    Aug 2011
    Location
    B.C., Canada
    Posts
    2,887

    Re: Dynamic UDT's saving to Random Access File *Help*

    Use Redim on the udt members that you want to resize.
    Use Redim Preserve on the udt members you want to resize while keeping the information intact (if any info in the udt members)

  25. #25

    Thread Starter
    New Member
    Join Date
    Oct 2014
    Posts
    13

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by Max187Boucher View Post
    Use Redim on the udt members that you want to resize.
    Use Redim Preserve on the udt members you want to resize while keeping the information intact (if any info in the udt members)
    Like I said in the original post, we tried this but it just resulted in errors.

  26. #26
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by DillPickleSwimmer View Post
    I believe our instructor is expecting us to work with the file types that he informed us about so that we can demonstrate our ability to use them, which is why we would prefer to use the random access file method here. I realize that this means that each record must be the same size, so is my only option to declare the array sizes when we make the UDT. Example:

    Code:
    Private Type PracticeQuizResults
        intNumAttempts As Integer 'Number of attempts on quiz
        blnCorrect(1 to 10) As Boolean 'Number of correct answers on quiz
        intNumCorrect As Integer 'Number of correct answers on quiz
        intQuestionIDs(1 to 10) As Integer 'ID of questions used on quiz
    End Type
    ...

    It would be nice to be able to modify the maximum number of "questions" available here...
    Then just introduce a Constant (the VB-Compiler is able to resolve those - as well as simple expressions -
    also for the Upper-Bounds of static VB-Array-Definitions).

    Small example:
    Code:
    Option Explicit
    
    Const MaxQuestions As Long = 10
    
    Private Type PracticeQuizResults
        intNumAttempts As Integer 'Number of attempts on quiz
        blnCorrect(1 To MaxQuestions) As Boolean 'Number of correct answers on quiz
        intNumCorrect As Integer 'Number of correct answers on quiz
        intQuestionIDs(1 To MaxQuestions) As Integer 'ID of questions used on quiz
    End Type
    
    Private Sub Form_Load()
    Dim PQR As PracticeQuizResults
      Debug.Print UBound(PQR.intQuestionIDs)
    End Sub
    Olaf

  27. #27
    PowerPoster
    Join Date
    Aug 2011
    Location
    B.C., Canada
    Posts
    2,887

    Re: Dynamic UDT's saving to Random Access File *Help*

    I'm no help for using open-random, i have never used it.

    Your length is 650 (i know that) here is how to got to it... I know I am missing 46bytes in my calculations, but don't know where.

    Code:
    For intI = 1 To 10
    lngRecLength = lngRecLength + LenB(udtStudent.udtPracticeQuizResults(intI))
    lngRecLength = lngRecLength + LenB(udtStudent.udtPracticeQuizResults(intI).intNumAttempts)
    lngRecLength = lngRecLength + LenB(udtStudent.udtPracticeQuizResults(intI).intNumCorrect)
    For intJ = 1 To 10
    lngRecLength = lngRecLength + LenB(udtStudent.udtPracticeQuizResults(intI).blnCorrect(intJ))
    lngRecLength = lngRecLength + LenB(udtStudent.udtPracticeQuizResults(intI).intQuestionIDs(intJ))
    Next
    Next
    lngRecLength = lngRecLength + LenB(udtStudent)
    MsgBox lngRecLength + 46
    Try changing your len = 650 in your open state, for example....
    open filename for random as #1 len = 650

    Udt members are pointers to the data.. so using lenb will only give you the pointer size which is usually 2 or 4 in your udt example.
    Last edited by Max187Boucher; Nov 2nd, 2014 at 07:16 PM.

  28. #28
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by Elroy View Post
    Also, in the strictest of terms, I am clear (as I'm sure everyone is), that a string Let is always a Unicode Let...
    Nope. It isn't.

    VB String variables are BSTRs, and they can hold pretty much any run of bytes at all.

    It is perfectly possible for a VB String to contain Unicode (i.e. UTF-16LE, which is a typical VB6 String value), or ANSI from any codepage, or ASCII, or UTF-8, etc. When we use an assignment (Let) statement to assign to a String the right hand side expression can be anything that can be coerced to a String value.

    When dealing with byte-oriented String expressions (i.e. ASCII, ANSI, etc.) we have the handy "B" functions.

    Code:
        Dim S1 As String
        Dim S2 As String
        Dim S3 As String
        Dim Pos As Long
    
        S1 = StrConv("Hello World....", vbFromUnicode)
        S2 = S1
        S3 = StrConv("VBForums!", vbFromUnicode)
        Pos = InStrB(S1, ChrB$(AscB(" ")))
        MidB$(S2, Pos + 1, LenB(S3)) = S3
        MsgBox StrConv(S2, vbUnicode)

  29. #29
    PowerPoster
    Join Date
    Feb 2006
    Posts
    24,482

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by DillPickleSwimmer View Post
    In our class we have only talked about sequential files and random access files. I don't really know much about databases and other types of files. I believe our instructor is expecting us to work with the file types that he informed us about so that we can demonstrate our ability to use them, which is why we would prefer to use the random access file method here. I realize that this means that each record must be the same size, so is my only option to declare the array sizes when we make the UDT.
    Actually you just need to provide a Len value in your Open statement that is as long as the space required for the longest UDT you plan to use.

    See Put Statement and Get Statement for information useful in calculating the required record length value.

    Using fixed-length String and array fields makes this much easier to determine.

  30. #30
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by Elroy View Post
    Also, in the strictest of terms, I am clear (as I'm sure everyone is), that a string Let is always a Unicode Let...
    Nope. It isn't.
    dilettante, really? (*said with nodding head in amazement*)

    That's about like saying that a Single isn't an IEEE-754 4 byte float, and that when we do an LSET on two of those that we could be shifting bits around that represent (in your words)...

    ...ANSI from any codepage, or ASCII, or UTF-8, etc.
    With your logic, we should just throw out type casting all together. Natively, VB6 strings are interpreted as Unicode (aka, UTF-16LE). When we read an ASCII (or codepaged ANSI) file, they are coverted to Unicode when read by VB6; when we make a non...W API call, they are converted FROM Unicode into ANSI; when we use them to set captions in a non-Unicode way, strings are expected to be Unicode and then translated to the necessary format.

    Said a bit differently, if you stuff the bits of UTF-8 (or true ASCII/ANSI) or anything other than UTF-16LE into a string and then try and use it for normal operations, the results will be completely unpredictable.

    To restate my original claim, the following is a Unicode LET:
    Code:
    Dim s1 as String
    Dim s2 as String
    Let s1 = "asdf"
    Let s2 = s1
    To say that those aren't Unicode strings with the LET statement putting Unicode into them is nonsense. (I'll grant that the string literal is stored as ANSI in the .BAS or .FRM file, but when it's compiled, it'll be a Unicode literal.)

    To say different is analogous to saying that a dog isn't a dog because it eats grains and cow entrails in its food. Let's just call things what they are, with the understanding that we can always make a philosophical argument that they're possibly made of other things, but let's not just be argumentative for the sake of being argumentative.

    Well, I'm just checking email so won't stay long, but I hope everyone stays well.

    Take Care,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  31. #31
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by Elroy View Post
    Natively, VB6 strings are interpreted as Unicode (aka, UTF-16LE).
    Nope.

    "Native" (for me) is anything the Runtime offers and allows (or even encourages,
    by offering a quite large Set of dedicated Functions for VB-Strings in "8Bit-Mode").

    Did you even try out the nice example Dilettante already gave in post #28?
    . S1 = StrConv("Hello World....", vbFromUnicode)
    . S2 = S1
    Hint: Check LenB on those two strings, to better understand what was happening there.

    Both assignemnts above are valid "Lets" - but neither of those Lets knows anything about
    Unicode - it's all about determining the ByteLen of the Source (on the right-hand-side) -
    followed by an allocation for the (left-hand-side) Target-StringContainer in the appropriate size...,
    followed by a copy-over of the Source-data into it.

    Quote Originally Posted by Elroy View Post
    When we read an ASCII (or codepaged ANSI) file, they are coverted to Unicode when read by VB6;
    when we make a non...W API call, they are converted FROM Unicode into ANSI;
    That's only two of the about two dozen things which are useful to know about VB-Strings -
    and 8Bit-Mode contributing its own entire chapter there.

    Quote Originally Posted by Elroy View Post
    Said a bit differently, if you stuff the bits of UTF-8 (or true ASCII/ANSI) or anything other than
    UTF-16LE into a string and then try and use it for normal operations, the results will be completely unpredictable.
    Same thing, when you pass VBStrings with WChar-content into the 8Bit-String-Function-Set.
    The results will not make sense.

    Quote Originally Posted by Elroy View Post
    To restate my original claim, the following is a Unicode LET:
    Aside from, that you originally claimed that "String-LETs" are *always* Unicode-Lets -
    an assignment is just an assignment - a copying of sourcedata into a destination-buffer.

    Theoretical example:

    S8 = S9

    Both Variables above are of type VB.String - you can't tell me, if I copied Bytes(8Bit-Chars) or WChars, can you?

    Olaf
    Last edited by Schmidt; Nov 3rd, 2014 at 01:29 PM.

  32. #32
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    9,936

    Re: Dynamic UDT's saving to Random Access File *Help*

    Hmmm, I should probably let this go because I believe that all of us have a pretty good understanding about how things work, and we seem to be debating for the pure sake of debate rather than actually working anything out. However...

    So when I do a LET on two Singles, such as....

    Dim n1 as Single
    Dim n2 as Single
    Let n2 = n1

    ... I shouldn't be allowed to say that that's an IEEE-754 4 byte float LET statement?

    Because, I certainly know how to use the bits in a Single for things other than IEEE-754 floats, and I actually have in certain situations. However, I still think of that as a Single Precision Float LET statement.

    But hey ho, I'm on a job and am going to unsubscribe from this thread. Arguing about semantics as silly as this isn't terribly entertaining. Y'all take care.
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  33. #33
    PowerPoster
    Join Date
    Jun 2013
    Posts
    7,253

    Re: Dynamic UDT's saving to Random Access File *Help*

    Quote Originally Posted by Elroy View Post
    Hmmm, I should probably let this go because I believe that all of us have a pretty good understanding about how things work, and we seem to be debating for the pure sake of debate rather than actually working anything out. However...

    So when I do a LET on two Singles, such as....

    Dim n1 as Single
    Dim n2 as Single
    Let n2 = n1

    ... I shouldn't be allowed to say that that's an IEEE-754 4 byte float LET statement?

    Because, I certainly know how to use the bits in a Single for things other than IEEE-754 floats, and I actually have in certain situations. However, I still think of that as a Single Precision Float LET statement.
    Aside from, that implementation-details behind a given TypeSpecifier may change in a language (e.g. VB6-Integer vs. .NET Integer),
    the VB-String-Type is intended of being of "dual nature" (otherwise the second set of "B-suffixed String-Functions" won't exist in the runtime).

    Other Basics (as e.g. PowerBasic or FreeBasic) solve that by defining dedicated TypeSpecifiers for 8Bit-Strings (as e.g. ZString).
    Or like OxygenBasic, which offers the currently largest fine-control in that regard with a whopping 6 different StringTypes:
    http://www.oxygenbasic.org/forum/index.php?topic=322.0

    In VB6 we only have that one (universal) String-Type (and accompanied by ByteArrays, we can solve all our problems quite nicely).
    But statements like:
    "An assignment of a VB-String is always 16Bit-Unicode"
    ...is wrong - and just misleading others who read such a thing

    Why not trying for a little bit more precision in language - and accepting valid
    corrections here in that public knowledge-pool with a "kind of grace".

    Olaf

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width