How to check instantly the changes made by user in TextBoxs? - vb.net

The procedure allows the modification of text zones by means of an Modify button on the main form. Using a structure, I read and store lines from a text file, and populated according to line number, 3 text boxes. On the other hand, in order to leave it to the user to modify something in these zones if necessary, I would need to know which text zones have been modified! Claude.
Here is my code:
Private Sub Button9_Click(sender As Object, e As EventArgs) Handles Button9.Click
' Modifier
Dim bibliotheque As New article
With bibliotheque
.Title = TextBox1.Text
.Name = TextBox2.Text
.Charge = TextBox3.Text
End With
Dim fileName As String = "c:\essai.librairie"
Dim someString As String = Trim(TextBox2.Text)
Dim lignes As String() = File.ReadAllLines(fileName, Encoding.UTF8)
Dim found As Integer = -1
For i As Integer = 0 To lignes.Length - 1
If lignes(i).Contains(someString) Then
found = i
Exit For
End If
Next
Dim lines As String() = File.ReadAllLines("c:\essai.librairie", Encoding.UTF8)
lines(found) = bibliotheque.Title.PadRight(17, " "c).ToString & bibliotheque.Name.PadRight(90, " "c).ToString & bibliotheque.Charge.PadRight(120, " "c).ToString
MessageBox.Show("Enregistrer les données modifiées ?",
"Prénommer", MessageBoxButtons.OKCancel,
MessageBoxIcon.Question, MessageBoxDefaultButton.Button2)
If Windows.Forms.DialogResult.OK Then
File.WriteAllLines("c:\essai.librairie", lines, Encoding.UTF8)
Using fStream As New FileStream("c:\essai.librairie", FileMode.Open, FileAccess.ReadWrite, FileShare.None)
fStream.SetLength(fStream.Length - Environment.NewLine.Length)
End Using
Else
Exit Sub
End If
End Sub

You can use the events txtbox1.changed or txtbox1.leave to take action or flag that textbox as being changed. The .changed event fires every time a character is changed. .leave only fires when focus leaves the text box.

Related

Index was outside the bounds of the array. VB.NET

My problem
Index was outside the bounds of the array. when i try to run the code , it generates this error
i have two forms : SIGN IN and SIGN UP , my problem is they don't work together and generates the error attached below
Dim fs As New FileStream("C:\Users\Selmen\Desktop\vb\logs.txt", FileMode.Open, FileAccess.ReadWrite)
Dim sr As New StreamReader(fs)
Dim sw As New StreamWriter(fs)
Dim s As String
Dim t() As String
Dim trouve As Integer = 0
Dim tt() As String
Dim ch As String
ch = TextBox1.Text + "#" + TextBox2.Text + "#" + TextBox3.Text + "#" + TextBox4.Text + "#" + TextBox5.Text
tt = ch.Split("#")
Do While (trouve = 0) And (sr.Peek > -1)
s = sr.ReadLine
t = s.Split("#")
If String.Compare(t(2), tt(2)) = 0 Then
trouve = 1
End If
Loop
If (trouve = 1) Then
MsgBox("user existant")
Else
sw.WriteLine(ch)
Me.Hide()
Form4.Show()
End If
sw.Close()
sr.Close()
fs.Close()
End Sub
If String.Compare(t(2), tt(2)) = 0 Then I get:
IndexOutOfRangeException was unhandled / Index was outside the bounds of the array.
Streams need to be disposed. Instead of using streams you can easily access a text file with the .net File class.
File.ReadAllLines returns an array of lines in the file. We can loop through the lines in a For Each. The lower case c following the "#" tells the compiler that you intend a Char not a String. String.Split expects a Char. Normally, String.Compare is used to order strings in alphabetical order. You just need an =. As soon as we find a match we exit the loop with Exit For.
We don't actually need the array of the text boxes Text property unless there is no match. Putting the elements in braces intializes and fills the array of String.
File.AppendAllLines does what it says. It is expecting an array of strings. As with the text boxes, we put our line to append in braces.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim p = "path to file"
Dim lines = File.ReadAllLines(p)
Dim trouve As Integer
For Each line In lines
Dim thirdField = line.Split("#"c)(2)
If thirdField = TextBox3.Text Then
trouve = 1
Exit For
End If
Next
If trouve = 1 Then
MsgBox("user existant")
Else
Dim tt = {TextBox1.Text, TextBox2.Text, TextBox3.Text, TextBox4.Text, TextBox5.Text}
File.AppendAllLines(p, {String.Join("#", tt)})
Me.Hid3e()
Form4.Show()
End If
End Sub

Checks The Informations In Text File. VB.NET

I work on a project "SignInLogeIn" using Visual Basic.NET.
I save the user informations in text file.
the name of the file is "data.txt".
to create a new account in my program. you must enter the name,email,password and the program write the informations in textfile.
i use "Streamwritter" to write the informations.
when user create a new account The program checks if the email entered by the user is already in the text file that contains the users' information.
and the program checks from informations by "StreamReader". it reads the information in text file and checks.
I have the problem.
when I CREATE A new account. problem appears.
and the problem is
"
An unhandled exception of type 'System.IO.IOException' occurred in mscorlib.dll
Additional information: The process cannot access the file 'D:\1- Anas Files\Projects\VisualBasic.NET\SignInLogIn\SignInLogIn\SignInLogIn\bin\Debug\Data.txt' because it is being used by another process.
"
I think the problem is that I used the file twice
Once to write and once to read.
The error occurs in this line "Dim sw As New StreamWriter("Data.txt")".
how can i solve this problem ?
this is the code of "SignIn" button
Private Sub btnSignIn_Click(sender As Object, e As EventArgs) Handles btnSignIn.Click
Dim strEmail As String = txtEmail.Text
Dim Reg As New Regex("^\w+([-_.]\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*$")
If txtUserName.Text.Trim() = "" Or txtEmail.Text.Trim() = "" Or txtPassword.Text.Trim() = "" Then
MsgBox("Please Enter All Input")
If Not Reg.IsMatch(strEmail) Then
MsgBox("Please Enter Email")
End If
Else
Dim sr As New StreamReader("Data.txt")
Dim sw As New StreamWriter("Data.txt")
Dim strPerson As String = txtUserName.Text & ";" & txtEmail.Text & ";" & txtPassword.Text
Dim line As String = ""
Do
line = sr.ReadLine()
Dim arrData As String() = line.Split(";")
If arrData(1) = strEmail Then
MsgBox("Please Change Email")
Else
sw.WriteLine(strPerson)
sw.Close()
End If
Loop While line <> Nothing
sr.Close()
End If
End Sub
You open twice the same file. First, to read and second to write, this is why you cannot write.
Dim sr As New StreamReader("Data.txt")
Dim lines As String = sr.ReadToEnd().Split(Environment.NewLine)
sr.Close()
Dim strPerson As String = txtUserName.Text & ";" & txtEmail.Text & ";" & txtPassword.Text
Dim sw As New StreamWriter("Data.txt")
For Each line As String In lines
Dim arrData As String() = line.Split(";")
If arrData(1) = strEmail Then
MsgBox("Please Change Email")
Exit For
Else
sw.WriteLine(strPerson)
Exit For
End If
Next
sw.Close()
Streams need to be closed and disposed. They are usually put in Using blocks.
I wasn't quite sure of the program flow you wanted. It seemed, since you created a writer and a reader you intended to add to user to the file if they were not listed.
I broke out some of the code into separate methods. I used System.IO since we have a simple text file.
Private Sub btnSignIn_Click(sender As Object, e As EventArgs) Handles btnSignIn.Click
If ValidInput() Then
Dim strPerson As String = $"{txtUserName.Text};{txtEmail.Text};{txtPassword.Text}"
If Not IsUserInFile(strPerson) Then
File.AppendAllText("Data.txt", strPerson & Environment.NewLine)
End If
End If
End Sub
Private Function ValidInput() As Boolean
Dim strEmail As String = txtEmail.Text
Dim Reg As New Regex("^\w+([-_.]\w+)*#\w+([-.]\w+)*\.\w+([-.]\w+)*$")
If txtUserName.Text.Trim() = "" OrElse txtEmail.Text.Trim() = "" OrElse txtPassword.Text.Trim() = "" Then
MsgBox("Please Enter All Input")
Return False
If Not Reg.IsMatch(strEmail) Then
MsgBox("Please Enter Email")
Return False
End If
End If
Return True
End Function
Private Function IsUserInFile(Person As String) As Boolean
Dim p = Person.Split(";"c)
Dim lines = File.ReadAllLines("Data.txt")
For Each line In lines
If Person = line Then
Return True
End If
Dim fields = line.Split(";"c)
If fields(0) = p(0) AndAlso fields(2) = p(2) AndAlso fields(1) <> p(1) Then
MessageBox.Show("Please Change Email")
Return False
End If
Next
Return False
End Function
This is going to get messy and slow if there are too many users. This info should really be in a database. The worst thing is the passwords should always be salted and hashed; never stored as plain text even is a database.

UltraWinGrid deletes top record rather than the selected one

I've got an ultrawingrid that I can select rows on, and need to be able to delete the highlighted row. At the moment, it calls the database SQL query that I wrote but instead of deleting the record in the row I selected, it deletes the record in the top row instead. Can anybody work out why?
Private Sub btnDeleteIncident_Click(sender As Object, e As EventArgs) Handles btnDeleteIncident.Click
Try
Dim rowValue = ugHistory.Selected.Rows
Dim rowToDelete = ugHistory.Rows(0).Cells(0).Value.ToString
Dim removeIncident As MsgBoxResult
removeIncident = MsgBox("Are you sure you wish to delete this incident?", MsgBoxStyle.Question + MsgBoxStyle.YesNo, "Confirm")
If removeIncident = MsgBoxResult.Yes Then
Database.deleteIncident(rowToDelete)
txtClientSave.Text = ""
rtbProblem.Text = ""
rtbSolution.Text = ""
dtpStart.Value = Date.Today
dtpEnd.Value = Date.Today
dtpStartTime.Value = DateTime.Now
dtpEndTime.Value = DateTime.Now
cboxSolved.Checked = False
btnUpdate.Hide()
btnSave.Show()
ElseIf removeIncident = MsgBoxResult.No Then
loadIncidents()
End If
Catch Ex As Exception
MsgBox("No incidents to delete")
End Try
loadIncidents()
End Sub
Database SQL query;
Public Shared Sub deleteIncident(ByVal supportID As Integer)
Connect()
Dim Dc As New OleDbCommand
Dc.Connection = Con
Dc.CommandText = "DELETE * FROM tblIncidents WHERE([supportID] = " & supportID & ")"
Dc.ExecuteNonQuery()
Disconnect()
End Sub
You are taking the value for rowToDelete from the first row of the grid not from the current active row
I suggest you to change this line
Dim rowToDelete = ugHistory.Rows(0).Cells(0).Value.ToString
to
Dim rowToDelete = ugHistory.ActiveRow.Cells(0).Value.ToString
Also, it is always better to follow a safe approach when handling reference objects like 'ActiveRow', so before running your code add a test for a valid
ActiveRow
if ugHistory.ActiveRow Is Nothing Then
Return
End If
Dim rowToDelete = ugHistory.ActiveRow.Cells(0).Value.ToString

How to replace multiple consective lines in a line and skip the header for that section

I need to find a section header, in this case "[Store Hours]", in a text file that I'm using to save the settings for the program. I need to skip the header and replace the next 7 lines with the text that is in the text boxes. The code below currently deletes the header "[Store Hours]" and does not replace any of the lines.
Dim objFileName As String = "Settings.txt"
Private Sub BtnAdd_Click(sender As System.Object, e As System.EventArgs) Handles btnSaveHours.Click
Dim OutPutLine As New List(Of String)()
Dim matchFound As Boolean
For Each line As String In System.IO.File.ReadAllLines(objFileName)
matchFound = line.Contains("[Store Hours]")
If matchFound Then
'does not skip the header line
line.Skip(line.Length)
'Need to loop through this 7 times (for each day of the week)
'without reading the header again
For intCount = 0 To 6
Dim aryLabelDay() As String = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}
Dim varLabelNameIn As String = "txt" & aryLabelDay(intCount).ToString & "In"
Dim varDropNameIn As String = "drp" & aryLabelDay(intCount).ToString & "In"
Dim varLabelNameOut As String = "txt" & aryLabelDay(intCount).ToString & "Out"
Dim varDropNameOut As String = "drp" & aryLabelDay(intCount).ToString & "Out"
Dim varTextBoxInControl() As Control = Me.Controls.Find(varLabelNameIn, True)
Dim varDropBoxInControl() As Control = Me.Controls.Find(varDropNameIn, True)
Dim varTextBoxOutControl() As Control = Me.Controls.Find(varLabelNameOut, True)
Dim varDropBoxOutControl() As Control = Me.Controls.Find(varDropNameOut, True)
Dim dymTextNameIn As TextBox = DirectCast(varTextBoxInControl(0), TextBox)
Dim dymDropNameIn As ComboBox = DirectCast(varDropBoxInControl(0), ComboBox)
Dim dymTextNameOut As TextBox = DirectCast(varTextBoxOutControl(0), TextBox)
Dim dymDropNameOut As ComboBox = DirectCast(varDropBoxOutControl(0), ComboBox)
Dim ReplaceLine As String
ReplaceLine = dymTextNameIn.Text & "," & dymDropNameIn.Text & "," & dymTextNameOut.Text & "," & dymDropNameOut.Text
'this doesn't replace anything
line.Replace(line, ReplaceLine)
intCount += 1
Next intCount
Else
OutPutLine.Add(line)
End If
Next
End Sub
Instead of using ReadAllLines simply use a streamreader and read the file line by line, like this;
Dim line As String
Using reader As StreamReader = New StreamReader("file.txt")
' Read one line from file
line = reader.ReadLine
If(line.Contains("[Store Hours]") Then
'The current line is the store hours header, so we skip it (read the next line)
line = reader.ReadLine
'Process the line like you want, and keep processing through the lines by doing a readline each time you want to progress to the next line.
End If
End Using
More importantly though, you should not be saving the settings for your program in a text file. They should be stored in app.config or web.config. See this question for further guidance on that.
Part of your confusion might be coming from the fact that you can't just replace part of a text file without copying it and overwriting it. One way, to do this, is to copy the file to memory changing the appropriate lines and overwriting the existing file with the new information. Here's one way that can be done:
Private Sub BtnAdd_Click(sender As System.Object, e As System.EventArgs) Handles btnSaveHours.Click
Dim OutPutLine As New List(Of String)()
Dim sr As New StreamReader(objFileName)
While Not sr.EndOfStream
Dim line = sr.ReadLine
'Found the header so let's save that line to memory and add all the other _
info after it.
If line.Contains("[Store Hours]") Then
OutPutLine.Add(line)
'Need to loop through this 7 times (for each day of the week)
'without reading the header again
Dim aryLabelDay() As String = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}
For intCount = 0 To 6
'even though we're not using the info from the file, calling _
Readline advances the file pointer so that the next iteration _
of the while loop we can finish reading the file.
If Not sr.EndOfStream Then
line = sr.ReadLine
Dim dymTextNameIn As TextBox = DirectCast(Me.Controls("txt" & aryLabelDay(intCount) & "In"), TextBox)
Dim dymDropNameIn As ComboBox = DirectCast(Me.Controls("drp" & aryLabelDay(intCount) & "In"), ComboBox)
Dim dymTextNameOut As TextBox = DirectCast(Me.Controls("txt" & aryLabelDay(intCount) & "Out"), TextBox)
Dim dymDropNameOut As ComboBox = DirectCast(Me.Controls("drp" & aryLabelDay(intCount) & "Out"), ComboBox)
OutPutLine.Add(dymTextNameIn.Text & "," & dymDropNameIn.Text & "," & dymTextNameOut.Text & "," & dymDropNameOut.Text)
End If
Next
Else
'Any line that isn't in that section gets copied as is.
OutPutLine.Add(line)
End If
End While
'Copy all the new info to the same file overwriting the old info.
File.WriteAllLines(objFileName, OutPutLine)
End Sub
On a side note. The Controls collection is indexed by number or name which makes it fairly simple to access the appropriate control just by knowing its name.
Thanks for the help I actually figured it out and this is the final code I used
Private Sub btnSaveHours_Click(sender As System.Object, e As System.EventArgs) Handles btnSaveHours.Click
Dim intOutPutLine As New List(Of String)()
Dim blnSearchString As Boolean
Dim intLineCount As Integer = -1
Dim intLoopCount As Integer
For Each line As String In System.IO.File.ReadAllLines(objFileName)
blnSearchString = line.Contains("[Store Hours]")
If blnSearchString Then
intLineCount = intOutPutLine.Count
line.Remove(0)
intLoopCount = 0
ElseIf intLineCount = intOutPutLine.Count And intLoopCount < 7 Then
line.Length.ToString()
line.Remove(0)
intLoopCount += 1
Else
intOutPutLine.Add(line)
End If
Next
System.IO.File.WriteAllLines(objFileName, intOutPutLine.ToArray())
Dim objFileWrite As New StreamWriter(objFileName, True)
If File.Exists(objFileName) Then
objFileWrite.WriteLine("[Store Hours]")
Dim varMe As Control = Me
Call subConvertFrom12to24Hours(objFileWrite, varMe)
Else
objFileWrite.WriteLine("[Store Hours]")
Dim varMe As Control = Me
Call subConvertFrom12to24Hours(objFileWrite, varMe)
End If
Call btnClear_Click(sender, e)
End Sub

How to read duplicate string in a text file in vb.net

I want this program to open a text file and find those specific character and add the words after that into the list (each character has specific subitem in the list).
It work well if there is no duplication. But if I have list like:
/* First row of the list */
#Alireza
%Human
&1
#$1200
$*1
*$1000
/* ' Second row */
#Behzad
%Human
&1
#$1340
$*1
*$1000
/* ' And third row */
#Samaneh
%Human
&1
#$1570
$*1
*$1230
then it only add the first row. I also make a while loop but it will only add first row to other rows. Is there anyone can help please!(by the way my list include 6 columns )
this is the code:
Public code As String
Public cat As String
Public stock As Integer
Public price As Double
Public sold As Double
Public cost As Double
Public i As Integer
Public Sub _Load(ByVal FileName As String)
Dim strLines() As String
Dim strLine As String
Dim strData As String
Dim objFileInfo As New FileInfo(FileName)
strData = My.Computer.FileSystem.ReadAllText(FileName)
strLines = strData.Split(New String() {ControlChars.CrLf}, StringSplitOptions.RemoveEmptyEntries)
For Each strLine In strLines
If strLine.StartsWith("#") Then
code = strLine.Substring(1)
End If
strLine = Nothing
Next
For Each strLine In strLines
If strLine.StartsWith("%") Then
cat = strLine.Substring(1)
Exit For
End If
strLine = Nothing
Next
For Each strLine In strLines
If strLine.StartsWith("&") Then
stock = strLine.Substring(1)
Exit For
End If
strLine = Nothing
Next
For Each strLine In strLines
If strLine.StartsWith("#$") Then
price = strLine.Substring(2)
Exit For
End If
strLine = Nothing
Next
For Each strLine In strLines
If strLine.StartsWith("$*") Then
sold = strLine.Substring(2)
Exit For
End If
strLine = Nothing
Next
For Each strLine In strLines
If strLine.StartsWith("*$") Then
cost = strLine.Substring(2)
Exit For
End If
strLine = Nothing
Next
End Sub
Private Sub button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles toolImport.Click
Dim ans As String
OpenFileDialog1.Title = "What are you looking for?"
OpenFileDialog1.InitialDirectory = Application.StartupPath
OpenFileDialog1.Filter = "text Files (*.txt)|*.txt|Data Files (*.dat)|*.dat|All files (*.*)|*.*"
OpenFileDialog1.FileName = "myList"
Try
If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
Dim sr As StreamReader = New StreamReader(OpenFileDialog1.FileName)
Do While sr.Peek > -1
_Load(OpenFileDialog1.FileName)
Dim list As New ListViewItem(code)
list.SubItems.Add(cat)
list.SubItems.Add(stock)
list.SubItems.Add(price)
list.SubItems.Add(sold)
list.SubItems.Add(cost)
listClothes.Items.Add(list)
i += 1
MessageBox.Show("Your list has been uploaded successfully", "ccc!", MessageBoxButtons.OK, MessageBoxIcon.Information)
Loop
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
By "duplicate strings", I think you mean how to read the file when there is more than one item (group of 6 columns) in the file.
The reason your current program is getting only the first item is because you're exiting the For loop after you find the first occurrence of a given sub item, regardless of how many there may be in the file.
One way to resolve this is to change your sub _Load to a function and have it return a List(Of ListViewItem) object, which you could then iterate through and add to the master list (ListClothes). I would also get rid of the StreamReader, as you don't need it for what you are doing. You're passing the FileName property (which contains the path and extensions) from the OpenFileDialog, so you can simply use that in the _Load function.
It would look something like this:
Public Function _Load(ByVal FileName As String) As List(Of ListViewItem)
Dim Lines() As String
Dim List(Of ListViewItem) StockList = New List(Of ListViewItem)
Dim ListViewItem As StockItem
Lines = File.ReadAllText(FileName).Split(New String() _
{ ControlChars.CrLf}, StringSplitOptions.RemoveEmptyEntries)
For j = 0 To Lines.Length - 1 Step 6
StockItem = New ListViewItem(Lines(j))
StockItem.SubItems.Add(Lines(j + 1))
StockItem.SubItems.Add(Lines(J + 2))
StockItem.SubItems.Add(Lines(j + 3))
StockItem.SubItems.Add(Lines(J + 4))
StockItem.SubItems.Add(Lines(j + 5))
StockList.Add(StockItem)
Next
Return StockList
End Function
The above code takes the passed in FileName, does a split on the string returned from ReadAllText and removes empty entries.
Next it loops through code, 6 lines at a time. In the loop a new ListViewItem is created, and the sub items are populated, and then this ListViewItem is added to the List(Of ListViewItem).
The populated StockList is then returned.
In your button1_Click event, you could use it like this:
Private Sub button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles toolImport.Click
Dim ans As String
Dim stockItems As List(Of ListViewItem)
OpenFileDialog1.Title = "What are you looking for?"
OpenFileDialog1.InitialDirectory = Application.StartupPath
OpenFileDialog1.Filter = "text Files (*.txt)|*.txt|Data Files (*.dat)|*.dat|All files (*.*)|*.*"
OpenFileDialog1.FileName = "myList"
Try
If OpenFileDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then
stockItems = _Load(OpenFileDialog1.FileName)
For Each (stockItem As ListViewItem in stockItems)
listClothes.Add(stockItem)
Next
MessageBox.Show("Your list has been uploaded successfully", "ccc!", MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
In this code, you pass the selected FileName to the _Load method and assign its return value to the local stockItems variable.
Then you loop through the stockItems list, and add each ListViewItem in it to your clothesList.
NOTE that this code is brittle - if the columns are not in the correct order in the input file, or if a column(s) is/are missing, your data will be skewed, and the program could potentially crash if you try to read a line in the array (from the file) that doesn't exist. Of course, you can wrap that code in a Try Catch block as well.
This is merely one way to do it - I have no doubt there are others. But this should at least get you going in the right direction.
EDIT
The easiest way to remove the leading characters is to add them to the split, like this:
Lines = File.ReadAllText(FileName).Split(New String() _
{ ControlChars.CrLf, "#", "%", "&", "#$", "$*", "*$"}, _
StringSplitOptions.RemoveEmptyEntries)
This will return an array of all the lines, minus empty lines and the leading characters.
Of course, with the code above, you actually don't need those leading characters anymore, as long as the input file always has the columns in the same order.