Finding width of each line in richtextbox where wordwrap is true - vb.net

I have a richtextbox and i have put a long sentences. Its wordwrap is on. Because of this it shows 4 lines. I want to show the width of each line separately.
I have tried with richtextbox1.lines.length, but it is showing: 1

I have tested this code briefly and I think that it does what you want. It will include carriage return and line break characters in the count I think, so you will have to handle that explicitly if you need different.
Dim previousFirstCharIndex = 0
Dim lineIndex = 1
Dim firstCharIndex = RichTextBox1.GetFirstCharIndexFromLine(lineIndex)
Dim lineLengths As New List(Of Integer)
Do Until firstCharIndex = -1
lineLengths.Add(firstCharIndex - previousFirstCharIndex)
previousFirstCharIndex = firstCharIndex
lineIndex += 1
firstCharIndex = RichTextBox1.GetFirstCharIndexFromLine(lineIndex)
Loop
lineLengths.Add(RichTextBox1.TextLength - previousFirstCharIndex)
MessageBox.Show(String.Join(Environment.NewLine, lineLengths), "Line Lengths")

Related

Gettint text from lastline in richtextbox

I want to copy the last line of a rich textbox.
I am avoiding Dim lastLine As String = RichTextBox1.Lines(RichTextBox1.Lines.Length - 1)as
it's not working properly, as It works just if there are atleast 2 lines in it.
I'm trying with MsgBox(RichTextBox1.Lines(UBound(richtextbox1.Lines))) but the problem is that even if the richtextbox has just 1 line of text but the cursor is in the second empty line, it will give back "" as I think the software is reading the empty 2nd line.
There is a solution to that?
Thanks
This will get the last non-empty line:
RichTextBox1.Lines.Where(Function(line) line <> String.Empty).Last()
There are some potential issues with that. If there's no text at all or if there are multiple lines but they are all empty, that will throw an exception. To allow for that, you can call LastOrDefault instead, in which case it would return Nothing.
If you only want to exclude the last empty line, e.g. if you have some text followed by a line break and then another line break then you want to get the first of those two empty lines, then you can't really do it in one line:
Dim lines = RichTextBox1.Lines
Dim upperBound = lines.GetUpperBound(0)
Dim lastLine = lines(upperBound)
If lastLine = String.Empty Then
If upperBound > 0 Then
lastLine = lines(upperBound - 1)
Else
lastLine = Nothing
End If
End If
'Use lastLine here.

How do you delete empty lines from a textfile

I am trying to delete empty lines from a textfile using vb.net. This is an example of what I have tried so far however it is not working as expected:
Dim i As Integer = 0
Dim CountDeleted = 0
Dim TextString As String
For Each Line As String In lines
TextString = lines(i)
If TextString.Trim = "" Then
lines.RemoveAt(i)
CountDeleted += 1
End If
i += 1
Next Line
This is an example of the data within a textfile that I would like to remove the lines from:
BUSINESS_UNIT|PO_ID|LINE_NBR|CANCEL_STATUS|
A
B
C
Required output:
BUSINESS_UNIT|PO_ID|LINE_NBR|CANCEL_STATUS|
A
B
C
Any help would be much appreciated
To remove all the blank lines is just one line of code with linq
Dim nonBlank = lines.Where(Function(x) Not String.IsNullOrWhiteSpace(x))
Counting the removed is just a difference between elements in the two lists
Dim CountDeleted = lines.Count - nonBlank.Count
Your code will trigger a runtime exception because you are removing an item from the same collection that you enumerate with the For Each loop.
You could switch to an old fashioned For Next loop but be careful to start from the end of the collection and examine the strings toward the beginning of the collection.
For i = lines.Count - 1 To 0 Step - 1
TextString = lines(i)
If string.IsNullOrWhiteSpace() Then
lines.RemoveAt(i)
CountDeleted += 1
End If
Next
This backward loop is required because when you remove an item from the collection the total items count decrease and the items following the current index will slide one position. A normal (forward) loop will skip to examine the item following the one deleted.
To remove all WhiteSpace strings from List(Of String):
lines.RemoveAll(addressOf String.IsNullOrWhiteSpace)
To remove all WhiteSpace lines from a text file:
File.WriteAllText(path, Regex.Replace(File.ReadAllText(path), "(?m)^\s+^", ""))

Read part of text file using VB.net

I am new to VB.net and I need help.
What I want to do is read lines from a text file that take place between two specific lines. Within these lines I have to look for a specific one and display the next line, if that makes any sense. The catch is that there are more than one pair of these marker lines that contain the exact lines that I need within them. I hope the explanation is clear enough for you guys! Is that possible?
I am looking for the line under the number 10 in the parts of the text file shown on the screenshot. Since there are a lot of 10s in that file I need to read it on parts in order to get the exact line needed.
The code below is what I have so far thanks to #TimSchmelter in my previous question Read certain line in text file and display the next. Which is actually the bit that looks for a specific line and displays the next one, but it reads all of the lines within that text file.
Dim x1 As Decimal = File.ReadLines("filepath").
SkipWhile(Function(line) Not line.Contains(" 10")).Skip(1).FirstOrDefault()
If x1 >= 0.0 Then TextBox1.Text = x1
Your original code was the best since it allowed you to have better control over what you read and whatnot, so I'm going to use that in my answer.
The LINQ approach will only give you the first instance of what you're looking for, therefore it is better to read though the whole file line-by-line.
First, a structure holding the coordinates of a line:
Public Structure Line
Public Start As PointF 'Start coordinates.
Public [End] As PointF 'End coordinates.
Public Sub New(ByVal Start As PointF, ByVal [End] As PointF)
Me.Start = Start
Me.End = [End]
End Sub
Public Sub New(ByVal x1 As Single, ByVal y1 As Single, ByVal x2 As Single, ByVal y2 As Single)
Me.New(New PointF(x1, y1), New PointF(x2, y2))
End Sub
End Structure
We will use this structure so that we can return a list of all lines we've found.
This will read the file line-by-line and look for our wanted values:
EDIT: I've updated the code to make it properly read the coordinates (i.e. it is no longer bound by the order: 10, 20, 11, 21).
I have also made it only read coordinates located inside AcDbLine/LINE blocks.
Public Function ParseLines(ByVal File As String) As List(Of Line)
'Create a list of Line structures.
Dim Lines As New List(Of Line)
'Create an array holding four items: the coordinates for 10, 20, 11 and 21.
Dim CoordValues As Single() = New Single(4 - 1) {}
'Declare a variable holding the current index in the array:
'CoordIndex = 0 represents the first X-coordinate (10).
'CoordIndex = 1 represents the first Y-coordinate (20).
'CoordIndex = 2 represents the second X-coordinate (11).
'CoordIndex = 3 represents the second Y-coordinate (21).
Dim CoordIndex As Integer = 0
'Declare a variable indicating whether we are currently inside an AcDbLine/LINE block.
Dim InsideAcDbLine As Boolean = False
Using sReader As New StreamReader(File) 'Open a StreamReader to our file.
While Not sReader.EndOfStream 'Keep reading until we've reached the end of the file.
Dim line As String = sReader.ReadLine() 'Read a line.
'Check if we're inside a AcDbLine/LINE block and that we aren't at the end of the file.
If InsideAcDbLine = True AndAlso Not sReader.EndOfStream Then
'Determine if the current line contains 10, 20, 11 or 21.
'Depending on what "line.Trim()" returns it will execute the code of the respective "Case".
'Ex: If "line.Trim()" returns "20" it will execute the code of 'Case "20"', which is 'CoordIndex = 1'.
Select Case line.Trim() 'Trim() removes leading or trailing space characters from the string (i.e. " 10" -> "10").
Case "10" : CoordIndex = 0 'We've reached "10", the following line is coordinate x1.
Case "20" : CoordIndex = 1 'We've reached "20", the following line is coordinate y1.
Case "11" : CoordIndex = 2 '[...] x2.
Case "21" : CoordIndex = 3 '[...] y2.
Case Else : Continue While
' "Continue While" stops execution at this point and
' goes back to the beginning of the loop to: "Dim line As String = ...".
'
' - If "line.Trim()" DOES NOT return 10, 20, 11 or 21 then we
' just want to skip the rest of the code (in other words: ignore the current line).
End Select
'I used colons above for better readability as they can be used to replace line breaks.
'For example the above SHOULD ACTUALLY be:
'
'Select Case line.Trim()
' Case "10"
' CoordIndex = 0
' Case "11"
' (and so on)
'=========================================
Dim nextLine As String = sReader.ReadLine() 'Read the next line.
Dim Coordinate As Single 'Declare a variable for the current coordinate.
'Try parsing the line into a single using
'invariant culture settings (decimal points must be dots: '.').
If Single.TryParse(nextLine.Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, Coordinate) = True Then
CoordValues(CoordIndex) = Coordinate 'Add the coordinate to the array.
If CoordIndex = CoordValues.Length - 1 Then 'Have we reached the end of the array?
InsideAcDbLine = False 'We've found all values we want. Do not look for any more in this block.
Lines.Add(New Line(CoordValues(0), CoordValues(1), CoordValues(2), CoordValues(3))) 'Create a new Line and set its coordinates to the values of 10, 20, 11 and 21.
Array.Clear(CoordValues, 0, CoordValues.Length) 'Set all the items in the array to zero.
End If
End If
End If
'Check if we've reached an "AcDbLine" or "LINE" marker.
'Used in order to determine whether we are inside a AcDbLine/LINE block.
'If we aren't, then we shouldn't look for any coordinates.
Select Case line.Trim()
Case "AcDbLine" : InsideAcDbLine = True 'Start of an AcDbLine/LINE block.
Case "LINE" : InsideAcDbLine = False 'End of an AcDbLine/LINE block.
End Select
End While
End Using
Return Lines 'Return our list of lines.
End Function
This code will only add a new line to the list once it has found four different coordinates, i.e. if it at the end only finds x1, y1 and x2 (but not y2) it will just ignore those values.
Here's how you can use it:
Dim Lines As List(Of Line) = ParseLines("filepath")
'Iterate through every parsed line.
For Each Line As Line In Lines
'Print all parsed lines to console in the format of:
'Line start: {X=x1, Y=y1}
'Line end: {X=x2, Y=y2}
Console.WriteLine("Line start: " & Line.Start.ToString())
Console.WriteLine("Line end: " & Line.End.ToString())
Console.WriteLine()
Next
To get individual coordinates of a line you can do (assuming you're still using the loop above):
Dim StartX As Single = Line.Start.X
Dim StartY As Single = Line.Start.Y
Dim EndX As Single = Line.End.X
Dim EndY As Single = Line.End.Y
If you want to access individual lines without a loop you can do:
Dim Line As Line = Lines(0) '0 is the first found line, 1 is the second (and so on).
Documentation:
List(Of T) class
PointF class
How to: Declare a Structure (Visual Basic)
Arrays in Visual Basic
Single Data Type (Visual Basic)
Single.TryParse() method
Select Case statement

replace a line in richtextbox vb.net

I have this code but it have errors , what should i do ?
Dim lines As New List(Of String)
lines = RichTextBox1.Lines.ToList
'Dim FilterText = "#"
For i As Integer = lines.Count - 1 To 0 Step -1
'If (lines(i).Contains(FilterText)) Then
RichTextBox1.Lines(i) = RichTextBox1.Lines(i).Replace("#", "#sometext")
'End If
Next
RichTextBox1.Lines = lines.ToArray
Update: while the following "works" it does only modify the array which was returned from the Lines-property. If you change that array you don't change the text of the TextBox. So you need to re-assign the whole array to the Lines-property if you want to change the text(as shown below). So i keep the first part of my answer only because it fixes the syntax not the real issue.
It's not
RichTextBox1.Lines(i).Replace = "#sometext"
but
RichTextBox1.Lines(i) = "#sometext"
You can loop the Lines forward, the reverse loop is not needed here.
Maybe you want to replace all "#" with "#sometext" instead:
RichTextBox1.Lines(i) = RichTextBox1.Lines(i).Replace("#","#sometext")
So here the full code necessary (since it still seems to be a problem):
Dim newLines As New List(Of String)
For i As Integer = 0 To RichTextBox1.Lines.Length - 1
newLines.Add(RichTextBox1.Lines(i).Replace("#", "#sometext"))
Next
RichTextBox1.Lines = newLines.ToArray()
But maybe you could even use:
RichTextBox1.Text = RichTextBox1.Text.Replace("#","#sometext")`
because if we have # abcd this code change it to # sometextabcd ! I
Want a code to replace for example line 1 completely to # sometext
Please provide all relevant informations in the first place next time:
Dim newLines As New List(Of String)
For Each line As String In RichTextBox1.Lines
Dim newLine = If(line.Contains("#"), "#sometext", line)
newLines.Add(newLine)
Next
RichTextBox1.Lines = newLines.ToArray()

How to change my code to work a certain number of times?

My code gets a list of words from a txt file and chooses the words randomly. However, the same word can appear more than once and i need to know how to stop this from happening?
Here is the code:
Dim aryName As String() = Nothing
aryName = File.ReadAllLines(Application.StartupPath & "\Random\fnames.txt")
Dim randomWords As New List(Of String)
For i = 0 To aryName.Length - 1
If randomWords.Contains(aryName(i)) = False Then
randomWords.Add(aryName(i))
End If
Next
Dim random As New Random
Label2.Text = (randomWords(random.Next(0, randomWords.Count - 1)).ToString)
Maybe this might work, although it's in english and not code :(
if label1.text is changed then
Get label1.text
if label.text becomes this word again then
run the random code
end if
end if
This should prevent immediate repeats:
Dim random As New Random
'Just create a temporary holder for comparison
Dim word As String = Label2.Text
'Run a while loop that works as long as there
'is no change to the word. This should prevent
'back to back repeats.
While word = Label2.Text
word = (randomWords(random.Next(0, randomWords.Count - 1)).ToString)
End While
Label2.Text = word
If you don't want it to repeat ever again, you should probably remove the used word from the randomWords List.
Dim random As New Random
Label2.Text = (randomWords(random.Next(0, randomWords.Count - 1)).ToString)
randomWords.Remove(Label2.Text)
You can a) remove the selected word from the list, or b) you can random sort the list first.
Option a) is already addressed in another answer
Option b) lets you retain all the words in memory. Here is the code:
Dim randomWords As New List(Of String)(File.ReadAllLines(Application.StartupPath & "\Random\fnames.txt"))
Dim random As New Random
randomWords.Sort(Function(s1 As String, s2 As String) random.Next(-1, 1))
For index As Integer = 0 To randomWords.Count - 1
Label2.Text = randomWords(index)
Next
Modify your For loop to prevent dupes in aryName from getting into randomWords:
For i = 0 To aryName.Length - 1
If randomWords.Contains(aryName(i)) = False Then
randomWords.Add(aryName(i))
End If
Next