¿Cómo hacer este bucle sencillo correctamente?

Estoy aprendiendo a programar en VBA, y estoy realizando mis primero bucles, ahora bien, tengo un formulario, el cual contiene una textbox "TexBox1" y una listbox "lb_clientes" tiene 3 columnas.

En el siguiente código cuando inizializo el formulario, cargo a la listbox los datos de la tabla "logros".

Private Sub UserForm_Initialize()
    Me.Caption = "Buscar Cliente"
    Me.lb_clientes.ColumnCount = 3
   'Me.lb_clientes.ColumnHeads = True
    Me.lb_clientes.ColumnWidths = "50;170;100"
    Me.lb_clientes.RowSource = "logros"
    Me.TextBox1.SetFocus
End Sub

Luego trato de realizar un filtro de la informacion de la tabla de la siguiente manera.

Private Sub TextBox1_Change()
    'cuando el valor en la TextBox1 cambie:
    Application.ScreenUpdating = False
    '1) Aqui trato de limpiar el contenido de la ListBox, pero no puedo porque _
    'previamente he cargado una lista entonces me da error ¿Como puedo limpiarla?.
    Me.lb_clientes.Clear
    'Aquí selecciono y activo la primera celda con la base de datos
    Worksheets("Hoja1").Activate
    Range("A1").Activate
    'Defino las variables necesarias
    fil = 1
    texbuscado = TextBox1.Text
    indfil = 0
    'Inicio bucle for while esta condicion para que llegue al _
    'final de la tabla.
    While ActiveCell.Offset(fil, 0).Value <> ""
    'Defino mas variables deacuerdo al contenido en cada fila.
    ActiveCell.Offset(fil, 0).Activate
    texto1 = ActiveCell.Value
    texto2 = ActiveCell.Offset(0, 1).Value
    texto3 = ActiveCell.Offset(0, 2).Value
    coincidencia = InStr(1, UCase(texto1 & " " & texto2 & " " & texto3), UCase(texbuscado))
        If coincidencia > 0 Then
            Me.lb_clientes.AddItem texto1
            Me.lb_clientes.List(indfil, 1) = texto2
            Me.lb_clientes.List(indfil, 2) = texto3
            indfil = indfil + 1
        End If
    fil = fil + 1
    Wend
    Application.ScreenUpdating = True
End Sub

Exeptuando la parte en la que trato de limpiar la ListBox, funciona, pero solo agrega las filas hasta que da el tamaño que tiene la listbox de alto, es decir, no sigue agregando valores de tal forma que me ponga la barrita de desplazamiento al lado derecho que permitira ver todas las coinsidencias segun lo que escriba en la textbox1.

Agradezco su colaboraciony si hay alguna forma más sencilla de hacer que funcione, estoy abierto a cualquier sugerencia.

Aquí el ARCHIVO si lo desean.

1 respuesta

Respuesta
2

Le hice algunas mejoras a tu macro, te cambie el ciclo do por un ciclo for son mucho mas rapidos y eficientes, recuerda esto uno de los secretos de una macro eficiente es que sin usar el Screenupdating la macro interactue lo menos posible con la pantalla y que los todo proceso se haga a traves de la memoria (esto ayuda bastante cuando se manejan miles de registros y tienes un equipo de bajo rendimiento), tu macro la veras en verde ya decides tu cual de las dos usar.

Private Sub TextBox1_change()
    Application.ScreenUpdating = False
    'si utilizas .rowsource para cargar datos debes usar rowsource para limpiar el combobox y no un .clear
    'esta instruccion se usa cuando usas la instruccion .additem
    lb_clientes.RowSource = Empty
    Rem ESTABLECE UNA MATRIZ DE N FILAS POR N COLUMNAS SE DETIENE EN LA ULTIMA FILA Y
    Rem COLUMNA CON DATOS, ES COMO UN CONTENEDOR VIRTUAL
    Set DATOS = Range("A1").CurrentRegion
    'Defino las variables necesarias
    fil = 1:    texbuscado = TextBox1.Text:   indfil = 0
    'En lugar de un bucle Do.. Wend usa un for... next es mucho mas eficiente ya que hace las
    'busquedas sin interactuar con la pantalla esto hace a la macro mucho mas rapida.
    With DATOS
        For I = 1 To .Rows.Count
        'si colocas las instrucciones (siempre que puedas) en la misma linea excel las considera como una sola,
 'lo cual le da mas rapidez a la macro
            TEXTO1 = .Cells(I, 1):  TEXTO2 = .Cells(I, 2):  TEXTO3 = .Cells(I, 3)
            coincidencia = InStr(1, UCase(TEXTO1 & " " & TEXTO2 & " " & TEXTO3), UCase(texbuscado))
            If coincidencia > 0 Then
    'los with end with ejecutan la instruccion en bloques es como cuando en vez de colocar ladrillo por ladrillo
    'colocas la pared ya terminada
            With lb_clientes
                    .AddItem TEXTO1: .List(indfil, 1) = TEXTO2: .List(indfil, 2) = TEXTO3
            End With
            indfil = indfil + 1
        End If
        Next I
    End With
    'While ActiveCell.Offset(fil, 0).Value <> ""
    'Defino mas variables deacuerdo al contenido en cada fila.
    'ActiveCell.Offset(fil - 1, 0).Activate
    'TEXTO1 = ActiveCell.Value
    'TEXTO2 = ActiveCell.Offset(0, 1).Value
    'TEXTO3 = ActiveCell.Offset(0, 2).Value
    'coincidencia = InStr(1, UCase(TEXTO1 & " " & TEXTO2 & " " & TEXTO3), UCase(texbuscado))
    '    If coincidencia > 0 Then
    '        Me.lb_clientes.AddItem TEXTO1
    '        Me.lb_clientes.List(indfil, 1) = TEXTO2
    '        Me.lb_clientes.List(indfil, 2) = TEXTO3
    '        indfil = indfil + 1
    '    End If
    'fil = fil + 1
    'Wend
    Application.ScreenUpdating = True
End Sub
Private Sub UserForm_Initialize()
    With Me
        .Caption = "Buscar Cliente"
        With .lb_clientes
            .ColumnCount = 3
            '.ColumnHeads = True
            .ColumnWidths = "50;170;100"
            .RowSource = "logros"
        End With
    .TextBox1.SetFocus
End With

Excelente amigo, muchas gracias, super bien explicado lo del With, "Ladrillo y pared", te lo agradezco. Espero seguir aprendiendo hasta ser así de pro.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas