Buenas tardes a todos. Otra vez recurro a su ayuda.
No encuentro cómo hacer que se cuenten palabras según su color en un RichTextBox en VB.NET. Sí puedo hacer que cuente palabras de un texto en total, pero quisiera hacer que tambien tenga la opcion de buscar palabras segun su color.
Tengo un texto a la cual aplico unos filtros de búsquedas, en algunos casos y según la búsqueda, es necesario poner el color de las fuentes en ROJO y en otros en AZUL, por ejemplo. Y estando todos marcados que sólo me diga cuantas palabars en ROJO están seleccionadas sea lo que sea que esté escrito.
Si me pueden orientar, les agradecería mucho.
Saludos!
Todo depende de la forma exacta en que se haga y si es algo automático o tienes control de ello. Supongamos que todo es asequible y que lo haces tú, sin requerir a librerías ajenas...
El modo más sencillo entonces es que cuando debas seleccionar las palabras que se están buscando según el filtro (etc...), las añadas a una colección explícita (quien dice una colección, dice una tabla hash, etc...).
A la colección colRojas, las palabras rojas y a la colección colAzules para las palabras azules, según el criterio seguido y acto seguido las coloreas sobre el texto (tal como vienes haciendo)...
Luego cuando se reclame contar las palabras, la propiedad Count de la colección te devuelve el total.
Luego también, si se reclama una búsqueda sobre esa selección, ahora puedes buscar en la colección las palabras específicas que se seleccionaron (en vez de hacerlo de nuevo cada vez sobre el texto).
Y por supuesto, cuando cambie el criterio de selección se debe destruir el contenido de las colecciones y crearlas de nuevo, exactamente igual que las palabras se volverían a colorear de la forma esperada...
p.d.: Si además de buscarla en la colección, tienes también que remarcarla en el texto, guarda también la posición de la palabra en el texto en la propia colección.
Podrías hacer un array a partir de las palabras que hay en el texto. Luego una función o procedimiento que busque cada palabra en le texto y obtienes la propiedad de color que tiene una palabra y un contador para coda color vaya sumando las palabras que tienen x color.
Algo así:
Dim array() As String = RichTextBox1.Text.Split(" "c)
For Each palabra As String In array
RichTextBox1.Find(palabra, RichTextBoxFinds.MatchCase) '//Busca la palabra y la selecciona
Select Case RichTextBox1.SelectionColor.Name
Case "Black" : negro += 1
Case "Red" : rojo += 1
End Select
Next
Ejemplo de uso:
Dim rojo = 0, negro As Integer = 0
With RichTextBox1
.Text = "Esto es una frase de prueba, esto no se más que poner"
.Find("Esto")
.SelectionColor = Color.Red
.Find("una")
.SelectionColor = Color.Red
Dim array() As String = .Text.Split(" "c)
For Each palabra As String In array
.Find(palabra, RichTextBoxFinds.MatchCase) '//Busca la palabra y la selecciona
Select Case .SelectionColor.Name
Case "Black" : negro += 1
Case "Red" : rojo += 1
End Select
Next
MessageBox.Show(String.Format("negro: {1}{0}rojo: {2}", Environment.NewLine, negro, rojo))
'//Deselecciona y coloca el cursor al principio del texto
.DeselectAll()
.SelectionStart = 0
End With
Puedes desarrollar a partir de ahí. Si no se adapta a lo que necesitas porque hay palabras que no desees que cuente, palabras repetidas, yo que se lo que sea, pues modificas lo que tu consideres. Es sólo una idea, no tengo ninguna función ni snippet en plan "expert" para estas cosas...
En un principio use
RichTextBoxFinds.WholeWord en lugar de
RichTextBoxFinds.MatchCase, pero tras colgar el ejemplo decidí probar añadir más palabras como 'Esto' y 'esto' 'es' a ver si contaba todos los 'es', que serían 3 en este caso. Solo debe buscar las palabras completas, así que cambié a
RichTextBoxFinds.MatchCase
También puedes poner el cas así:
Case Color.Black.Name : negro += 1
Case Color.Red.Name : rojo += 1
Case Color.Blue.Name : azul += 1
Dim rojo = 0, negro = 0, azul As Integer = 0
With RichTextBox1
.Text = "Esto es una frase de prueba, esto no se más que poner"
.Find("Esto")
.SelectionColor = Color.Red
.Find("una")
.SelectionColor = Color.Red
.Find("prueba")
.SelectionColor = Color.Blue
Dim array() As String = .Text.Split(" "c)
For Each palabra As String In array
.Find(palabra, RichTextBoxFinds.MatchCase) '//Busca la palabra y la selecciona
Select Case .SelectionColor.Name
Case Color.Black.Name : negro += 1
Case Color.Red.Name : rojo += 1
Case Color.Blue.Name : azul += 1
End Select
Next
MessageBox.Show(String.Format("negro: {1}{0}rojo: {2}{0}azul: {3}", Environment.NewLine, negro, rojo, azul))
'//Deselecciona y coloca el cursor al principio del texto
.DeselectAll()
.SelectionStart = 0
End With
MessageBox.Show(String.Join(vbCrLf, array))
Si te fijas azul devuelve 0, porque cuenta "prueba," como una palabra y como solo hay el texto "prueba" (sin la coma) en azul no lo cuenta.
array
Esto
es
una
frase
de
prueba,
esto
no
se
más
que
poner
Esto es algo que hay que pulir, como digo es un ejemplo.
Una solución que he encontrado es quitar la coma que pueda haber en 'palabra'
RichTextBox1.Find(palabra.Replace(",", ""), RichTextBoxFinds.MatchCase) '//Busca la palabra y la selecciona
Ahora sí ya contaría correctamente
Dim rojo = 0, negro = 0, azul As Integer = 0
With RichTextBox1
.Text = "Esto es una frase de prueba, esto no se más que poner"
.Find("Esto")
.SelectionColor = Color.Red
.Find("una")
.SelectionColor = Color.Red
.Find("prueba")
.SelectionColor = Color.Blue
Dim array() As String = .Text.Split(" "c)
For Each palabra As String In array
.Find(palabra.Replace(",", ""), RichTextBoxFinds.MatchCase) '//Busca la palabra y la selecciona
Select Case .SelectionColor.Name
Case Color.Black.Name : negro += 1
Case Color.Red.Name : rojo += 1
Case Color.Blue.Name : azul += 1
End Select
Next
MessageBox.Show(String.Format("negro: {1}{0}rojo: {2}{0}azul: {3}", Environment.NewLine, negro, rojo, azul))
'//Deselecciona y coloca el cursor al principio del texto
.DeselectAll()
.SelectionStart = 0
MessageBox.Show(String.Join(vbCrLf, array))
End With
Esto es una frase de prueba, esto no se más que poner
COMO EJEMPLO, puedes crearte por ejemplo una clase y lo modificas o lo mejoras a tu gusto
Public Class CountWordsColorRichTextBox
Private Shared azul, rojo, negro As Integer
Public Shared Sub CountColorsWords(ByVal myRich As RichTextBox)
With myRich
Dim array() As String = .Text.Split(" "c)
For Each palabra As String In array
.Find(palabra.Replace(",", ""), RichTextBoxFinds.MatchCase) '//Busca la palabra y la selecciona
Select Case .SelectionColor.Name
Case Color.Black.Name : negro += 1
Case Color.Red.Name : rojo += 1
Case Color.Blue.Name : azul += 1
End Select
Next
End With
End Sub
Public Shared Property GetBlueCount() As Integer
Get
Return azul
End Get
Set(ByVal value As Integer)
azul = 0
End Set
End Property
Public Shared Property GetRedCount() As Integer
Get
Return rojo
End Get
Set(ByVal value As Integer)
rojo = 0
End Set
End Property
Public Shared Property GetBlackCount() As Integer
Get
Return negro
End Get
Set(ByVal value As Integer)
negro = 0
End Set
End Property
End Class
EJEMPLO DE USO:
Public Class Form1
Private Sub Form1_Shown(sender As Object, e As EventArgs) Handles Me.Shown
With RichTextBox1
.Text = "Esto es una frase de prueba, esto no se más que poner"
.Find("Esto")
.SelectionColor = Color.Red
.Find("una")
.SelectionColor = Color.Red
.Find("prueba")
.SelectionColor = Color.Blue
End With
CountWordsColorRichTextBox.CountColorsWords(RichTextBox1)
MsgBox("negro: " & CountWordsColorRichTextBox.GetBlackCount)
MsgBox("rojo: " & CountWordsColorRichTextBox.GetRedCount)
MsgBox("azul: " & CountWordsColorRichTextBox.GetBlueCount)
End Sub
End Class
Public Class CountWordsColorRichTextBox
Private Shared azul, rojo, negro As Integer
Public Shared Sub CountColorsWords(ByVal myRich As RichTextBox)
With myRich
Dim array() As String = .Text.Split(" "c)
For Each palabra As String In array
.Find(palabra.Replace(",", ""), RichTextBoxFinds.MatchCase) '//Busca la palabra y la selecciona
Select Case .SelectionColor.Name
Case Color.Black.Name : negro += 1
Case Color.Red.Name : rojo += 1
Case Color.Blue.Name : azul += 1
End Select
Next
End With
End Sub
Public Shared Property GetBlueCount() As Integer
Get
Return azul
End Get
Set(ByVal value As Integer)
azul = 0
End Set
End Property
Public Shared Property GetRedCount() As Integer
Get
Return rojo
End Get
Set(ByVal value As Integer)
rojo = 0
End Set
End Property
Public Shared Property GetBlackCount() As Integer
Get
Return negro
End Get
Set(ByVal value As Integer)
negro = 0
End Set
End Property
End Class
Maneras de hacerlo abran unas cuantas. Ignoro si RitcthTExtBox tendrá algún método o algo para contar palabras que reúna alguna propiedad, se me ocurre que igual se podría usar
LINQ por ejemplo, pero de eso ya se encargará otro jaja.