RichTextBox Highlighting - vb.net

Goal
Programmatically highlight part of a string contained in a RichTextBox based on what is selected in a DataGridView.
See screenshot for a more visual example
As you can see, when an Option type (EC - Electrical) is selected, its options are displayed in another DataGridView to the right. From there, the user can check the ones he wishes to have included in the Conveyor Function Summary (Photoeye in this case) and it gets highlighted.
Code Used
This method is executed every time the Option Type DataGridView has a selectionchanged event.
Private Sub SummaryOptionsHighlight()
Dim strToFind As String = ""
Dim textEnd As Integer = rtbSummary.TextLength
Dim index As Integer = 0
Dim lastIndex As Integer = 0
'Builds the string to find based on custom classes - works fine
For Each o As clsConveyorFunctionOptions In lst_Options
If o.Included Then
If strToFind.Length <> 0 Then strToFind += ", "
If o.Optn.IsMultipleQty And o.Qty > 0 Then
strToFind += o.Optn.Description & " (" & o.Qty & "x)"
Else
strToFind += o.Optn.Description
End If
End If
Next
'Retrieves the last index of the found string: ex. Photoeye (3x)
lastIndex = rtbSummary.Text.LastIndexOf(strToFind)
'Find and set the selection back color of the RichTextBox
While index < lastIndex
rtbSummary.Find(strToFind, index, textEnd, RichTextBoxFinds.None)
rtbSummary.SelectionBackColor = SystemColors.Highlight
index = rtbSummary.Text.IndexOf(strToFind, index) + 1
End While
End Sub
Problem
What's going on isn't a highlight but more of a backcolor being set to that selection. The reason I say this is because when I click in the RichTextBox to indicate that it has focus, it doesn't clear the highlighting. Perhaps there is an actual highlight instead of a backcolor selection?
See the difference:
Selection Back Color:
Highlighting:

to highlight, you just need to do this:
if richtextbox1.text.contians("photoeye") then
richtextbox1.select("photoeye")
end if
this should work for what you are trying to do

Related

MS Access: Multi ListBox get values

I have a listbox on a form that contains 6 values. The user is allowed to select multiple values at once. For each value selected I want to assign this value to a variable.
My listbox is called: lstFilterUnits
The listbox contents are as follows:
Blue, Red, Green, Yellow, Orange, White
I understand that the following is associated with each colour:
Forms("Form1").lstFilterUnits.Selected(0) 'Blue Selected
Forms("Form1").lstFilterUnits.Selected(1) 'Red Selected
Forms("Form1").lstFilterUnits.Selected(2) 'Green Selected
Forms("Form1").lstFilterUnits.Selected(3) 'Yellow Selected
Forms("Form1").lstFilterUnits.Selected(4) 'Orange Selected
Forms("Form1").lstFilterUnits.Selected(5) 'White Selected
I have attempted to do this using the below code in the listbox on click event:
As you can see I had to hard code the value assigned to the vUnit variable as anytime I try get the value associated with the list box with either of the lines commented out it doesn't work.
Dim vUnit As String
If Forms("Form1").lstFilterUnits.Selected(0) = True Then
vUnit = "Blue
MsgBox (vUnit)
'MsgBox "You selected " & lstFilterUnits.Value 'Returns null value
'MsgBox "You selected " & lstFilterBusinessUnits.SelectedValue 'Returns Compile error
ElseIf Forms("Form1").lstFilterUnits.Selected(1) = True Then
vUnit = vUnit & ", Red'"
MsgBox (vUnit)
End If
So for the above code I can't seem to assign the value associated with the selected item to a variable. I also want to me able to display multiple values in the variable if they are selected, however if I select more than one value using the above method it will only go into the first if statement that is true, due to this I think I should be using some sort of a loop to assign the variable multiple values but I'm new to VBA and d not know how to do this.
Any help would be appreciated, I think this is probably a simple task that I am overthinking.
EDIT:
After searching online I finally found something that is kind of doing what I need. However the output is also outputting the index number of the listbox. The code I found is below. I've tried playing around with it but can't seem to achieve my desired output.
The below code will output the following:
'1 , 'Blue', '2 'Red', 3 ,'Green',
Whereas I want it to output:
'Blue','Red', 'Green',
Does anyone know how I can achieve this? I've tried changing the column to both only i and J and this didn't seem to work. I've never worked with arrays in VBA before so will admit I don't understand the code fully and the form I found it on didn't explain the code, it was just providing a solution for another user.
Dim i As Long
Dim J As Long
Dim Msg As String
Dim arrItems() As String
ReDim arrItems(0 To lstFilterUnits.ColumnCount - 1)
For J = 0 To lstFilterUnits.ListCount - 1
If lstFilterUnits.Selected(J) Then
For i = 0 To lstFilterUnits.ColumnCount - 1
arrItems(i) = lstFilterUnits.Column(i, J)
Next i
Msg = Msg & "'" & Join(arrItems, " , '") & "', "
End If
Next J
MsgBox Msg
Use the .ItemsSelected collection. It already has all the items.
EXAMPLE:
Sub Example()
dim ctl as Control
Set ctl = Forms("Form1").lstFilterUnits
Dim varItm As Variant
For Each varItm In ctl.ItemsSelected
Debug.Print ctl.ItemData(varItm)
Next varItm
End Sub
SOURCE: https://learn.microsoft.com/en-us/office/vba/api/access.listbox.itemsselected
Have a try on it.
Private Sub lstFilterUnits_Click()
Dim ctl As Control
Dim varItm As Variant
Dim SelectedColor As String
Set ctl = Forms!Form1!lstFilterUnits
For Each varItm In ctl.ItemsSelected
SelectedColor = SelectedColor & vbCrLf & ctl.ItemData(varItm) 'This for each color in each line
'SelectedColor = SelectedColor & "," & ctl.ItemData(varItm) ' This line for comma separated color
Next varItm
MsgBox SelectedColor
End Sub

VBA convert textbox entry to an integer

I am trying to convert a textbox entry to an integer:
Dim cplayers() As Variant: cplayers = Array ("Danny", "Freddy", "Billy", "Tommy")
Dim i As Integer
i = CInt(TextBox3)
MsgBox (cplayers(i) & " is on first base.")
When I run it now, the message box always reads "Danny is on first base." so it must be reading the textbox as empty and assuming the entry is 0 then. What should I change?
You can use an ActiveX Text Box to import the value.
To Insert: Developer Tab > Insert > ActiveX Controls > Text Box (ActiveX Control)
You can then extract your value as such:
Option Explicit
Sub Test()
Dim cplayers() As Variant: cplayers = Array("Danny", "Freddy", "Billy", "Tommy")
Dim i As Integer
i = TextBox1.Value
MsgBox cplayers(i) & " is on first base."
End Sub
You could also refer to the object but that would be overkill here.
The field that holds the actual entry for the Textbox seems to be "TextBox3.text"
Dim cplayers() As Variant: cplayers = Array ("Danny", "Freddy", "Billy", "Tommy")
Dim i As Integer
i = CInt(TextBox3.text)
MsgBox (cplayers(i) & " is on first base.")
There is also a check that can help you to prevent wrong inputs in the calculations. You can use isNumeric() to determine if the entered value is a valid number like If IsNumeric(TextBox3.text) Then

How do I display the result of a loop on a new line in a text box?

Basically, how do I write a new line in a text box, keeping the existing information as well.
If I have for loop,
For i As Integer = 1 To 10
Dim result = i
i = i + 1
textbox1.text = result
Next
This will display '10' in the textbox. I want it to be like:
1
2
3
4
...
First, your TextBox must allow multiple lines. This is a property of the textbox control that you can set from the designer or from the code. You may want to ensure that a scroll bar is there to scroll in case the height is not large enough.
If you want to set the properties from code, use this code in the Load event of the form.
' Set the Multiline property to true.
textBox1.Multiline = True
' Add vertical scroll bars to the TextBox control.
textBox1.ScrollBars = ScrollBars.Vertical
' Change the height of the textbox so that it could accomodate the lines
TextBox1.Height = 120
Now, your approach had a major problem in this line:
textbox1.text = result
The way you coded it, every new value of i, would overwrite the old value. What you want to do is to first construct a string, then send the entire string to the TextBox control. This is not required had you been using Console.WriteLine method.
Method 1
Dim s as string
s=""
For i As Integer = 1 To 10
s = s & Environment.Newline & i.ToString() 'we use Environment.NewLine to force new line
Next i
textbox1.text = s
Method 2
.NET offers a class to handle strings better than the way we did before. It won't matter in your case but it is the efficient way to handle concatenation when volume is large and/or performance matters
Dim s as new System.Text.StringBuilder() 'Initialize stringbuilder instance
For i As Integer = 1 To 10
s.AppendLine (i.ToString()) 'We use stringbuilder to concat. and inser line feed
Next i
textbox1.text = s.ToString()
Note: If you want double spacing then you need to add a linefeed (using & ) to both of the above methods.
Something like this should work:
For i As Integer = 1 To 10
if i = 1 then
textbox1.text = i
else
textbox1.text &= vbcrlf & i
end if
Next
For i = 1 To 10
textbox1.AppendText(vbNewLine & i)
Next

Check if listbox contains textbox

I know I could use .FindString for this but for some reason it is not working.
Basically,if listbox items contains just a PART of textbox text,it does action.
Here's the example of not-working code :
Dim x As Integer = -1
x = ListBox1.FindString(TextBox1.Text)
If x > -1 Then
'dont add
ListBox2.Items.Add("String found at " & x.ToString)
Else
End If
The FindString method returns the first item which starts with the search string (MSDN). If you want to match the whole item, you would have to use FindStringExact (MSDN). If you want to perform more complex searches, you would have to iterate through all the elements in the ListBox.
UPDATE:
Code delivering the exact functionality expected by the OP.
For i As Integer = 0 To ListBox1.Items.Count - 1
If (ListBox1.Items(i).ToString.Contains(TextBox1.Text)) Then
ListBox2.Items.Add("String found at " & (i + 1).ToString) 'Indexing is zero-based
Exit For
End If
Next

A way to change font color besides *.SelectionColor, or a way to better make use of it?

So, I'm trying to create a function or two that takes html tags and colors them differently than the rest of the text (similar to how Visual Studio does it for key words like Dim). The only way I have found, is to use a rich text box and then do *.SelectionColor = Color.Blue, or something similar. Is there any other way to do this? I made it so whenever the textbox updates, it reads through it at changes all html tags to a different color. This works fine with a really short html file, but when they get to be larger, it takes too long, and the selection moves the cursor around.
So, is there any other way to do this, even if I have to use something other than a rich text box? If not, does anyone see a way to improve this?
Here are the two functions that run when the textbox updates. Tag is blue, attributes are red, stuff in quotes is green.
'//////////////////////////////////////////////////////////////////////////
'// findTag()
'// -finds a tag
'//////////////////////////////////////////////////////////////////////////
Private Function findTag()
Dim tag As String = ""
Dim i As Integer = 0
Dim startTag As Integer
While (i < txtCurrentFile.TextLength - 1)
If txtCurrentFile.Text(i) = "<" Then
startTag = i
While txtCurrentFile.Text(i) <> ">"
tag += txtCurrentFile.Text(i)
i += 1
End While
tag += ">"
colorCode(startTag, tag)
tag = ""
End If
i += 1
End While
Return Nothing
End Function
'//////////////////////////////////////////////////////////////////////////
'// colorCode()
'// -colors different tags accordingly
'//////////////////////////////////////////////////////////////////////////
Private Function colorCode(ByVal startIndex As Integer,
ByVal tag As String)
Dim i As Integer = 0
Dim isAttributes As Boolean = False
Do While (tag(i) <> " " And tag(i) <> ">")
txtCurrentFile.Select(startIndex + i, 1)
txtCurrentFile.SelectionColor = Color.Blue
i += 1
Loop
If i < tag.Length Then
Do Until (tag(i) = ">")
Do Until (tag(i) = Chr(34))
txtCurrentFile.Select(startIndex + i, 1)
txtCurrentFile.SelectionColor = Color.Red
i += 1
Loop
i += 1
Do Until (tag(i) = Chr(34))
txtCurrentFile.Select(startIndex + i, 1)
txtCurrentFile.SelectionColor = Color.Purple
i += 1
Loop
i += 1
Loop
txtCurrentFile.Select(startIndex + i, 1)
txtCurrentFile.SelectionColor = Color.Blue
End If
Return Nothing
End Function
a few suggestions:
Ditch the character scanner. Replace it with anything that is speedier (RegEx, HTML Agility Pack, ...)
If you really want to keep the character scanner, then limit the scan to the area around the modifications (say, 200 characters behind and in front of the cursor)
Remember where the cursor is before you start the color process and restore it when finished.
Implement a background colorizer that does a full file re-color on a separate thread (you'll have to clone the RTB and only apply the changes if the user hasn't made any changes while the colorizer was running).
... I don't know if this would work AT ALL!!!, but it could be cool if it did...
Maybe open the file in a webbrowser control and set your coloring rules in a css sheet??
Again, I don't know if this is a good idea or not, but it might do the trick very nicely since it's already HTML you're dealing with...