sequential access file in vb - vb.net

I am working on a program in Visual Basic that incorporates using a sequential access file for a ballot type program. Each type the user clicks the save vote button, the amount of votes gets stored. What I am trying to do is in my access file is to display the number of votes as an actual number. The way my program is written right now, the name of the candidate appears as many times as the vote was saved. for example, if perez was voted for 4 times, in the access file perez is displayed on 4 different lines. How do I display the actual number of how many time they were voted for. I'm thinking using a counter variable, but not really sure how to really implement it in. this is what i have so far.
Public Class Voter
Dim file As IO.File
Dim infile As IO.StreamReader
Dim outfile As IO.StreamWriter
Private Sub Voter_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
outfile = IO.File.CreateText("Votes.txt")
End Sub
Private Sub btnVote_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnVote.Click
lstResult.Items.Clear()
'which buttons is clicked
If radMark.Checked = True Then
outfile.WriteLine(radMark.Text)
radMark.Checked = False
ElseIf radSheima.Checked = True Then
outfile.WriteLine(radSheima.Text)
radSheima.Checked = False
ElseIf radSam.Checked = True Then
outfile.WriteLine(radSam.Text)
radSam.Checked = False
Else
MessageBox.Show("You should select one among them")
End If
End Sub
Private Sub btnResult_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnResult.Click
'Dim Mark, Sheima, Sam As Integer
Dim Mark As Integer = 0
Dim Sheima As Integer = 0
Dim Sam As Integer = 0
Dim name As String
'Mark = Sheima = Sam = 0
outfile.Close()
infile = IO.File.OpenText("Votes.txt")
'keep track of votes
While Not infile.EndOfStream
name = infile.ReadLine()
If name.Equals("Mark Stone") Then
Mark += 1
ElseIf name.Equals("Sheima Patel") Then
Sheima += 1
Else
Sam += 1
End If
End While
'results
lstResult.Items.Clear()
lstResult.Items.Add("Mark Stone " & CStr(Mark))
lstResult.Items.Add("Shemia Patel " & CStr(Sheima))
lstResult.Items.Add("Sam Perez " & CStr(Sam))
infile.Close()
End Sub
Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click
Me.Close()
End Sub
End Class

In your btnVote_Click function you are writing the radiobutton text into the file everytime you click on it, that's how the issue to be created.
Also you are counting how many times the name appears in the file as the number of vote but not the number.
You should try putting the name and count in your vote file rather than just the name, e.g.
Mark,1
Sheima,2
Same,5
Then when you click Vote button, you should read the number for Mark, increment by 1 and write it back.
Try this,
Private Sub btnVote_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnVote.Click
lstResult.Items.Clear()
'which buttons is clicked
If radMark.Checked = True Then
AddCount(radMark.Text)
radMark.Checked = False
ElseIf radSheima.Checked = True Then
AddCount(radSheima.Text)
radSheima.Checked = False
ElseIf radSam.Checked = True Then
AddCount(radSam.Text)
radSam.Checked = False
Else
MessageBox.Show("You should select one among them")
End If
End Sub
Private Sub btnResult_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnResult.Click
'results
lstResult.Items.Clear()
lstResult.Items.Add("Mark Stone " & GetCount(radMark.Text))
lstResult.Items.Add("Shemia Patel " & CStr(radSheima.Text))
lstResult.Items.Add("Sam Perez " & CStr(radSam.Text))
End Sub
Private Sub AddCount(Byval VoteName As String)
infile = New IO.File.StreamReader("Votes.txt")
Dim whole_line As String
Dim person As String
Dim vote_count As Integer
Dim found as boolean
'read through the whole file until the end or find the name
Do While infile.Peek() >= 0 And person <> VoteName
'read each line
whole_line = infile.ReadLine
person = Split(whole_line, ",")(0)
If person = VoteName Then
vote_count = Split(whole_line, ",")(1)
found = True
End If
Loop
'Close the file after it is used.
infile.Close()
'Reopen the file with the StreamWriter
outfile = IO.File.OpenText("Votes.txt")
If found = True Then
'the line will only be replace if the person name is found in the line
whole_line = Whole_line.replace(VoteName & "," & vote_count, VoteName & "," & vote_count + 1)
'Write back into the file
outfile.WriteLine(whole_line)
Else
'if the vote name is not found in the file
'Then create a new one
outfile.WriteLine(VoteName & ",1" & VbCrLf)
End If
outfile.Close()
End Sub
Private Function GetCount(Byval VoteName As String)
infile = New IO.File.StreamReader("Votes.txt")
Dim whole_line As String
Dim person As String
Dim vote_count As Integer
'read through the whole file
Do While infile.Peek() >= 0 And person <> VoteName
'read each line
whole_line = infile.ReadLine
person = Split(Whole_line, ",")(0)
If person = VoteName Then
vote_count = Split(whole_line, ",")(1)
End If
Loop
infile.Close()
Return vote_count
End Sub

Related

Reading and writing files causes "The process cannot access the file because it is being used by another process" error

I'm very new to coding so my code is very basic but I am trying to rewrite a file using an item selected from a list box. The code is a recreation of my full code so it's not as thorough but I want to be able to change the "availability" of a product for a website (In theory because this is not a professional project). When I try to read or write the file an error message comes up saying "The process cannot access the file because it is being used by another process".
Dim FileRewrite As String = "FileRewrite.txt"
Dim ValidateID As Boolean
Dim Read As String
Dim IDR As String
Dim YNR As String
Private Sub TxtBxID_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles TxtBxID.TextChanged
If TxtBxID.Text.Length = 2 Then
ValidateID = True
Else
ValidateID = False
End If
End Sub
Private Sub BtnAdd_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnAdd.Click
Dim ID As String
Dim YN As String
Dim Writer As New System.IO.StreamWriter(FileRewrite, True)
If ValidateID = True Then
ID = TxtBxID.Text
If CBxYN.Checked = True Then
YN = "YES"
Else
YN = "NO "
End If
Writer.WriteLine(LSet(ID, 3) & LSet(YN, 3))
Writer.Close()
LstBxItems.Items.Clear()
Dim Reader As New System.IO.StreamReader(FileRewrite, True)
Do While Reader.Peek >= 0
LstBxItems.Items.Add(Reader.ReadLine)
Loop
Reader.Close()
Else
MsgBox("Please enter a 2 digit ID")
End If
End Sub
Private Sub BtnChange_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BtnChange.Click
Dim ItemToChange As String
Dim Reader As New System.IO.StreamReader(FileRewrite, True)
ItemToChange = LstBxItems.SelectedItem
IDR = Mid(ItemToChange, 1, 3)
YNR = Mid(ItemToChange, 4, 6)
Do While Reader.Peek >= 0
Read = Reader.ReadLine
Writer()
Loop
Reader.Close()
End Sub
Private Sub Writer()
Dim Writer As New System.IO.StreamWriter(FileRewrite, True)
If Mid(Read, 1, 3) = IDR Then
If YNR = "YES" Then
YNR = "NO "
Else
YNR = "YES"
End If
Writer.WriteLine(LSet(IDR, 3) & LSet(YNR, 3))
Writer.Close()
End If
End Sub
I expect the availability of the product in the file to change from yes to no or no to yes but the reader and writer will not work
You cannot write to the file while looping through the same file to read via Reader.Peek

Why is it only displaying one result

This program is supposed to accept in valid candidates for voting, add the names typed in a text box to a list box. In the list box the user may double click on the candidate they choose. After the tally button is clicked a list box displaying the candidates' Names and votes will appear along side the other list box.
My problem is that the lstTallies only displays the last voted candidate.
Below is my code
Public Class Form1
Dim maxVotes As Integer
Dim winner As String
Dim votes() As Integer
Dim index As Integer
Dim candidates As String
Private Sub btnAdd_Click(sender As Object, e As EventArgs) Handles btnAdd.Click
If Not isValidInput(txtNewCandidate.Text) Then
Exit Sub
End If
lstCandidates.Items.Add(txtNewCandidate.Text)
txtNewCandidate.Clear()
txtNewCandidate.Focus()
ReDim Preserve votes(index)
index += 1
End Sub
Private Function isValidInput(ByRef firstName As String) As Boolean
If IsNumeric(txtNewCandidate.Text) Or txtNewCandidate.Text = "" Then
MsgBox("Please input a valid candidate name.")
txtNewCandidate.Focus()
Return False
Else
Return True
End If
End Function
Private Sub btnTally_Click(sender As Object, e As EventArgs) Handles btnTally.Click
lstTallies.Visible = True
lblTally.Visible = True
lstTallies.Items.Add(lstCandidates.Text & " " & votes(lstCandidates.SelectedIndex))
End Sub
Private Sub lstCandidates_DoubleClick(sender As Object, e As EventArgs) Handles lstCandidates.DoubleClick
If lstCandidates.SelectedIndex = -1 Then
MsgBox("Select a candidate by double-clicking")
End If
votes(lstCandidates.SelectedIndex) += 1
MsgBox("Vote Tallied")
End Sub
End Class
Try this:
Assuming the index of the Candidate and his/her Vote are the same:
Private Sub btnTally_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnTally.Click
lstTallies.Visible = True
lblTally.Visible = True
For i = 0 To lstCandidates.Items.Count - 1
lstTallies.Items.Add(lstCandidates.Items(i).ToString & " - " & votes(i))
Next
End Sub
You cannot get the contents of the ListBox unless you iterate it.

VB.NET Read text file line by line and set every line in textbox with button clicks

hello i want to read text file line by line and set every lien in textbox eash time i click the button
this is my code and working fine. but i looking for easy way to read large text that has more thean 5 lines ?
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Static count As Integer
count = count + 1
Dim textfile As String = "c:\test.txt"
If IO.File.Exists(textfile) Then
Dim readLines() As String = IO.File.ReadAllLines(myFile)
If count = 1 Then
TextBox1.Text = readLines(0)
End If
If count = 2 Then
TextBox1.Text = readLines(1)
End If
If count = 3 Then
TextBox1.Text = readLines(2)
End If
If count = 4 Then
TextBox1.Text = readLines(3)
End If
If count = 5 Then
TextBox1.Text = readLines(4)
End If
If count = 6 Then
TextBox1.Text = readLines(5)
End If
End If
End Sub
I think you need to read the file just one time when you load your form (assuming a WinForms example here)
' Declare these two globally
Dim readLines() As String
Dim count As Integer = 0
Private void Form_Load(sender As Oject, e As EventArgs) Handles Base.Load
' In form load, read the file, just one time
Dim textfile As String = "c:\test.txt"
If IO.File.Exists(textfile) Then
readLines() As String = IO.File.ReadAllLines(myFile)
else
TextBox1.Text "File not found"
End If
End Sub
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
' Check if you have a file and if you don't have reached the last line
if readLines IsNot Nothing AndAlso count < readLines.Length Then
TextBox1.Text = readLines(count)
count += 1
else
TextBox1.Text "End of file"
End If
End Sub
This reduces the amount of code you need to write:
TextBox1.Text = readLines(count - 1)

How to search a text file in Visual basic

So my teacher wants the class to search a file for an authors name and display all the info on that author in a text box like a mailing label.
Here is my code i added a picture below. I'm really lost as to getting the program to take the Authors string and search another file. I can display the Authors name prefectly but how do you search another file for that name and display the information on that line about the author?
Imports System.IO
Public Class Form1
' CSCI 6
' Alex Smutny
' Lab #3
'
' DATE: 3/1/2013
Dim SR As IO.StreamReader
' initial start spot for the record Count
Dim RecordCount As Integer = 0
Dim Author As String = File.ReadAllText("Authors.txt")
Private Sub btnQuit_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles quitBtn.Click
' Properly Exits the application.
Me.Close()
End Sub
Private Sub btnClose_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles closeBtn.Click
readBtn.Text = "Read"
SR.Close()
' Changes the button statuses Locked or unlocked and sets default settings.
openBtn.Enabled = True
quitBtn.Enabled = True
readBtn.Enabled = False
closeBtn.Enabled = False
SearBtn.Enabled = False
RecordCount = 0
recordNum.Clear()
bookNum.Clear()
isbnNum.Clear()
bookTitle.Clear()
authorName.Clear()
bookPrice.Clear()
bookQuanity.Clear()
reorderPoint.Clear()
End Sub
Private Sub btnOpen_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles openBtn.Click
' Sets the file to read from and opens it.
SR = IO.File.OpenText("Books.Txt")
' Changes the status of the buttons again now that the File is open and ready to read.
openBtn.Enabled = False
quitBtn.Enabled = False
readBtn.Enabled = True
closeBtn.Enabled = True
SearBtn.Enabled = True
End Sub
Private Sub btnRead_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles readBtn.Click
'Changes the Read button to say next because it makes more since.
readBtn.Text = "Next"
' Setting all the variables.
Dim srIndex1 As Integer = 18
Dim srTitle As Integer
Dim srAuthor As Integer
Dim srPrice As Integer
Dim srDPrice As Double
Dim srData As String
Dim srLength As Integer
If SR.Peek() = -1 Then
MessageBox.Show("End of file")
Else
' Starts to read
srData = SR.ReadLine
' Increment counter by 1.
RecordCount = RecordCount + 1
' Determine the record length.
srLength = srData.Length
' gets the book number
bookNum.Text = srData.Substring(0, 3)
' ISBN number
isbnNum.Text = srData.Substring(4, 13)
' Book title
For srTitle = 1 To srLength Step 1
If srData.Substring(srIndex1 + srTitle, 1) = "," Then
bookTitle.Text = srData.Substring(srIndex1, srTitle)
srIndex1 = srIndex1 + srTitle + 1
srTitle = srLength + 1
End If
Next
' Book Author
For srAuthor = 1 To srLength Step 1
If srData.Substring(srIndex1 + srAuthor, 1) = "," Then
authorName.Text = srData.Substring(srIndex1, srAuthor)
srIndex1 = srIndex1 + srAuthor + 1
srAuthor = srLength + 1
Author = authorName.Text
End If
Next
' Book Price
For srPrice = 1 To srLength Step 1
If srData.Substring(srIndex1 + srPrice, 1) = "," Then
srDPrice = CDbl(srData.Substring(srIndex1, srPrice))
bookPrice.Text = srDPrice.ToString("C")
srIndex1 = srIndex1 + srPrice + 1
srPrice = srLength + 1
End If
Next
' Quanity
bookQuanity.Text = srData.Substring(srIndex1, 2)
srIndex1 = srIndex1 + 3
' Reorder Point
reorderPoint.Text = srData.Substring(srIndex1, 2)
End If
' record count
recordNum.Text = RecordCount
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
openBtn.Enabled = True
quitBtn.Enabled = True
readBtn.Enabled = False
closeBtn.Enabled = False
SearBtn.Enabled = False
End Sub
Private Sub SearBtn_Click(sender As System.Object, e As System.EventArgs) Handles SearBtn.Click
SR = IO.File.OpenText("Authors.Txt")
SR.Close()
readBtn.Text = "Restart"
RecordCount = 0
SR = IO.File.OpenText("Books.Txt")
End Sub
End Class
Authors File http://pastebin.com/t7C8ye9e
Books File http://pastebin.com/y6DNyUFd
So my goal is to just get the info for the current author and then get it from the other file and take out all trailing spaces and just display it as a mailing label.
There's a variety of good ways to do this. Let's, for now, assume that there's one author per line. If there is, you can get the entire string with My.Computer.FileSystem.ReadAllText() and use String.Split(Environment.NewLine) to split it on each new line. At any rate, you need to have some way to separate each author in the list. String.Split returns an array of String objects. You can then iterate through the array to determine if a term matches the search. Here's an example of a for loop.
'... search term given in param
'... after loading text file
Dim StrArr() As String
StrArr = AuthorsString.Split(Environment.NewLine)
Dim i as Integer
For i=0 to StrArr.Length - 1 Step 1
If StrArr(i).toLower = SearchTerm.toLower Then
'String is a match! Case insensitivity should make it a little easier for the user.
End If
Next
Let me know if you have any questions.

Running Different Processes In Multiple Threads Without Overlapping In VB.NET 2

I have a sub-procedure which I want to run a different process, depending on what is currently running. I thought the easiest way to do this was by using an ArrayList of each of the campaign details & adding an 'Inuse' field to check to see if the Inuse field is set to 0 or 1. The problem that I have is that when running the process it is all happening at once & the integer hasn't been changed before the next thread kicks in so my threads are running the same campaigns.
I tried to avoid the problem by adding a Thread.Sleep(100) delay inbetween starting threads but this led to exactly the same problem.
Here's an example of what I am trying to do:
Imports System.Threading
Public Class Form1
Private Campaigns As New ArrayList
Private ProcessRunning As Boolean = False
Friend StopProcess As Boolean = False
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
For i = 0 To Campaigns.Count - 1
Dim objNewThread As New Thread(AddressOf RunProcess)
objNewThread.IsBackground = True
objNewThread.Start()
Next
End Sub
Private Sub UpdateCells(ByVal CampID As Integer, ByVal Column As String, ByVal newText As String)
Dim CellItemNum As Integer
If Column = "Status" Then CellItemNum = 4
DataGridView2.Rows(CampID).Cells.Item(CellItemNum).Value = newText
End Sub
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
For i As Integer = 0 To 10
Campaigns.Add({Campaigns.Count(), "Campaign " & i, "Keywords " & i, "Link " & i, 5, True, 0, 0})
Next
DataGridView2.Rows.Clear()
For Each Campaign In Campaigns
DataGridView2.Rows.Add(New String() {Campaign(1), Campaign(2), Campaign(3), Campaign(6), ""})
Next
End Sub
Private Sub RunProcess()
' Set Variables
Dim CampID As Integer
Dim CampName As String
Dim Keywords As String
Dim Link As String
Dim CheckEvery As Integer
Dim OkToUse As Boolean
Dim Sent As Integer
' Find A Free Campaign
For i As Integer = 0 To Campaigns.Count - 1
' Check If Inuse
If Campaigns(i)(7) = 1 Then Continue For Else Campaigns(i)(7) = 1 ' This Line Sets Campaign To Inuse
' Most of the time only campaign(0) and campaign(1) are selected & multiple threads are running them instead of choosing unique campaigns
' Set Campaign Details
CampID = Campaigns(i)(0)
CampName = Campaigns(i)(1)
Keywords = Campaigns(i)(2)
Link = Campaigns(i)(3)
CheckEvery = Campaigns(i)(4)
OkToUse = Campaigns(i)(5)
Sent = Campaigns(i)(6)
' Start Process
UpdateCells(CampID, "Status", "Looking Up New Links (" & CampID & ")")
Exit For
Next
While StopProcess = False
Thread.Sleep(1000)
UpdateCells(CampID, "Status", "Running Process (" & CampID & ")")
Thread.Sleep(1000)
For i = 0 To CheckEvery
UpdateCells(CampID, "Status", "Re-Checking In " & (CheckEvery - i) & " Seconds")
Thread.Sleep(1000)
Next
End While
' Closing Processes
Campaigns(CampID)(7) = 0
End Sub
End Class
You can use SyncLock to force your threads to wait.
class level so all threads access same lock
private myLock as new Object
Then use syncLock when you start your process and end it when you are done.
SyncLock myLock
'process code here
End SyncLock
More MSDN info on the subject
Try looking into QueueUserWorkItem():
Private Sub Button1_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles Button1.Click
For i = 0 To Campaigns.Count - 1
ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf RunProcess), Campaigns[i])
Next
End Sub
Then change the RunProcess() method to include the Campaign object sent in by the work item:
Private Sub RunProcess(ByVal o As System.Object)
' Process the Campaign
Dim campaign As Campaign = Ctype(o, Campaign)
End Sub
There will be no need for inuse, plus threads will be managed by the managed ThreadPool!