I've read through some of the previous questions on speed up processing of large CSV data. I've implement some of the ideas and i got some improvement on processing time. However i still need to further cut down the processing time hopefully someone can help me.
I think my code is too long, I'll try to simplify. Here is what my code suppose to do:
1. Read through a csv file.
2. Group the data by first column; calculate total sum of each column and return the result.Example (Raw Data): A B C1 2 31 2 32 4 42 4 4Result:A B C1 4 62 8 8Note: My actual data will be 100MB file with 630 columns and 29000 rows, total 18.27M records.
Here is how i achieve it:Method 1:
1. Read a csv file through Filestream.
2. Use Split to split the returned string and process line by line, field by field.
3. Storing the result in an array and save the result in a text file.
Note on Method1: Time to process the data using this method takes ~1 min 20 secs.Method 2:1. Read a csv file through Filestream.2. Feed the data into different threads before start process. (For now i feed 100 lines of data into different thread, fix 5 threads for now due to CPU resource constraint)3. Use Split to split the returned string and process line by line, field by field in each thread.4. Join all result from every threads and store in an array. Save the result in text file.Note on Method 2: Time to process the data using this method takes ~50 secs.So i got ~30secs improvement migrating from Method 1 to Method 2. I was wondering whether what i can do to further improve the process time. I've tried to cut down the data into smaller section like 100 lines x 100 columns and process it but the time to process the data become longer instead.Hopefully some one can help me on this.Thank you in advance.Edit:Here is my code for Method 2 (I'll skip Method 1 as i'm not using it already), I have a subroutine that manage the assignment of threads for every 100 lines read from filestream, execute each threads and return the result, finally update the all the results into single array before write the result into file. I tried to make the code as simple as possible. Hopefully this will give more idea to you all on how i process my data.'Subroutine that assign smaller section of raw data into different threadsSub process_control(byval filename as string) Dim sread As New FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read) Dim read As New StreamReader(sread) Dim t1 As System.Threading.Thread Dim value, data1(), data2(), data3(), data4(), data5(), threadid(), result1(0), result2(0), result3(0), result4(0), result5(0) As String Dim row as integer Dim rowlimit as integer = 99 Dim check1 as boolean = true row = 0 check = false ReDim data1(rowlimit), data2(rowlimit), data3(rowlimit), data4(rowlimit), data5(rowlimit), threadid(4) do
value = read.ReadLine
If row < rowlimit + 1 then
If data1(rowlimit) = "" Then
data1(row) = value
ElseIf data2(rowlimit) = "" Then
data2(row) = value
ElseIf data3(rowlimit) = "" Then
data3(row) = value
ElseIf data4(rowlimit) = "" Then
data4(row) = value
ElseIf data5(rowlimit) = "" Then
data5(row) = value
End If
Else
If data1(rowlimit) <> "" And data2(rowlimit) = "" And data3(rowlimit) = "" And data4(rowlimit) = "" And data5(rowlimit) = "" Then
threadid(0) = ""
t1 = New Threading.Thread(Sub()
result1 = process(data1).Clone
threadid(0) = System.Threading.Thread.CurrentThread.ManagedThreadId
End Sub)
t1.Start()
row = 0
data2(row) = value
ElseIf data1(rowlimit) <> "" And data2(rowlimit) <> "" And data3(rowlimit) = "" And data4(rowlimit) = "" And data5(rowlimit) = "" Then
threadid(1) = ""
t1 = New Threading.Thread(Sub()
result2 = process(data2).Clone
threadid(1) = System.Threading.Thread.CurrentThread.ManagedThreadId
End Sub)
t1.Start()
row = 0
data3(row) = value
ElseIf data1(rowlimit) <> "" And data2(rowlimit) <> "" And data3(rowlimit) <> "" And data4(rowlimit) = "" And data5(rowlimit) = "" Then
threadid(2) = ""
t1 = New Threading.Thread(Sub()
result3 = process(data3).Clone
threadid(2) = System.Threading.Thread.CurrentThread.ManagedThreadId
End Sub)
t1.Start()
row = 0
data4(row) = value
ElseIf data1(rowlimit) <> "" And data2(rowlimit) <> "" And data3(rowlimit) <> "" And data4(rowlimit) <> "" And data5(rowlimit) = "" Then
threadid(3) = ""
t1 = New Threading.Thread(Sub()
result4 = process(data4).Clone
threadid(3) = System.Threading.Thread.CurrentThread.ManagedThreadId
End Sub)
t1.Start()
row = 0
data5(row) = value
ElseIf data1(rowlimit) <> "" And data2(rowlimit) <> "" And data3(rowlimit) <> "" And data4(rowlimit) <> "" And data5(rowlimit) <> "" Then
threadid(4) = ""
t1 = New Threading.Thread(Sub()
result5 = process(data5).Clone
threadid(4) = System.Threading.Thread.CurrentThread.ManagedThreadId
End Sub)
t1.Start()
row = 0
check1 = True
End If
row += 1
End If If check1 = True Then
Do
System.Threading.Thread.Sleep(100)
Loop Until threadid(0) <> "" And threadid(1) <> "" And threadid(2) <> "" And threadid(3) <> "" And threadid(4) <> ""
row = 0
ReDim data1(rowlimit)
data1(row) = value
row += 1
result1_update(result1) ' consolidate result into a single array
result2_update(result2) ' consolidate result into a single array
result3_update(result3) ' consolidate result into a single array
result4_update(result4) ' consolidate result into a single array
result5_update(result5) ' consolidate result into a single array
check1 = False
ReDim data2(rowlimit), data3(rowlimit), data4(rowlimit), data5(rowlimit)
End If
loop until read.endofstreamend sub
' Function that calculate the sum of each row and columns Function process(ByVal data() As String) As String()
Dim line(), line1(), result() As String
Dim check As Boolean
redim result(0)
For n = 0 To (data.Count - 1)
if result(0) = "" and result.count = 1 then
result(result.count-1) = data(n)
else
check = true
line1 = Split(data(n), ",", -1, CompareMethod.Text)
For m = 0 to (result.count-1)
line = split(result(m),",",-1, CompareMethod.Text)
if line1(0) = line(0) then
check = false
for o = 1 to (line1.count-1)
line(o) = val(line1(o)) + val(line(o))
next o
result(m) = join(line,",")
exit for
end if
Next m
if check = true then
redim preserve result(result.count)
result(result.count-1) = join(line1,",")
end if
end if
Next n
redim preserve result(result.count-2)
process = result.clone
End Function
Looking at your code I noticed a couple of things:
you're using Val which is very easy to use but has a high overhead. Integer.Parse would work much more efficiently.
You're converting from string to number back to string way more than you should have to. Since your summary will only be a fraction of the size of your complete data, you shouldn't have any trouble storing the results in memory. A Dictionary(Of Integer, Integer()) would work well for this.
Consider this code which will read the data, summarize it and put the data in a format easy to write to a file all in less than 10 secs. using random integers up to 1000:
Function SummarizeData(filename As String, delimiter As Char) As Dictionary(Of Integer, Integer())
Dim limit As Integer = 0
SummarizeData = New Dictionary(Of Integer, Integer())
Using sr As New IO.StreamReader(filename)
'Since we don't need the first line for the summary we can read it get _
'the upper bound for the array, and discard the line.
If Not sr.EndOfStream Then
limit = sr.ReadLine.Split(delimiter).Length - 1
Else : Throw New Exception("Empty File")
End If
Do Until sr.EndOfStream
'This creates an array of integers representing the data in one line.
Dim line = sr.ReadLine.Split(" "c).Select(Function(x) Integer.Parse(x)).ToArray
'If the key is already in the dictionary we increment the values
If SummarizeData.ContainsKey(line(0)) Then
For I = 1 To limit
SummarizeData.Item(line(0))(I) += line(I)
Next
Else
'If not we create a new element using the line as the initial values
SummarizeData.Add(line(0), New Integer(limit) {})
SummarizeData.Item(line(0)) = line
End If
Loop
End Using
End Function
To use the function and write the data, this would work:
Dim results = SummarizeData("data.txt", ","c)
'If you don't need the results sorted you can gain a few fractions of a second by _
'removing the Order By clause
IO.File.WriteAllLines("results.txt", (From kvp In results
Order By kvp.Key
Select String.Join(",", kvp.Value)).ToArray)
Related
Hello I'm having quite some trouble with this task that was given to me.
I need to find a Sequence of 8 consecutive numbers in a Text file and Put that Line into a MsgBox.
So far I've only found
For Each i As Char In fileLocation
If IsNumeric(i) Then
result += i
End If
Next`
MsgBox(result)
But that won't help me I guess
Edit:
an example Line woudl look like this:
! MK 90 GRAD ALU L 10793013 144 63.00 90 1 3745 !
In this case I would need the 10793013 as an output
Edit 2:
this is the code I currently managed to create
Dim objReader As New System.IO.StreamReader(fileLocation)
Do While objReader.Peek() <> -1
concounter = 0
zeileInhalt = objReader.ReadLine()
ListBox1.Items.Add(zeileInhalt)
For Each zeichen As Char In zeileInhalt
If IsNumeric(zeichen) Then
concounter += 1
vorhanden = True
If vorhanden = False Then
ListBox1.Items.Add(zeileInhalt)
End If
ElseIf IsNumeric(zeichen) = False And concounter = 8 Then
concounter = 0
ElseIf IsNumeric(zeichen) = False And concounter < 8 Then
concounter = 0
ListBox1.Items.Remove(zeileInhalt)
ElseIf concounter > 8 Then
concounter = 0
ListBox1.Items.Remove(zeileInhalt)
vorhanden = False
End If
Next
Loop
'For i As Integer = 0 To fileLocation.Length <> -1
objReader.Close()
The counter itself appears to work however for some reason no entries end up in my listbox.
am I missing a case where the entries are getting removed?
PS: I hope you don't mind the german variable names. If you do
zeileInhalt = content of the row
zeichen = character
vorhanden = existing
Here's another approach to try out:
Dim values() As String
Using objReader As New System.IO.StreamReader(fileLocation)
Do While Not objReader.EndOfStream
values = objReader.ReadLine().Split(" ".ToCharArray(), StringSplitOptions.RemoveEmptyEntries)
For Each value As String In values
value = value.Trim()
If value.Length = 8 AndAlso value.All(Function(c) Char.IsDigit(c)) Then
ListBox1.Items.Add(value)
Exit For
End If
Next
Loop
End Using
try to introduce a counter to check the consecutivity in your if clause and reset it and result string to zero once it's not numeric!
Dim result As String = ""
Dim conCounter As Integer = 0
For Each i As Char In fileLocation
If Char.IsDigit(i) Then
conCounter = (conCounter + 1)
result = (result + i)
Else
conCounter = 0
If (result.Length < 8) Then
result = ""
End If
End If
Next
MsgBox(result)
for each word in fileLocation
Dim noExp As New Regex("([0-9]{8,11})")
Dim m As Match = noExp.Match(word)
If Not m.Success Then Throw New Exception("No sequence number found")
Dim c = m.Groups(1).Captures(0)
Msgbox(c.value)
next
how about this ?
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 4 years ago.
Improve this question
I have the following code that searches through folder directories in a DataGridView table, and puts all files of the wanted format into a list, it also gathers a list of their last modified date for later use in the application.
The code works, but it is sore on the eyes. I want to tidy up the following loops to improve efficiency - what I mean is that I have a For loop within a For loop that creates the list of filenames, then I have two separate Do Until loops that search through the list from start to finish to pick out file names that need adjustment.
I would be very interested to learn a better way of achieving the same result, as my knowledge of efficiency in coding is quite elementary. Basically, can this be done in one or two loops, as the idea of looping through the Lists twice seems inefficient?
Public Class
Private Sub btnDirectory_Click(sender As Object, e As EventArgs) Handles btnDirectory.Click
Dim FileNames As New List(Of String)
Dim FileDates As New List(Of Date)
Dim DocNo As String
Dim rowCheck As String
Dim ProjectNo As String = "1111"
Dim FileNameCheck As String
Dim str As String
Dim k As Integer = 0
Dim i As Integer
Dim j As Integer
Dim CorrectType As Boolean = False
'The first loop grabs all files of the wanted format from a datagridview table containing all directories to be checked
For Each rw In Background.Table1.Rows
rowCheck = Background.Table1(0, k).Value
If Not String.IsNullOrEmpty(rowCheck) Then
For Each file As String In My.Computer.FileSystem.GetFiles(Background.Table1(0, k).Value)
CorrectType = False
FileNameCheck = IO.Path.GetFileNameWithoutExtension(file)
If FileNameCheck.Contains(ProjectNo) AndAlso FileNameCheck.Contains("-") AndAlso Not String.IsNullOrEmpty(FileNameCheck) AndAlso FileNameCheck.Contains(" ") Then
DocNo = FileNameCheck.Substring(0, FileNameCheck.IndexOf(" "))
If FileNameCheck.Substring(0, FileNameCheck.IndexOf("-")) = ProjectNo AndAlso CountLetters(DocNo) = 3 Then
CorrectType = True
End If
End If
If CorrectType = True Then
FileNames.Add(FileNameCheck)
FileDates.Add(IO.File.GetLastWriteTime(file))
End If
Next
End If
k += 1
Next
'The next loop tidies up the file formats that contain a "-00-" in their names
j = FileNames.Count
i = 0
Do
str = FileNames(i)
If str.Contains("-00-") Then
FileNames(i) = RemoveChar(str, "-00-") ' RemoveChar is a function that replaces "-00-" with a "-"
End If
i += 1
Loop Until i = j
i = 0
j = FileNames.Count
'Finally, this loop checks that no two files have the exact same name, and gets rid of one of them if that is the case
Do
Dim st1 As String = FileNames(j - 1)
Dim st2 As String = FileNames(j - 2)
If st1 = st2 Then
FileNames.RemoveAt(j - 1)
FileDates.RemoveAt(j - 1)
End If
j -= 1
Loop Until j = 1
End Sub
End Class
The code is certainly hard on the eyes.
the For Each rw loop does not use rw. You could replace this with a loop such as:
For k = 1 to Background.Table1.Rows.Count
' Do things here
Next k
You assign rowCheck and use it once, but you missed the opportunity to reuse it in the For Each file line.
Where you have CorrectType = True you can easily place the corresponding code instead.
If FileNameCheck.Substring(0, FileNameCheck.IndexOf("-")) = ProjectNo AndAlso CountLetters(DocNo) = 3 Then
CorrectType = True
End If
End If
If CorrectType = True Then
FileNames.Add(FileNameCheck)
FileDates.Add(IO.File.GetLastWriteTime(file))
End If
becomes:
If FileNameCheck.Substring(0, FileNameCheck.IndexOf("-")) = ProjectNo AndAlso CountLetters(DocNo) = 3 Then
FileNames.Add(FileNameCheck)
FileDates.Add(IO.File.GetLastWriteTime(file))
End If
I must admit, the next two loops made my eyes bleed (figuratively, not literally).
j = FileNames.Count
i = 0
Do
str = FileNames(i)
If str.Contains("-00-") Then
FileNames(i) = RemoveChar(str, "-00-") ' RemoveChar is a function that replaces "-00-" with a "-"
End If
i += 1
Loop Until i = j
becomes
for i = 1 to FileNames.Count
str = FileNames(i)
If str.Contains("-00-") Then
FileNames(i) = RemoveChar(str, "-00-") ' RemoveChar is a function that replaces "-00-" with a "-"
End If
Next I
And
i = 0
j = FileNames.Count
'Finally, this loop checks that no two files have the exact same name, and gets rid of one of them if that is the case
Do
Dim st1 As String = FileNames(j - 1)
Dim st2 As String = FileNames(j - 2)
If st1 = st2 Then
FileNames.RemoveAt(j - 1)
FileDates.RemoveAt(j - 1)
End If
j -= 1
Loop Until j = 1
becomes
'Finally, this loop checks that no two files have the exact same name, and gets rid of one of them if that is the case
For j = FileNames.Count - 1 to 1 Step -1 ' Check my counting here - stop at 1, 2 or 0?
Dim st1 As String = FileNames(j)
Dim st2 As String = FileNames(j - 1)
If st1 = st2 Then
FileNames.RemoveAt(j)
FileDates.RemoveAt(j)
End If
Next j
All,
I have an Excel spreadsheet which gathers files from various locations which have version numbers at the end of their name.
eg
Filea_v1.1.xlsm
Filea_v1.1.1.xlsm
Filea_v9.1.xlsm
Filea_v11.1.1.xlsm
I have already stripped the details of the file and left with the version number, but I'm finding it hard to code to get the latest version. When using a simple
If LatestVersion > LatestVersion_Last
' 11.1.1 > 9.1
I get a FALSE output as it thinks the 9.1 is greater than 11.1.1 (as its held in a string). I can't convert to a number that I'm aware of as it contains more than one decimal place.
Does anyone have any suggestions?
Thanks
This function returns 1 if the version of the first input string is bigger, -1 if the second one is bigger and 0 if both are equal:
Function Compare(a As String, b As String) As Integer
Dim n As Integer
Dim aarr() As String
Dim barr() As String
Dim av As Integer
Dim bv As Integer
aarr = Split(a, ".")
barr = Split(b, ".")
n = LBound(aarr)
Do
av = -1
If UBound(aarr) > i - 1 Then av = CInt(aarr(i))
bv = -1
If UBound(barr) > i - 1 Then bv = CInt(barr(i))
If av = -1 And bv = -1 Then
Compare = 0
Exit Function
End If
If av > bv Then
Compare = 1
Exit Function
End If
If av < bv Then
Compare = -1
Exit Function
End If
i = i + 1
Loop
End Function
Public Fucntion CompareVersion( strVersion1 as String, strVersion2 as String)
strVersion1 = "Filea_v11.1.1.xlsm"
strVersion2 = "Filea_v9.1.xlsm"
strVersion1 = Replace(strVersion1, "Filea_v", "") 'remove prefix
strVersion1 = Replace(strVersion1, ".xlsm", "") ' remove suffix
strVersion1 = Replace(strVersion1, ".", "") 'remove dots
strVersion2 = Replace(strVersion1, "Filea_v", "") 'remove prefix
strVersion2 = Replace(strVersion1, ".xlsm", "") ' remove suffix
strVersion2 = Replace(strVersion1, ".", "") 'remove dots
Dim strVersionArray1 as String()
Dim strVersionArray2 as String()
strVersionArray1 = Split(strVersion1,".")
strVersionArray2 = Split(strVersion2,".")
Dim i as Integer
For i=LBound(strVersionArray1) To UBound(strVersionArray2)
If (Cint(strVersionArray1(i))>Cint(strVersionArray2(i))) Then
'strVerion1 is greater than strVersion2
GoTo EXIT_FUNC:
Else If (Cint(strVersionArray1(i))<Cint(strVersionArray2(i))) Then
'strVerion is greater than strVersion2
GoTo EXIT_FUNC:
Else If (Cint(strVersionArray1(i))=Cint(strVersionArray2(i))) Then
'we need to examine the next segment of the array
End if
Next i
EXIT_FUNC:
End Function
I think you could try something like this:
Function FctLatest(ByVal LatestVersion As String, ByVal LatestVersion_Last As String) As Boolean
Dim comparedNew, comparedOld As String
'Loop to remove the versions one by one
Do
'For the new version
comparedNew = CutString(comparedNew, LatestVersion)
'For the previous version
comparedOld = CutString(comparedOld, LatestVersion_Last)
'we eliminate the case of equal versions
If CInt(comparedNew) > CInt(comparedOld) Then
FctLatest = True
GoTo endFunction
ElseIf CInt(comparedNew) < CInt(comparedOld) Then
FctLatest = False
GoTo endFunction
End If
Loop While InStr(LatestVersion_Last, ".") <> 0 Or InStr(LatestVersion, ".") <> 0
'For the new version
comparedNew = CutString(comparedNew, LatestVersion)
'For the previous version
comparedOld = CutString(comparedOld, LatestVersion_Last)
'we eliminate the case of equal versions, and choose the first one input
If CInt(comparedNew) > CInt(comparedOld) Then
FctLatest = True
ElseIf CInt(comparedNew) < CInt(comparedOld) Then
FctLatest = False
End If
endFunction:
End Function
Private Function CutString(ByVal ReturnedString, ByRef InputString As String) As String
'For latest version
If InStr(InputString, ".") = 0 Then
ReturnedString = InputString
Else
ReturnedString = Left(InputString, InStr(InputString, ".") - 1) 'Adding the first part of the version
InputString = Right(InputString, Len(InputString) - InStr(InputString, ".")) 'Removing the first part of the version
End If
CutString = ReturnedString
End Function
It returns a boolean comparing the versions you're interested in.
Regards,
Pierre.
Edit: just added cases, as it wasn't functional in the first place.
All of the number 6's in column 6 (Item(5)) should be deleted, and the rest of the numbers should be increased by 1. However, when the process is completed, I check the file and the file is unchanged.
Dim liness As New List(Of String)(File.ReadAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv"))
For Each line As String In liness
Dim item() As String = line.Split(","c)
Do
If item(5) = 6 Then
liness.Remove(line)
Else : Exit Do
End If
Exit Do
Loop
Console.WriteLine("Have you already entered the next school years, year 3's? (y/n)")
Dim year3s As String = Console.ReadLine
If year3s = "Y" Or year3s = "y" Then
For i As Integer = 1 To liness.Count - 1 'this will read to the end of the array list once
If item(5) > 3 And item(5) < 6 Then
item(5) = item(5) + 1
End If
Next
ElseIf year3s = "N" Or year3s = "n" Then
For i As Integer = 1 To liness.Count - 1 'this will read to the end of the array list once
If item(5) > 2 And item(5) < 6 Then
item(5) = item(5) + 1
End If
Next
End If
File.WriteAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv", liness)
Exit For
Next
Exit Do
ElseIf enter.Key = ConsoleKey.End Then
Console.Clear()
adminmenu()
End If
You are updating the 'item' array, but not the 'liness' list. When you write the new 'liness' list to the file, any changes you made to the 'item' array are ignored.
Also, you are writing the 'liness' list back to the file for every loop iteration - this has to be wrong - you probably want to do that after the loop.
While I don't condone using the Split() function for parsing CSV data, I'll leave that part alone here in order to highlight other improvements in the code:
Dim minYear As Integer = 2
Console.WriteLine("Have you already entered the next school years, year 3's? (y/n)")
If Console.ReadLine().ToUpper().Trim() = "Y" Then minYear = 3
Dim NewLines = File.ReadLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv").
Select(Function(l) l.Split(","c) ).
Where(Function(l) Integer.Parse(l(5)) <> 6 ).
Select(Function(l)
Dim x As Integer = Integer.Parse(l(5))
If x >= minYear Then x += 1
l(5) = x.ToString()
Return String.Join(",", l)
End Function).ToList()
File.WriteAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv", NewLines)
What is causing 'Index was outside the bounds of the array' error? It can't be my file, defianetly not. Below is my code:
Sub pupiltest()
Dim exitt As String = Console.ReadLine
Do
If IsNumeric(exitt) Then
Exit Do
Else
'error message
End If
Loop
Select Case exitt
Case 1
Case 2
Case 3
End Select
Do
If exitt = 1 Then
pupilmenu()
ElseIf exitt = 3 Then
Exit Do
End If
Loop
Dim score As Integer
Dim word As String
Dim totalscore As Integer = 0
'If DatePart(DateInterval.Weekday, Today) = 5 Then
'Else
' Console.WriteLine("You are only allowed to take the test on Friday unless you missed it")
' pupiltest()
'End If
Dim founditem() As String = Nothing
For Each line As String In File.ReadAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv")
Dim item() As String = line.Split(","c)
founditem = item
Next
Dim stdntfname As String = founditem(3)
Dim stdntsname As String = founditem(4)
Dim stdntyear As String = founditem(5)
Console.Clear()
If founditem IsNot Nothing Then
Do
If stdntyear = founditem(5) And daytoday = founditem(6) Then
Exit Do
ElseIf daytoday <> founditem(6) Then
Console.WriteLine("Sorry you are not allowed to do this test today. Test available on " & item(6).Substring(0, 3) & "/" & item(6).Substring(3, 6) & "/" & item(6).Substring(6, 9))
Threading.Thread.Sleep(2500)
pupiltest()
ElseIf stdntyear <> founditem(5) Then
Console.WriteLine("Year not found, please contact the system analysts")
Threading.Thread.Sleep(2500)
pupiltest()
End If
Loop
End If
For Each line As String In File.ReadAllLines("F:\Computing\Spelling Bee\testtests.csv")
Dim item() As String = line.Split(","c)
Dim mine As String = String.Join(",", item(2), item(3), item(4), item(5), item(6))
For i As Integer = 1 To 10
Console.WriteLine(i.ToString & "." & item(1))
Console.Write("Please enter the word: ")
word = Console.ReadLine
If word = Nothing Or word <> item(0) Then
score += 0
ElseIf word = item(0) Then
score += 2
ElseIf word = mine Then
score += 1
End If
Next
If score > 15 Then
Console.WriteLine("Well done! Your score is" & score & "/20")
ElseIf score > 10 Then
Console.WriteLine("Your score is" & score & "/20")
ElseIf score Then
End If
Next
Using sw As New StreamWriter("F:\Computing\Spelling Bee\stdntscores", True)
sw.Write(stdntfname, stdntsname, stdntyear, score, daytoday, item(7))
Try
Catch ex As Exception
MsgBox("Error accessing designated file")
End Try
End Using
End
End Sub
All help is highly appreciated,
You are constantly replacing the foundItem array when you do founditem = item:
Dim founditem() As String = Nothing
For Each line As String In File.ReadAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv")
Dim item() As String = line.Split(","c)
founditem = item
Next
Also, you are using (=) the assignment operation instead of (==) relational operator, to compare. Refer to this article for help in understanding the difference between the two.
Instead of this: If stdntyear = founditem(5) And daytoday = founditem(6) Then
Use this: If (stdntyear == founditem(5)) And (daytoday == founditem(6)) Then
Now back to your main error. You continue to assign the itemarray to founditem every time you iterate (Which overwrites previous content). At the end of the Iteration you will be left with the last entry in your CSV only... So in other words, founditem will only have 1 element inside of it. If you try to pick out ANYTHING but index 0, it will throw the exception index was outside the bounds of the array
So when you try to do the following later, it throws the exception.
Dim stdntfname As String = founditem(3) 'index 3 does not exist!
To fix it do the following change:
Dim founditem() As String = Nothing
For Each line As String In File.ReadAllLines("F:\Computing\Spelling Bee\stdnt&staffdtls.csv")
'NOTE: Make sure you know exactly how many columns your csv has or whatever column
' you wish to access.
Dim item() As String = line.Split(","c)
founditem(0) = item(0) 'Assign item index 0 to index 0 of founditem...
founditem(1) = item(1)
founditem(2) = item(2)
founditem(3) = item(3)
founditem(4) = item(4)
founditem(5) = item(5)
founditem(6) = item(6)
Next
For more help on how to work with VB.NET Arrays visit this site: http://www.dotnetperls.com/array-vbnet
In your line Dim item() As String = line.Split(","c) there's no guarantee that the correct number of elements exist. It's possible that one of the lines is missing a comma or is a blank trailing line in the document. You might want to add a If item.Length >= 7 and skipping rows that don't have the right number of rows. Also, remember that unlike VB6, arrays in .Net are 0 based not 1 based so make sure that item(6) is the value that you think it is.