Link to home
Start Free TrialLog in
Avatar of RUSS_EMI
RUSS_EMI

asked on

How do I create a dynamic array in VB6

I have an ASCII flat file, which may grow or shrink.  I would like to read each line of data into an array.  What is the most efficient way to get the number of lines (records) in a file and then Dim an array?  This array is used in several different procedures throughout the form.

I have already Opened the file, read in each line and got a count that way, but it is slow.  I've set an upper limit to the file size, but that is risky.

Thanks,

Russ
Avatar of hes
hes
Flag of United States of America image

Is each record a fixed length, if so try using
recno = Len(Open File #)/length of each record
redim yourarray(recno)
Avatar of RUSS_EMI
RUSS_EMI

ASKER

Each record isn't fixed in length.
A sample record is as follows;

filename, start_postion, end_postion, repeat

where filename = string
others = long

This is used to play audio files at specific locations within a text file.

Russ
open "FileName" for append as 13:close 13
open "FileName" for inputas 13

type MyType
    filename
    start_postion
    end_postion
    repeat
end type
Dim Myarray() as MyType
' 13 is the file no
do until eof(#13)
    input #13,Myarray(N).filename, _
        Myarray(N).start_postion, _
        Myarray(N).end_postion, Myarray(N).repeat
     N=N+1
    redim preserve Myarray(N) as MyType
loop
close#13
Why don't you create REAL dynamic array:

Dim a() As String  'or whatever you need
Redim a(0)  'init value

Dim line_count As Long
line_count = 0

'your file reading
While ...
   Line Input #1, a(line_count)  'or whatever you use
   line_count = line_count +1
   Redim Preserve a(line_count)
Wend

instead of line_count you could use UBound(a), but rather store value it returns to some variable instead of calling it many times
Set a good upper limit and if it is about to be exceeded than use the Preserve keyword to ReDim to a larger size.
Bahnass, you forgot to set initial value for dynamic array with Redim (can't use var until it has at least 1 element)
3 on same minute ??
bye 4 now ;-)
Russ:

   1) How big are the files?

   2) Which version of VB are you using?

   3) Just to verify, each line is terminated by Carriage Return and Line Feed characters?

If it isn't too big, then the following routine should work fine:


   Dim sBuff   As String
   Dim aBuff() As String
   Dim hFile   As Integer

   hFile = FreeFile() 'Get next available File Handle
   Open "somefile" For Binary Input As #hFile
   sBuff = Input(LOF(hFile),hFile) 'Read entire file
   Close #hFile
   aBuff() = Split(sBuff, vbCrLf)


aBuff() is now a dynamic array, loaded with the contents of the file.  aBuff(0) contains the first line, aBuff(1) contains the second line, etc.

If you need to know how many lines, then you can simply add one to the Upper Bound of the array:

   LineCount = UBound(aBuff) + 1



-Dennis Borg
>2) Which version of VB are you using?

I see you've already told us this in your subject line. :-)
BozzoCage,
   Thank you for your suggestion.  I get a compile error saying that the array is already dimensioned.  
The initial Dim statement is in the Declaration section.
The ReDim Preserve statement is in the Form_Load procedure.
As these arrays are referenced thoughout the Form, how do I proceed?

Russ
Dennis,
   The file (which may be from 1 to 1000 lines) consists of 4 elements / line -
              filename, start_pos, end_pos, repeat_value.

Each line does end w/ CrLf.

If I use your suggestion, how do I further parse each line, into the different array elements?

Russ
ASKER CERTIFIED SOLUTION
Avatar of BozzoCage
BozzoCage

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
BozzoCage,
   Thank you for that definitive answer.  I'll try it and post the points if all is OK, which I think it will.

Russ
BozzoCage
Thanks for Good  Documentation
Sorry I had notime wrote it on the fly n saw many EE answering

Thanks all of U
Bahnass, sorry for using almost same sample as you did... I just didn't took time to read other comments...
But anyway, it is hard to show some "other" way if there is more or less single standard way.
Russ:

>If I use your suggestion, how do I further parse each
>line, into the different array elements?

Given your description of each line, then you would go about it as follows:

(after you've read the file and created the dynamic array as I suggested above)


   Dim Elements() As String

   Elements = Split(aBuff(0),",") 'Split the first line

Element(0) now contains your FileName
Element(1) now contains your Start Pos
Element(2) now contains your End Pos
Element(3) now contains your Repeat Value


I don't know exactly how you need to process this, but if you need to go thru each line sequentially, then you can use a loop such as the following:

   Dim idxLine    As Long
   Dim uB         As Long
   Dim Elements() As String

   ub = UBound(aBuff)
   For idxLine = 0 To ub
      Elements = Split(aBuff(idxLine), ",")
      ' *** now use Elements(0) thru Elements(3) as needed
   Next 'idxLine



-Dennis Borg
BozzoCage
Nice 2 meet U
thanks 4 EE
U reserve Points if that U R Sorry 4
Here is a very fast way to persist Tables.

1. Open a Standard.Exe Project.
2. Copy/Paste the following into the Form1 code window.
3. Press F5 to run. After the program completes, press Control-G to View the Debug Immediate window.

I'll leave it up to you to figure out the rest.. I'm going home!!! <lol> and a <smile>.

<----- Code Begin ----->

Option Explicit

Private Type typMyData
   strField As String
   lngField As Long
   intField As Integer
End Type

Private Type typMyFile
   lngCount As Long
   udtData() As typMyData
End Type

Dim m_udtFileGet As typMyFile
Dim m_udtFilePut As typMyFile

Private Sub Form_Load()

'  Build Table and Write
With m_udtFilePut
   ReDim .udtData(10)
   Dim lngIndex As Long
   For lngIndex = LBound(.udtData) To UBound(.udtData)
      With .udtData(lngIndex)
         .strField = String$(lngIndex, "x")
         .lngField = lngIndex
         .intField = lngIndex * 2
      End With
   Next lngIndex
   .lngCount = UBound(.udtData) + 1
End With

'  Write Data
   Dim strFile As String: strFile = "c:\tempwork\TestFile.Dat" ' <-- CHANGE
   Dim lngFile As Long: lngFile = FreeFile
   If Dir(strFile) <> "" Then
      Kill strFile
   End If
   Open strFile For Binary As lngFile
   Put lngFile, , m_udtFilePut
   Close lngFile

'  Read Data
   Open strFile For Binary As lngFile
   Get lngFile, , m_udtFileGet
   Close lngFile
   
'  Display Data In The Immediate Window
With m_udtFileGet
   For lngIndex = LBound(.udtData) To UBound(.udtData)
      With .udtData(lngIndex)
         Debug.Print .strField & " " _
            & .lngField & " " _
            & .intField
      End With
   Next lngIndex
End With

   Unload Me

End Sub

<----- Code End ----->


I'm overwhelmed at the various ways to skin this cat.
Still processing the comments to find the best solution.

BozzoCage's suggestion doesn't work, due to the fact I'm using a multi-dimensional array.

I don't fully understand wsh2's suggestion, but give me time.

Am working on Dennis's solution.  Will let you know.

Here is some sample code, does this help understand?

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


Dim X As Integer
Dim sound_number As Integer
Dim picture_number As Integer
Dim mypath
Dim CdKey As String
Dim CdPath As String
Dim BookmarkLocation As Long
Dim BookmarkString As String
Dim cr As CharRange
Dim pict(9) As String
Dim pictloc(9,3) As Long
Dim aud(9) As String
Dim audloc(9,2) As Long
Dim playing(9) As Boolean


Private Sub Form_Load()
If Dir(mypath + "text\sounds.txt") > "" Then
Open mypath + "text\sounds.txt" For Input As #1

X = 0

Do While Not EOF(1) ' Loop until end of file.
            ' sound file, min,        max,          repeat times
   Input #1, aud$(X), audloc(X, 0), audloc(X, 1), audloc(X, 2)
   MP2(X).PlayCount = audloc(X, 2)
   X = X + 1

Loop
sound_number = X - 1

Close #1    ' Close file.

Else
EnableAudio.Visible = False
EnableAudio.Value = 0
End If


If Dir(mypath + "text\pictures.txt") > "" Then

Open mypath + "text\pictures.txt" For Input As #1

X = 0

Do While Not EOF(1) ' Loop until end of file.
            ' picture file, min,        max,            left,           top
   Input #1, pict$(X), pictloc(X, 0), pictloc(X, 1), pictloc(X, 2), pictloc(X, 3)
   Picture1(X).Left = pictloc(X, 2)
   Picture1(X).Top = pictloc(X, 3)
   Set Picture1(X).Picture = LoadPicture(pict$(X))
   X = X + 1

Loop
picture_number = X - 1
Close #1    ' Close file.

Else
EnablePictures.Visible = False
EnablePictures.Value = 0
End If

BookmarkLocation = rtfTest.Find(" ", BookmarkLocation)

Timer1.Enabled = True
End Sub

Private Sub Timer1_Timer()
' get minimum & maximum screen characters within RTF window
cr = GetCharrange(rtfTest)

If (EnableAudio.Value > 0 Or EnablePictures.Value > 0) Then


 If EnableAudio.Value = 1 Then
 
 For X = 0 To sound_number
 If cr.cpMax <= audloc(X, 1) And cr.cpMax >= audloc(X, 0) Then
 If Not playing(X) Then MP2(X).Open (aud$(X))
 playing(X) = True
 Else
 playing(X) = False
 MP2(X).Stop
 End If
 Next
 
 End If
 
 
 
 
 If EnablePictures.Value = 1 Then
 
 For X = 0 To picture_number
 If cr.cpMax <= pictloc(X, 1) And cr.cpMax >= pictloc(X, 0) Then
 Picture1(X).Visible = True
 Else
 Picture1(X).Visible = False
 End If
 Next
 
 End If
 
 
 
End If
 End Sub
************************************************

To all THANKS!

Russ



You didn't mentioned that you use multi-dimensional array. Well, with ReDim you can resize last dimension only.
It is hard to award the points to only 1 response and be fair.  Please understand I got a little more from each answer.  In the program I ended up using all single dimensional arrays.  All seems to work fine.
Again, thank you all for responding.

Russ
>It is hard to award the points to only 1 response and be
>fair.  Please understand I got a little more from each
>answer.

You did just fine, Russ. Glad to see you arrived at a working solution! That's the important thing.


-Dennis Borg