VB.NET - Contar palabras seguhn propiedad

Iniciado por dont'Exist, 13 Abril 2017, 21:58 PM

0 Miembros y 1 Visitante están viendo este tema.

dont'Exist

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!

Serapis

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.

okik

#2
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í:

Código (vbnet) [Seleccionar]

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:

Código (vbnet) [Seleccionar]

     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í:
Código (vbnet) [Seleccionar]
   
Case Color.Black.Name : negro += 1
Case Color.Red.Name : rojo += 1
Case Color.Blue.Name : azul += 1




Código (vbnet) [Seleccionar]
     
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'

Código (vbnet) [Seleccionar]

RichTextBox1.Find(palabra.Replace(",", ""), RichTextBoxFinds.MatchCase) '//Busca la palabra y la selecciona


Ahora sí ya contaría correctamente
Código (vbnet) [Seleccionar]
       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



CitarEsto es una frase de prueba, esto no se más que poner

 
 negro:9
  rojo: 2
  azul: 1






COMO EJEMPLO, puedes crearte por ejemplo una clase y lo modificas o lo mejoras a tu gusto

Código (vbnet) [Seleccionar]

   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:
Código (vbnet) [Seleccionar]

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.