jueves, 21 de diciembre de 2017

VBA: Filtrar en un ListBox

Veremos una manera rápida y ágil de mostrar elementos coincidentes similares en un ListBox a partir de un valor introducido en un TextBox.
Ya vimos algo similar en este post, pero en esta ocasión emplearemos las Array en nuestro código para agilizar el traspaso de información...

Nuestros datos en una hoja llamada 'Datos' y un rango A1:C11:

VBA: Filtrar en un ListBox



Nuestro formulario, reducido a lo necesario, tendrá:
1- un TextBox llamado 'TxtFiltro'
2- un ListBox llamdao 'ListFiltro'


Así pues añadimos la siguiente macro dentro de la ventana de código de nuestro UserForm en nuestro proyecto de VB:

Private Sub TxtFiltro_Change()
Dim myList() As Variant
Dim X As Long, Y As Long
Dim coincidencia As Boolean
coincidencia = False
Y = 0
'replicamos un filtro a visualizar sobre el ListBox
For X = 2 To Sheets("Datos").Range("A" & Rows.Count).End(xlUp).Row
    If InStr(1, UCase(Sheets("Datos").Range("B" & X).Value), UCase(Me.TxtFiltro.Value)) > 0 Then
        coincidencia = True
        ReDim Preserve myList(2, Y)
        'cargamos nuestra matriz....
        myList(0, Y) = Sheets("Datos").Range("A" & X).Text
        myList(1, Y) = Sheets("Datos").Range("B" & X).Text
        myList(2, Y) = Sheets("Datos").Range("C" & X).Text
        Y = Y + 1
    End If
Next
'si hemos localizado alguna coincidencia...
If coincidencia = True Then
    'mostramos datos coincidentes cargados en nuestra Array
    Me.ListFiltro.List = Application.Transpose(myList)
Else
    Me.ListFiltro.Clear
End If
End Sub
 
Private Sub UserForm_Activate()
Dim var As Variant
'cargamos en una Array el rango de datos...
With Sheets("Datos")
    var = .Range("A2:C" & .Range("A" & Rows.Count).End(xlUp).Row).Value
End With
With Me.ListFiltro
    .ColumnCount = 3 'indicamos número columnas
    .ColumnWidths = "50;50;50" 'determinamos ancho...
    If Not IsEmpty(var) Then
        'si hay datos vaciamos el ListBox
        .Clear
        .List = var
    End If
End With
End Sub



Además del uso de Array, y para compensar el desconocimiento a priori del número de registros coincidentes, hacemos de nuevo uso de la definición de tamaño de una Array, empleando ReDim Preserve, que nos habilita la opcíon de incorporar nuevos registros de manera 'ilimitada' manteniendo los datos cargados.
Esta técnica evita los conteos previos de coincidencias...


Al ejecutar el UserForm comprobaremos cómo a medida escribimos en el TextBox, el filtro se muestra directamente sobre los elementos del campo 'Concepto', tal como buscábamos.

9 comentarios:

  1. porque me pinta en vertical el resultado?

    ResponderEliminar
  2. cuando cambio para que filtre por la columna A no funcion, la columna B y C si funciona. Porque pasa eso

    ResponderEliminar
    Respuestas
    1. Hola,
      ¿qué tal estás?, un placer saludarte igualmente

      Disculpa pero no comprendo tus preguntas

      Saludos cordiales y quedo atento a tus aclaraciones

      Eliminar
    2. gracias por tu tiempo, o que pasa es que el cuando modifico el codigo para que filtre por la columna A, la informacion la muestra en vertical, caso contrario pasa cuando filtro por la columna B o C

      Eliminar
    3. A B C
      nombre cargo aplicación
      pedro G.I. MCSS
      pedro 1 G.A. CRM
      pedro 2 G.P. MCSS
      pedro G.I. MCSS
      pedro 3 G.A. CRM
      pedro 4 G.P. MCSS
      pedro G.I. MCSS
      pedro 5 G.A. CRM
      pedro 6 G.P. MCSS
      pedro G.I. MCSS

      si buscas Pedro 1
      te muestra asi :

      Pedro 1
      G.A.
      CRM
      cuando lo perfecto es
      Pedro 1 G.A. CRM

      Eliminar
    4. Hola,
      a veces pasa que si solo existe un registro aparece, como indicas, en 'vertical', tienes que gestionar para identificar primero el número de registros que existe y en caso que sea 1 ,aplicar un trasponse

      Saludos

      Eliminar
  3. Este comentario ha sido eliminado por un administrador del blog.

    ResponderEliminar
  4. BUENAS TARDES,
    GRACIAS POR ESTOS APORTES QUE NOS DAS. TENGO UNA DUDA HICE UN LISTBOX QUE SE LLENA DE UNA HOJA DE EXCEL Y LE HICE UN BUSCAR CON UN TEXTBOX EN E EVENTO CHANCE, MI PROBLEMA SE ENCUENTRA QUE CUANDO LE ESCRIBO EN LA BÚSQUEDA ME BORRA LOS ENCABEZADOS.

    TE DEJO MI CODIGO

    numdatos = Hoja4.Range("B" & Rows.Count).End(xlUp).Row

    Hoja4.AutoFilterMode = False
    Me.Detalle = Clear
    Me.Detalle.RowSource = Clear

    y = 0

    For fila = 3 To numdatos
    descrip = Hoja4.Cells(fila, 2).Value

    If UCase(descrip) Like "*" & UCase(Me.txtNProyecto.Value) & "*" Then

    With Me.Detalle
    .ColumnHeads = True
    .AddItem
    .List(y, 0) = Hoja4.Cells(fila, 2).Value
    .List(y, 1) = Hoja4.Cells(fila, 3).Value
    .List(y, 2) = Hoja4.Cells(fila, 7).Value
    .List(y, 3) = Hoja4.Cells(fila, 9).Value
    .List(y, 4) = Hoja4.Cells(fila, 10).Value
    .List(y, 5) = Hoja4.Cells(fila, 11).Value
    .List(y, 6) = Hoja4.Cells(fila, 12).Value
    .List(y, 7) = Hoja4.Cells(fila, 15).Value



    End With

    Me.Detalle.AddItem
    Me.Detalle.List(y, 0) = Hoja4.Cells(fila, 2).Value
    Me.Detalle.List(y, 1) = Hoja4.Cells(fila, 3).Value
    Me.Detalle.List(y, 2) = Hoja4.Cells(fila, 7).Value
    Me.Detalle.List(y, 3) = Hoja4.Cells(fila, 9).Value
    Me.Detalle.List(y, 4) = Hoja4.Cells(fila, 10).Value
    Me.Detalle.List(y, 5) = Hoja4.Cells(fila, 11).Value
    Me.Detalle.List(y, 6) = Hoja4.Cells(fila, 12).Value
    Me.Detalle.List(y, 7) = Hoja4.Cells(fila, 15).Value

    y = y + 1

    Detalle.ColumnHeads = True
    End If

    Next

    AGRADECERIA QUE PUDIERAS AYUDARME

    ResponderEliminar
    Respuestas
    1. Hola,
      los encabezados solo aparecen cuando se carga datos desde un rango o tabla.. si procedes a cargar el listbox desde datos individuales (un array o celdas una a una o similar), dará igual que pongas True a mostrar encabezados... no lo cogerá.
      Lo normal es poner unas etiquetas por encima del listbox para mostrarlos... no muy fino, pero poco más se puede hacer

      Saludos

      Eliminar