BÚSQUEDA AVANZADA


En una hoja que contiene los datos que se muestra en la imagen de la derecha, muestro un formulario con tres cuadros de texto, un cuadro de lista y un botón de comando (ver imagen más abajo).

El tema trata de que a medida que escribimos en el cuadro de texto, el cuadro de lista muestra los datos que coinciden con el texto escrito, para facilitar la búsqueda.

Contenido:

1.- Búsqueda avanzada 1.
2.- Búsqueda avanzada 2.


Búsqueda avanzada 1:

En este ejemplo, controlo que la lista no contenga nombres duplicados. Además la búsqueda la podemos realizar tanto por nombre como por categoría.



La imagen de arriba a la izquierda, muestra como construye el listado con aquellos nombres que contienen en cualquier posición el texto escrito en el cuadro de texto. No discrimina entre mayúsculas y minúsculas, para ello hago uso de UCASE en el código VBA del módulo de filtrado.

Al hacer clic en el cuadro de lista para seleccionar un nombre (en el ejemplo; José Antonio P. H.), muestra/escribe en los otros cuadros de texto, los datos correspondientes al nombre elegido (imagen; arriba al centro).

En la imagen de arriba a la derecha, buscamos/filtramos por categoría. En este caso el proceso trabaja de igual manera para la construcción del listado, pero al hacer clic en una categoría; escribe la misma en el cuadro correspondiente, pero no escribe ningún nombre ni ningún salario, ya que el dato elegido no contiene información para ello. En cambio, rellena el cuadro de lista con todos los nombres que coinciden con la categoría elegida (imagen a la derecha), permitiendo elegir uno de ellos en cuyo caso; si que completa los cuadros de texto con la información correspondiente, tal como se explica más arriba al seleccionar un nombre. Se puede ver más fácil el funcionamiento, interactuando con el ejemplo descargable.

El “cuadro de texto” Salario, en realidad es una etiqueta con la propiedad SpecialEffect ajustada a 2, para simular un cuadro de texto y que el contenido no pueda ser modificado.

A continuación reproduzco el código VBA que corresponde a este ejemplo.


 En un módulo ordinario (UserForm1):
      
      Sub Ejemplo1(Optional nada&)
        UserForm1.Show
      End Sub

      Sub MuestraDatos(control&, miDato$, fila&)
        Dim CT&
        CT = Val(UserForm1.LabelControl.Caption) ' TextBox1 o TextBox
        ' Debloquea los cuadros de texto.
        UserForm1.TextBoxNombre.Locked = True
        UserForm1.TextBoxCateg.Locked = True
        ' Escribe los datos relacionados con el nombre elegido.
        If CT = 1 Then UserForm1.TextBoxNombre.Text = Cells(fila, 1).Value
        UserForm1.TextBoxCateg.Text = Cells(fila, 2).Value
        If CT = 1 Then UserForm1.LabelSalario.Caption = Format(Cells(fila, _
             3).Value, "#,##0.00 € ") & " "
        ' Desbloquea los cuadros de texto.
        UserForm1.TextBoxNombre.Locked = False
        UserForm1.TextBoxCateg.Locked = False
     End Sub

     Sub Agrega(columna&, texto$, Optional sup&)
       Dim i As Integer
       ' ... compara con los datos existentes.
       For i = 2 To Cells(60000, columna).End(xlUp).Row
         If InStr(UCase(Cells(i, columna + sup).Text), texto) > 0 Then
           If i = 2 Then
             UserForm1.ListBox1.AddItem Cells(i, columna) ' ... lo añade a la lista.
           Else
             ' Si no está repetido...
             If Application.CountIf(Range(Cells(2, columna), Cells(i - 1, _
                 columna)), Cells(i, columna).Value) = 0 Then
               UserForm1.ListBox1.AddItem Cells(i, columna) ' ... lo añade a la lista.
             End If
           End If
         End If
       Next i
     End Sub


 En el módulo del formulario (UserForm1):

     Private Sub CommandButton1_Click()
       Unload UserForm1
     End Sub

     Private Sub ListBox1_Click()
       MuestraDatos Val(LabelControl.Caption), ListBox1.Value, Columns(Val(LabelControl.Caption)) _
           .Find(ListBox1.Value).Row
       If LabelControl.Caption = "2" Then
         ListBox1.Clear
         LabelControl.Caption = "1"
         Agrega 1, UCase(TextBoxCateg.Text), 1
       End If
       UserForm1.CommandButton1.SetFocus
     End Sub

     Private Sub TextBoxNombre_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
       LabelControl.Caption = "1"
     End Sub

     Private Sub TextBoxNombre_Change()
       ' Si no es cambio "manual", no evalua el cambio.
       If TextBoxNombre.Locked = True Then Exit Sub
       LabelControl.Caption = "1"
       TextBoxCateg.Locked = True
       limpia 1
       If TextBoxNombre.Text <> "" Then
         ' Muestra la ayuda sobre el cuadro de lista.
         ListBox1.ControlTipText = "Haz clic en un nombre"
         Agrega 1, UCase(UserForm1.TextBoxNombre.Text)
       Else
         ' Oculta la ayuda sobre el cuadro de lista.
         ListBox1.ControlTipText = ""
       End If
       TextBoxCateg.Locked = False
     End Sub

     Private Sub TextBoxCateg_KeyPress(ByVal KeyAscii As MSForms.ReturnInteger)
       LabelControl.Caption = "2"
     End Sub

     Private Sub TextBoxCateg_Change()
       ' Si viene del cuadro de lista no evalua el cambio.
       If TextBoxCateg.Locked = True Then Exit Sub
       LabelControl.Caption = "2"
       TextBoxNombre.Locked = True
       limpia 2
       If TextBoxCateg.Text <> "" Then
         Dim i As Integer
         ' Muestra la ayuda sobre el cuadro de lista.
         ListBox1.ControlTipText = "Haz clic en una categoría"
         Agrega 2, UCase(UserForm1.TextBoxCateg.Text)
       Else
         ' Oculta la ayuda sobre el cuadro de lista.
         ListBox1.ControlTipText = ""
       End If
       TextBoxNombre.Locked = False
     End Sub

     Private Sub limpia(control&)
         ListBox1.Clear ' Borra contenido anterior.
         If control = 1 Then TextBoxCateg.Value = "" ' Borra contenido anterior.
         If control = 2 Then TextBoxNombre.Value = "" ' Borra contenido anterior.
         LabelSalario.Caption = "" ' Borra contenido anterior.
     End Sub
     

Búsqueda avanzada 2:

Este ejemplo es más sencillo que el anterior. Aquí no permite buscar por categoría, ni controla los datos duplicados a la hora de construir el listado. Así como tampoco busca las coincidencias en cualquier parte del nombre, sino que filtra solamente cuando el nombre comienza igual que el texto escrito.
En la imagen de la derecha se puede ver que no ha filtrado José Antonio P. H. como en el ejemplo anterior, ya que dicho nombre no empieza por “ant” sino por "Jos".

Obviando esta diferencia, el resto funciona de la misma forma que el ejemplo anterior.

Para emplear un método diferente de bloqueo al empleado en el ejemplo anterior, los cuadros de texto; Categoría y Salario, están bloqueados (Locked=True), para evitar que sean modificados.

En ambos ejemplos, el botón Finalizar cierra y descarga el formulario.

A continuación reproduzco el código VBA que corresponde a este ejemplo.


 En un módulo ordinario (UserForm1):
      
     Sub Ejemplo2(Optional nada&)
       UserForm2.Show
     End Sub

 En el módulo del formulario (UserForm2):

     Private Sub CommandButtonFin_Click()
       Unload UserForm2  ' Cierra y descarga el formulario.
     End Sub

     Private Sub ListBox1_Click()
       Dim fila&
       TextBoxNombre.Locked = True  ' Para control de cambios.
       fila = Columns(1).Find(ListBox1.Value).Row  ' Número de fila que contiene el nombre.
       TextBoxNombre.Text = Cells(fila, 1).Value  ' Escribe el nombre.
       TextBoxCateg.Text = Cells(fila, 2).Value  ' Escribe la categoría.
       ' Escribe el salario.
       UserForm2.TextBoxSalario2.Text = Format(Cells(fila, 3).Value, "#,##0.00 € ") & " "
       TextBoxNombre.Locked = False  ' Desbloqua el cuadro de texto.
     End Sub

     Private Sub TextBoxNombre_Change()
       Dim i As Integer
       If TextBoxNombre.Locked = True Then Exit Sub  ' Si viene del Cuadro de lista; sale.
       ListBox1.Clear  ' Limpia el Cuadro de lista.
       TextBoxCateg.Text = ""  ' Limpia el cuadro Categoría.
       TextBoxSalario2.Text = ""  ' Limpia el cuadro Salario.
       ' Compara con los datos existentes.
       For i = 2 To Cells(60000, 1).End(xlUp).Row ' Si hay coincidencia...
         If UCase(Left(Cells(i, 1).Text, Len(TextBoxNombre.Text))) = UCase(TextBoxNombre _
             .Text) Then ListBox1.AddItem Cells(i, 1) ' ... añade el nombre a la lista.
       Next i
     End Sub


                                    * * * * * * *  0  * * * * * * *
     



Volver arriba