Use streamreader to load data from text file into textboxes, code cannot find objStudent array - vb.net

Option Strict On
Imports System.Text.RegularExpressions
Imports System.IO
Public Class StudentTestScores
Private Structure Student
Dim strStudentName As String
Dim dblTestScores() As Double
Dim dblAverage As Double
End Structure
Public Function GetDoubleTestScore(ByVal value As String) As Double
'Checks if the value is numeric and returns message if error is found
If IsNumeric(value) Then
Dim dblValue = CDbl(value)
'Check to make sure number is a positive and less or equal to 100
If dblValue >= 0 And dblValue <= 100 Then
Return dblValue
Else
Throw New Exception("The number needs to be between 0 and 100")
End If
Else
Throw New Exception("Please enter a number in the test score area.")
End If
End Function
Private Sub btnCalc_Click(sender As Object, e As EventArgs) Handles btnCalc.Click
'Creates variable and runs isValidName
Dim objStudent(6) As Student
If isValidName() = True Then
Try
' This initializes each of the test score arrays in a Student object
For i As Integer = 0 To 5
InitializeTestScores(objStudent(i))
Next
InitializeTestScores(objStudent(0))
'runs isNumeric function to txtStudentScores
objStudent(0).dblTestScores(0) = GetDoubleTestScore(txtStudent1Score1.Text)
objStudent(0).dblTestScores(1) = GetDoubleTestScore(txtStudent1Score2.Text)
objStudent(0).dblTestScores(2) = GetDoubleTestScore(txtStudent1Score3.Text)
objStudent(0).dblTestScores(3) = GetDoubleTestScore(txtStudent1Score4.Text)
objStudent(0).dblTestScores(4) = GetDoubleTestScore(txtStudent1Score5.Text)
objStudent(1).dblTestScores(0) = GetDoubleTestScore(txtStudent2Score1.Text)
objStudent(1).dblTestScores(1) = GetDoubleTestScore(txtStudent2Score2.Text)
objStudent(1).dblTestScores(2) = GetDoubleTestScore(txtStudent2Score3.Text)
objStudent(1).dblTestScores(3) = GetDoubleTestScore(txtStudent2Score4.Text)
objStudent(1).dblTestScores(4) = GetDoubleTestScore(txtStudent2Score5.Text)
objStudent(2).dblTestScores(0) = GetDoubleTestScore(txtStudent3Score1.Text)
objStudent(2).dblTestScores(1) = GetDoubleTestScore(txtStudent3Score2.Text)
objStudent(2).dblTestScores(2) = GetDoubleTestScore(txtStudent3Score3.Text)
objStudent(2).dblTestScores(3) = GetDoubleTestScore(txtStudent3Score4.Text)
objStudent(2).dblTestScores(4) = GetDoubleTestScore(txtStudent3Score5.Text)
objStudent(3).dblTestScores(0) = GetDoubleTestScore(txtStudent4Score1.Text)
objStudent(3).dblTestScores(1) = GetDoubleTestScore(txtStudent4Score2.Text)
objStudent(3).dblTestScores(2) = GetDoubleTestScore(txtStudent4Score3.Text)
objStudent(3).dblTestScores(3) = GetDoubleTestScore(txtStudent4Score4.Text)
objStudent(3).dblTestScores(4) = GetDoubleTestScore(txtStudent4Score5.Text)
objStudent(4).dblTestScores(0) = GetDoubleTestScore(txtStudent5Score1.Text)
objStudent(4).dblTestScores(1) = GetDoubleTestScore(txtStudent5Score2.Text)
objStudent(4).dblTestScores(2) = GetDoubleTestScore(txtStudent5Score3.Text)
objStudent(4).dblTestScores(3) = GetDoubleTestScore(txtStudent5Score4.Text)
objStudent(4).dblTestScores(4) = GetDoubleTestScore(txtStudent5Score5.Text)
objStudent(5).dblTestScores(0) = GetDoubleTestScore(txtStudent6Score1.Text)
objStudent(5).dblTestScores(1) = GetDoubleTestScore(txtStudent6Score2.Text)
objStudent(5).dblTestScores(2) = GetDoubleTestScore(txtStudent6Score3.Text)
objStudent(5).dblTestScores(3) = GetDoubleTestScore(txtStudent6Score4.Text)
objStudent(5).dblTestScores(4) = GetDoubleTestScore(txtStudent6Score5.Text)
' This loops through each Student structure object and calculates the average test score.
For i As Integer = 0 To 5
objStudent(i).dblAverage = CaculateStudentAverage(objStudent(i))
Next
objStudent(0).strStudentName = txtStudent1.Text
objStudent(1).strStudentName = txtStudent2.Text
objStudent(2).strStudentName = txtStudent3.Text
objStudent(3).strStudentName = txtStudent4.Text
objStudent(4).strStudentName = txtStudent5.Text
objStudent(5).strStudentName = txtStudent6.Text
lblAverageStudent1.Text = objStudent(0).dblAverage.ToString()
lblAverageStudent2.Text = objStudent(1).dblAverage.ToString()
lblAverageStudent3.Text = objStudent(2).dblAverage.ToString()
lblAverageStudent4.Text = objStudent(3).dblAverage.ToString()
lblAverageStudent5.Text = objStudent(4).dblAverage.ToString()
lblAverageStudent6.Text = objStudent(5).dblAverage.ToString()
'This creates the text file the program will write to
Dim StudentFile As System.IO.StreamWriter
Dim strFileName As String = "StudentTestScore.txt"
StudentFile = System.IO.File.AppendText(strFileName)
'Creates for loop that takes the 6 students
For i As Integer = 0 To 5
StudentFile.Write("Student Name: ")
StudentFile.Write(objStudent(i).strStudentName)
StudentFile.Write(" Student Test Scores: ")
'This creates a loop for the students and test scores
For intIndex2 As Integer = 0 To 4
StudentFile.Write(objStudent(i).dblTestScores(intIndex2).ToString())
If intIndex2 <> 4 Then
StudentFile.Write(", ")
End If
'Finally the average is ran using the objStudent (i)
Next
StudentFile.Write(" Average Score = ")
StudentFile.Write(objStudent(i).dblAverage.ToString())
StudentFile.WriteLine()
Next
'Closes the text file that was created
StudentFile.Close()
'Shows a message box that says the file was written to the text file and or modified
MessageBox.Show("Student Test Score file was created or modified.")
Catch ex As Exception
MessageBox.Show(ex.Message)
End Try
End If
End Sub
Private Sub InitializeTestScores(ByRef objStudent As Student) 'references objStudent object
' This takes the array dblTestScores and makes it a fixed array of size 6 since it could not be given a number in the structure
ReDim objStudent.dblTestScores(5)
End Sub
Private Function CaculateStudentAverage(ByVal objStudent As Student) As Double
' This loop loops through each value in dblTestScores and then just adds them to objstudent
For i As Integer = 0 To 4
objStudent.dblAverage += objStudent.dblTestScores(i)
Next
' This divides and then stores it back into the variable
objStudent.dblAverage /= 5
'Returns student average
Return objStudent.dblAverage
End Function
Private Sub LoadToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles LoadToolStripMenuItem.Click
' Create a new open file dialog
Dim MyFileDialog As New System.Windows.Forms.OpenFileDialog
' Configure the dialog to show only text files
' Set its title and set the filename field blank for the moment.
MyFileDialog.FileName = "StudentTestScore.txt"
' Show the dialog and see if the user pressed ok.
If MyFileDialog.ShowDialog() = Windows.Forms.DialogResult.OK Then
' Check to see if they selected a file and that it exists.
If File.Exists(MyFileDialog.FileName) Then
Dim strFile As String = MyFileDialog.FileName
Dim reader As StreamReader
Try
' Setup a file stream reader to read the text file.
reader = New StreamReader(New FileStream(strFile, FileMode.Open, FileAccess.Read))
' While there is data to be read, read each line into a rich edit box control.
Select
Case 0
txtStudent1.Text = Student.objStudent(0)
txtStudent1Score1.Text =
End Select
While reader.Peek > -1
txtStudent1.Text &= reader.ReadLine()
End While
' Close the file
reader.Close()
Catch ex As FileNotFoundException
' If the file was not found, tell the user.
MessageBox.Show("File was not found. Please try again.")
End Try
End If
End If
End Sub
End Class

Related

How to stop new lines being created when I want to edit the first line when the file has been created

I have made some functions that run on a button click. It creates the file if it does not exist and writes to the first line "1" on the first write to the file, however when you click the button again, it moves that "1" down a line each time in the file.
Any help would be appreciated!
Dim appData As String = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
Dim Lines As New List(Of String)
Public Function ReadConfigLines()
If File.Exists(appData + "\example.txt") Then
Lines.Clear()
Lines.AddRange(File.ReadAllLines(appData + "\example.txt").ToList)
End If
End Function
Public Function WriteConfigLines()
Dim i As Integer = 0
Dim c As Integer = 0
Dim newlines As String = ""
While i < Lines.Count()
While i > c
newlines = newlines + vbCrLf
c = c + 1
End While
File.WriteAllText(appData + "\example.txt", newlines + Lines(i))
newlines = ""
c = 0
i = i + 1
End While
End Function
Private Sub btnAvatar1_Click(sender As Object, e As EventArgs) Handles btnAvatar1.Click
PBPreview.Image = btnAvatar1.Image
ReadConfigLines()
Lines.Insert(0, "1")
WriteConfigLines()
End Sub

Highlight specific text while user is typing

I am writing a code that highlight the duplicate words in a text. The code is working well when I add a button and the user have to press on the button to check for duplicates.
But I want to make an auto-checking code. I set my code in a subroutine that Handles RichTextBox.TextChanged. The problem is the code selects the target word and highlight it but the selection remains so when a new letter is typed, it clear what has been highlighted.
Here is my code:
Private Sub RichTextBox_TextChanged(sender As Object, e As EventArgs) Handles RichTextBox.TextChanged
Try
Call duplicate_check()
Catch ex As Exception
MessageBox.Show("error in RichTextBox.TextChanged")
End Try
End Sub
duplicate check function:
Private Sub duplicate_check()
Try
' read line by line and get input
Dim LineByLineInput() As String = RichTextBox.Lines
Dim selectionStart, selectionLength As Integer
Dim i, j As Integer
For lineNumber = 0 To UBound(LineByLineInput)
selectionStart = 0
selectionLength = 0
'get index of first char index in the current line
Dim count As Integer = lineNumber
While count <> 0
selectionStart += RichTextBox.Lines(count - 1).Length + 1
count -= 1
End While
' get line as string
Dim line As String = RichTextBox.Lines(lineNumber)
' split line into array of strings
Dim input() As String = line.Split(" ")
'check for duplicates
i = 0
For j = i + 1 To UBound(input)
If input(i) = input(j) Then 'compare each 2 consecutive words if they are the same
selectionStart += input(i).Length + 1
selectionLength = input(i).Length
RichTextBox.SelectionStart = selectionStart
RichTextBox.SelectionLength = selectionLength
RichTextBox.SelectionBackColor = Color.Yellow
Else
selectionStart += input(i).Length + 1
End If
i += 1
Next
Next
Catch ex As Exception
MessageBox.Show("error duplicate_check()")
End Try
End Sub
After your duplicate_check call, have you tried to set the selection of the RichTextBox back to the old position ?
See below :
Private Sub RichTextBox1_TextChanged(sender As Object, e As System.EventArgs) Handles RichTextBox1.TextChanged
Try
' Get current position
Dim cur_pos As Integer = Me.RichTextBox.SelectionStart
Call duplicate_check()
' Set back to old position
Me.RichTextBox.SelectionStart = cur_pos
' Unselect what your sub duplicate_check has selected
Me.RichTextBox1.SelectionLength = 0
Catch ex As Exception
MessageBox.Show("error in RichTextBox.TextChanged")
End Try
End Sub
If this solution is good for you, you should change your duplicate_check Sub to make this change and not in the RichTextBox1_TextChanged Sub

How to debug a cast execption in vb.net?

I am getting a cast exception and I have re-written this code a large number of times. I am getting the exception on the following line:
If (CInt(hHurricaneYear) < CInt(_strYears(hAverage))) Then
And I am only getting results in the lblNumberOfHurricans. the other two labels are not showing any results. I thought I was getting it when the cast exception showed up.
Can anyone suggest how to get the results and stop the exception?
Here is what I have so far (well at least the last try).
Option Strict On
Public Class frmHurricaneStatistics
' Class level Private variables.
Public Shared _intSizeOfArray As Integer = 20
Private _strYears(_intSizeOfArray) As String
Private _intNumberOfHurricans(_intSizeOfArray) As Integer
Private Sub frmHurricaneStatistics_Load(sender As Object, e As EventArgs
) Handles MyBase.Load
' This load event reads the inventory text file and fills
' the ComboBox object with the Hurricane Statistics.
' Initialize an instace of the streamreader object and declare variables.
Dim objReader As IO.StreamReader
Dim strHurricaneStatistics As String = "Hurricanes.txt"
Dim intCount As Integer = 0
Dim intFill As Integer
Dim strFileError As String = "The file is not available. Please restart the
application when the file is available."
' Verify the Hurricane.txt file exists.
If IO.File.Exists(strHurricaneStatistics) Then
objReader = IO.File.OpenText(strHurricaneStatistics)
' Read the file line by line until the file is completed.
Do While objReader.Peek <> -1
_strYears(intCount) = objReader.ReadLine()
_intNumberOfHurricans(intCount) = Convert.ToInt32(objReader.ReadLine())
intCount += 1
Loop
objReader.Close()
' The ComboBox objext is filled with the Years for Hurricanes.
For intFill = 0 To (_strYears.Length - 1)
cmbYears.Items.Add(_strYears(intFill))
Next
Else
MsgBox(strFileError, , "Error")
Close()
' If ComboBox is filled then enable the Display Statistics button.
'btnDisplayStatistics.Enabled = True
End If
End Sub
Private Sub btnDisplayStatistics_Click(sender As Object, e As EventArgs
) Handles btnDisplayStatistics.Click
' This click event calls the sub procedures for the selected years and
' the number of hurricans in that year.
Dim intSelectedYear As Integer
Dim strMissingSelection As String = "Missing Selection"
Dim strSelectAYearError As String = "Please Select a Year"
' If the ComboBox object has a selection, Display Statistics.
If cmbYears.SelectedIndex >= 0 Then
intSelectedYear = cmbYears.SelectedIndex
Else
MsgBox(strSelectAYearError, , strMissingSelection)
End If
Private Sub btnDisplayStatistics_Click(sender As Object, e As EventArgs
) Handles btnDisplayStatistics.Click
' This click event calls the sub procedures for the selected years and
' the number of hurricans in that year.
Dim intSelectedYear As Integer
Dim strMissingSelection As String = "Missing Selection"
Dim strSelectAYearError As String = "Please Select a Year"
' If the ComboBox object has a selection, call the Display Statistics procedure.
If cmbYears.SelectedIndex >= 0 Then
intSelectedYear = cmbYears.SelectedIndex
Else
MsgBox(strSelectAYearError, , strMissingSelection)
End If
' This procedure MakeLabelsVisible Is called to display the labels
' And the results.
MakeLabelsVisible()
Dim hHurricaneAverage As Integer
Dim hHurricaneYear As Integer = 0
For hAverage As Integer = 0 To _strYears.Length - 1
If (CInt(hHurricaneYear) < CInt(_strYears(hAverage))) Then
hHurricaneYear = CInt(CType(CInt(_strYears(hAverage)), String))
End If
hHurricaneAverage = hHurricaneAverage + CInt((_strYears.ToString))
hHurricaneAverage = CInt(hHurricaneAverage / _strYears.Length)
Next
' Display the statistics for the Storm Average in the selected Year
' and the most active year within the range of year.
lblNumberOfHurricanes.Text = "The Number of Hurricanes in the Year " &
_strYears(intSelectedYear) & " is " & _intNumberOfHurricans(intSelectedYear).ToString() & "."
lblAvergeNumberHurricanes.Text = "The Average Number of Storms was " &
hHurricaneAverage & " Hurricanes."
Dim intSizeOfArray As Integer = Nothing
lblMostStorms.Text = "The Year "(CInt(_strYears(CInt(hHurricaneYear.ToString())) & "
Had The Most Storms Between " & (_strYears(0) & _strYears(20).ToString)))
End Sub
Option strict on
Your error lies in that you are trying to convert an entire string array into an integer:
hHurricaneAverage = hHurricaneAverage + CInt((_strYears.ToString))
You will need to call the index of _strYears:
hHurricaneAverage = hHurricaneAverage + CInt((_strYears(hAverage).ToString))
This will also explain why the other labels do not update, because hHurricanAverage never gets calculated.

VB "Index was out of range, must be non-negative and less than the size of the collection." When trying to generate a random number more than once

So I'm trying to generate a random number on button click. Now this number needs to be between two numbers that are inside my text file with various other things all separated by the "|" symbol. The number is then put into the text of a textbox which is being created after i run the form. I can get everything to work perfectly once, but as soon as i try to generate a different random number it gives me the error: "Index was out of range, must be non-negative and less than the size of the collection." Here is the main code as well as the block that generates the textbox after loading the form. As well as the contents of my text file.
Private Sub generate()
Dim newrandom As New Random
Try
Using sr As New StreamReader(itemfile) 'Create a stream reader object for the file
'While we have lines to read in
Do Until sr.EndOfStream
Dim line As String
line = sr.ReadLine() 'Read a line out one at a time
Dim tmp()
tmp = Split(line, "|")
rows(lineNum).buybutton.Text = tmp(1)
rows(lineNum).buyprice.Text = newrandom.Next(tmp(2), tmp(3)) 'Generate the random number between two values
rows(lineNum).amount.Text = tmp(4)
rows(lineNum).sellprice.Text = tmp(5)
rows(lineNum).sellbutton.Text = tmp(1)
lineNum += 1
If sr.EndOfStream = True Then
sr.Close()
End If
Loop
End Using
Catch x As Exception ' Report any errors in reading the line of code
Dim errMsg As String = "Problems: " & x.Message
MsgBox(errMsg)
End Try
End Sub
Private Sub Form2_Load(sender As Object, e As EventArgs) Handles MyBase.Load
rows = New List(Of duplicate)
For dupnum = 0 To 11
'There are about 5 more of these above this one but they all have set values, this is the only troublesome one
Dim buyprice As System.Windows.Forms.TextBox
buyprice = New System.Windows.Forms.TextBox
buyprice.Width = textbox1.Width
buyprice.Height = textbox1.Height
buyprice.Left = textbox1.Left
buyprice.Top = textbox1.Top + 30 * dupnum
buyprice.Name = "buypricetxt" + Str(dupnum)
Me.Controls.Add(buyprice)
pair = New itemrow
pair.sellbutton = sellbutton
pair.amount = amounttxt
pair.sellprice = sellpricetxt
pair.buybutton = buybutton
pair.buyprice = buypricetxt
rows.Add(pair)
next
end sub
'textfile contents
0|Iron Sword|10|30|0|0
1|Steel Sword|20|40|0|0
2|Iron Shield|15|35|0|0
3|Steel Shield|30|50|0|0
4|Bread|5|10|0|0
5|Cloak|15|30|0|0
6|Tent|40|80|0|0
7|Leather Armour|50|70|0|0
8|Horse|100|200|0|0
9|Saddle|50|75|0|0
10|Opium|200|500|0|0
11|House|1000|5000|0|0
Not sure what else to add, if you know whats wrong please help :/ thanks
Add the following two lines to the start of generate():
Private Sub generate()
Dim lineNum
lineNum = 0
This ensures that you don't point to a value of lineNum outside of the collection.
I usually consider it a good idea to add
Option Explicit
to my code - it forces me to declare my variables, and then I think about their initialization more carefully. It helps me consider their scope, too.
Try this little modification.
I took your original Sub and changed a little bit take a try and let us know if it solve the issue
Private Sub generate()
Dim line As String
Dim lineNum As Integer = 0
Dim rn As New Random(Now.Millisecond)
Try
Using sr As New StreamReader(_path) 'Create a stream reader object for the file
'While we have lines to read in
While sr.Peek > 0
line = sr.ReadLine() 'Read a line out one at a time
If Not String.IsNullOrEmpty(line) And Not String.IsNullOrWhiteSpace(line) Then
Dim tmp()
tmp = Split(line, "|")
rows(lineNum).buybutton.Text = tmp(1)
rows(lineNum).buyprice.Text = rn.Next(CInt(tmp(2)), CInt(tmp(3))) 'Generate the random number between two values
rows(lineNum).amount.Text = tmp(4)
rows(lineNum).sellprice.Text = tmp(5)
rows(lineNum).sellbutton.Text = tmp(1)
lineNum += 1
End If
End While
End Using
Catch x As Exception ' Report any errors in reading the line of code
Dim errMsg As String = "Problems: " & x.Message
MsgBox(errMsg)
End Try
End Sub

Basic Name Sorting Program using VB.net

My teacher has instructed our class to create a basic word sorting program the 'old fashioned way' in visual basic. So comparing two array values, a and b, then if one is considered higher in the order than the other, swap them if not do nothing, continue until there are no more swaps. Here is the code I have so far:
Imports System.IO
Imports System
Public Class Form1
Public arrText As New ArrayList()
Private Sub btnImprt_Click(sender As Object, e As EventArgs) Handles btnImprt.Click
'Dim OpenAnswerFile As New OpenFileDialog
Dim objReader As New StreamReader("c:\Users\Adam\Desktop\unSortList.txt")
Dim sLine As String = ""
Dim arrText As New ArrayList()
Do
sLine = objReader.ReadLine()
If Not sLine Is Nothing Then
arrText.Add(sLine)
End If
Loop Until sLine Is Nothing
objReader.Close()
Dim i As Integer = 0
txtImport.Text = arrText(i)
End Sub
Private Sub btnSort_Click(sender As Object, e As EventArgs) Handles btnSort.Click
Dim i As Integer = 0
Dim a As Integer = i + 1
txtImport.Text = i
txtImport.Text = a
Dim Temp As String
Dim Change As Boolean = True
While Change = True
Change = False
For Each i In arrText(i) - 1
If String.Compare(arrText(i), arrText(i + 1)) = 1 Then
Change = True
Temp = arrText(i)
arrText(i) = arrText(i + 1)
arrText(i + 1) = Temp
End If
Next
i = 0
End While
txtSort.Text = arrText(39)
End Sub
My problem is that I am getting an Index error and I'm not sure where the error is located as the logic seems fine.
And yes I am aware of the sorting function built into Visual Basic. but as the teacher said. No cheating.
Your code has several flaws, which I'm ignoring and just concentrating on the sorting part, as your query is related to that. Replace your sort loop with the following and check again. The basic problem was that your loop should only iterate up to List.Count - 2 and not List.Count - 1 because you're comparing List(i) and List(i + 1) inside the loop:
Dim Temp As String
Dim Change As Boolean = True
While Change
Change = False
For i = 0 To arrText.Count() - 2
If String.Compare(arrText(i), arrText(i + 1)) = 1 Then
Change = True
Temp = arrText(i)
arrText(i) = arrText(i + 1)
arrText(i + 1) = Temp
End If
Next
End While