Hey guys, noob here.. I'm learning to work with arrays but I have a problem with my code somewhere...
My goal is to:
- load a text file
- grab the first 15 characters of each line and store to strIP each time
- see if the new value of strIP matches a value already in the array (arrIPs)
- if it doesn't, then add it..
- if it does, then add 1 to the count for this instance
That last one is my problem. I keep getting inaccurate numbers.
I.E. when something shows up in the text file about 34 times.. it is only showing a count of 2 or 1. I'm not sure what i've done wrong. Could ne1 help?
Everything works according to plan except for the counting.
As you can see, once the file is done loading, I display the count in another text box.... an inaccurate count.. grrrr
VB Code:
Open cd1.FileName For Input As #1
Do Until EOF(1)
Line Input #1, strNewLine
' get the ip string from the start of the log
strIP = (Mid(strNewLine, 1, txtCharsToCopy))
'loop through the array to see if the ip is in it
Found = False
For i = 0 To numIPs
If strIP = arrIPs(i) Then
Found = True
arrIPcount(i) = (arrIPcount(i) + 1)
Exit For
End If
Next i
If Found = False Then
arrIPs(numIPs) = strIP
numIPs = numIPs + 1
ReDim Preserve arrIPs(numIPs)
ReDim Preserve arrIPcount(numIPs)
txtSimple = txtSimple & strIP & vbCrLf
End If
'========================
Loop
Close #1
For i = 1 To UBound(arrIPcount)
'compensate for 0 starting count
txtIPCount = txtIPCount & arrIPcount(i) & vbCrLf
Next i
-----------------------------------------------
I am incapable of advanced reasoning.
-----------------------------------------------
Open cd1.FileName For Input As #1
Do Until EOF(1)
Line Input #1, strNewLine
' Get the ip String from the start of the log
strIP = (Mid(strNewLine, 1, txtCharsToCopy))
'loop through the array To see If the ip is In it
Found = False
For i = 0 To ubound(arrIPs)
If strIP = arrIPs(i) Then
Found = True
arrIPcount(i) = (arrIPcount(i) + 1)
Exit For
End If
Next i
If Found = False Then
ReDim Preserve arrIPs(i)
ReDim Preserve arrIPcount(i)
arrIPs(I) = strIP
arrIPcount(i)=1
txtSimple = txtSimple & strIP & vbCrLf
End If
'========================
Loop
Close #1
For i = 1 To UBound(arrIPs)
'compensate For 0 starting count
txtIPCount = txtIPCount & arrIs(i) & ": " & arrIPcount(i) & vbCrLf
Next i
This should work a little better. I didn't test it, though. Post back if there are any problems. You were close.
Dim lngFreeFile As Long
On Error Goto ErrHandler
lngFreeFile = FreeFile
Open cd1.FileName For Input As #lngFreeFile
Close #lngFreeFile
Exit Sub
ErrHandler:
Close #lngFreeFile
That will stop the file failing to open next time you run your code after an error.
hmmm... i don't know how you guys do it... lol... my brain ties itself into knots when i try to learn visual basic.. i can't even imagine C or Perl or something.. lol
it looks like that code works great! Thanks a gabazabillion!
i'll have to try that filename thing.. hmm.. i never had any issues opening the file back up, but i'm sure it wouldn't hurt to throw that in there
P.S. Just out of curiosity. I'm writing this program for analysing an apache log file just for fun but.. do you guys know of a free Analys(z)er for Apache?
Cheers
-----------------------------------------------
I am incapable of advanced reasoning.
-----------------------------------------------
I wouldn't declare the array before hand.
I would leave it empty until I needed it, and I certainly wouldn't have a spare place holder for a future item. I would use:
Code:
Option Explicit
Private Declare Function SafeArrayGetDim Lib "oleaut32" (ByRef saArray() As Any) As Long
Private Sub Form_Load()
Dim arrStrings() As String
CheckArray
ReDim arrStrings(0)
CheckArray
Erase arrStrings
CheckArray
End Sub
Private Sub CheckArray()
If SafeArrayGetDim(arrStrings) = 0 Then
MsgBox "Array Empty"
Else
MsgBox "Array NOT Empty"
End If
End Sub
I like to resize the array right before I write to it, as opposed to when it may not even be needed. Sometimes causes a problem if you want to use the 0 (or first) array option, but you can set the index to -1 or some other tricks to handle it.
Yeah. I see what you're saying now (and Woka too) and I agree with both of you. I originally did it this way (in a previous post by iqchicken) so I wouldn't have to rearrange his code too much.
That's what you get for being lazy
Pete
No trees were harmed in the making of this post, however a large number of electrons were greatly inconvenienced.
Have to put it above the first subroutine, in General Declarations.
Code:
Option Explicit
Dim arrStrings() As String
Private Declare Function SafeArrayGetDim Lib "oleaut32" (ByRef saArray() As Any) As Long
Private Sub Form_Load()
CheckArray
ReDim arrStrings(0)
CheckArray
Erase arrStrings
CheckArray
End Sub
Private Sub CheckArray()
If SafeArrayGetDim(arrStrings) = 0 Then
MsgBox "Array Empty"
Else
MsgBox "Array Not Empty"
End If
End Sub
I have no trouble knowing if the array is empty, but I always dim(0) with zero items, and then have a problem detecting if its occupied or not. I guess I could not redim it as anything until I need it.
Option Explicit
Private Declare Function SafeArrayGetDim Lib "oleaut32" (ByRef saArray() As Any) As Long
Private Type mtypIPs
IP As String
Count As Long
End Type
Private mudtData() As mtypIPs
Private Sub Command1_Click()
On Error GoTo ErrHandler
StartExample
Exit Sub
ErrHandler:
MsgBox Err.Number & " - " & Err.Description, vbCritical, "Error"
End Sub
Private Sub StartExample()
Dim lngIndex As Long
Dim strEntry As String
On Error GoTo ErrHandler
List1.Clear
GetData (App.Path & "\Data.txt")
If SafeArrayGetDim(mudtData) = 0 Then
MsgBox "No data found"
Else
For lngIndex = 0 To UBound(mudtData)
strEntry = mudtData(lngIndex).IP & " - " & mudtData(lngIndex).Count
List1.AddItem strEntry
Next lngIndex
End If
Exit Sub
ErrHandler:
Err.Raise Err.Number
End Sub
Private Sub GetData(ByVal pstrFilename As String)
Dim blnInit As Boolean
Dim strLine As String
Dim strIP As String
Dim blnFound As Boolean
Dim lngFreeFile As Long
Dim lngIndex As Long
On Error GoTo ErrHandler
Erase mudtData
lngFreeFile = FreeFile
Open pstrFilename For Input As #lngFreeFile
Do Until EOF(lngFreeFile)
Line Input #lngFreeFile, strLine
strIP = Mid$(strLine, 1, 15)
blnFound = False
If blnInit Then
For lngIndex = 0 To UBound(mudtData)
If strIP = mudtData(lngIndex).IP Then
blnFound = True
mudtData(lngIndex).Count = mudtData(lngIndex).Count + 1
Exit For
End If
Next lngIndex
End If
If Not blnFound Then
If Not blnInit Then
lngIndex = 0
blnInit = True
Else
lngIndex = UBound(mudtData) + 1
End If
ReDim Preserve mudtData(lngIndex) As mtypIPs
mudtData(lngIndex).IP = strIP
mudtData(lngIndex).Count = 1
End If
Loop
Close #lngFreeFile
Exit Sub
ErrHandler:
Close #lngFreeFile
Err.Raise Err.Number
End Sub
It seems to work.
Attached is the project I ran, with my test file with random data in.