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
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
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
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
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
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 ;-)
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
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. :-)
I see you've already told us this in your subject line. :-)
ASKER
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
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
ASKER
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
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
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
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
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.
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
>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
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 ----->
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"
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 ----->
ASKER
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
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.
ASKER
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
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
>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
recno = Len(Open File #)/length of each record
redim yourarray(recno)