Click con botón derecho en listbox y abra un menú contextual

Quisiera saber si existe la posibilidad e hacer click con el botón derecho en una fila de un listbox que se encuentra en un formulario y abra un menu contextual con las palabras Modificar, Eliminar.

1 Respuesta

Respuesta
1

En un modulo pega el siguiente código:

Private Sub runModificar()
    MsgBox "Ejecutando 'Modificar'"
End Sub
Private Sub runEliminar()
    MsgBox "Ejecutando 'Eliminar'"
End Sub
Private Sub ClickDerecho()
    Application.CommandBars("Cell").Reset
    Dim cbc As CommandBarControl
    For Each cbc In Application.CommandBars("cell").Controls
        cbc.Visible = False
    Next cbc
    With Application.CommandBars("Cell").Controls.Add(temporary:=True)
        .Caption = "Modificar"
        .OnAction = "runModificar"
    End With
    With Application.CommandBars("Cell").Controls.Add(temporary:=True)
        .Caption = "Eliminar"
        .OnAction = "runEliminar"
    End With
    Application.CommandBars("Cell").ShowPopup
End Sub

Luego en el evento MouseDown del listbox el siguiente:

Private Sub Listbox1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
    If Button = 2 Then Run "ClickDerecho"
End Sub

NOTA (Limitación)!!!:

Esa es la manera más simple y sencilla de hacerlo. Con esta forma primero tienes que seleccionar la fila que deseas "Modificar o Eliminar" con click izquierdo. Esto se puede arreglar, pero llevaría más trabajo y seria una pregunta totalmente aparte. El código presentado es totalmente ilustrativo para que agarres la idea, asumiendo que conoces algo de VBA y continúes por tu cuenta.

Perdón, dije MouseDown pero el código dice MouseUp, es lo mismo, funciona igual en cualquiera de los dos eventos, mejor usa el MouseUp como en el código.

Si te queda alguna otra duda sobre este tema, me dejas sabe.

Muchas gracias, la secuencia que me enviaste funciona correctamente. Siento no saber cómo modificarla para seguir con mis conocimientos para seleccionar la línea con el botón derecho y se abra el menú. Saludos

Esta es una alternativa un poco rustica pero funciona, es lo más sencillo que puedo hacerte, para poder seleccionar directamente con el click derecho, modifica el código en el evento del listbox así:

Private Sub Listbox1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Dim Idx As Long
If Button = 2 Then
    Idx = ListBox1.TopIndex + Int(Y / (ListBox1.Font.Size * 1.2) - 1)
    ListBox1.ListIndex = Idx
    Cells(Idx + 2, 1).Select
    Run "ClickDerecho"
End If
End Sub

Si quieres agregarle algo visual a tu menú para que se vea mas bonito, coloca un .FaceId

para el botón "Modificar" el faceid puede ser 6512, y para "Eliminar" el 3265.

Te queda así:

Private Sub ClickDerecho()
    Application.CommandBars("Cell").Reset
    Dim cbc As CommandBarControl
    For Each cbc In Application.CommandBars("cell").Controls
        cbc.Visible = False
    Next cbc
    With Application.CommandBars("Cell").Controls.Add(temporary:=True)
        .Caption = "Modificar"
        .OnAction = "runModificar"
        .FaceId = 6512 '<--FACE ID'
    End With
    With Application.CommandBars("Cell").Controls.Add(temporary:=True)
        .Caption = "Eliminar"
        .OnAction = "runEliminar"
        .FaceId = 3265 '<--FACE ID'
    End With
    Application.CommandBars("Cell").ShowPopup
End Sub

Andy

Si quieres cambiar los face id, puedes encontrar una referencia aquí:

Excel Face IDs

Andy

¡Gracias por los detalles gráficos y el ajuste a mi solicitud! Hice una sola modificación mínima que quedo así:

Private Sub Listbox1_MouseUp(ByVal Button As Integer, ByVal Shift As Integer, ByVal X As Single, ByVal Y As Single)
Dim Idx As Long
If Button = 2 Then
    Idx = ListBox1.TopIndex + Int(Y / (ListBox1.Font.Size * 1.2) - 1)
    ListBox1.ListIndex = Idx
    Cells(Idx + 1, 1).Select
    Run "ClickDerecho"
End If
End Su

pues si Cells(Idx + 2, 1).Select seleccionaba la fila superior si intentaba correr la apertura de un formulario despues de la seleccion en el menu contextual,

Private Sub runModificar()
    frmModificar.Show
End Sub

de todos modos el merito es todo tuyo.
Gracias otra vez.

Ah esa línea se me escapo, la tenia puesta yo para probar, no debí copiarla, el +2 depende si tienes encabezado o no.. Cualquier duda me dejas saber. Si puedes calificar la otra respuesta te lo agradeceré

¡Gracias! 

Hola, una consulta: si en el listbox se encuentra toda la base de datos y hago click derecho desplegando el menu me selecciona correctamente la fila, sin embargo si hago un filtro desde un textbox para reducir la informacion al seleccionar la fila elige la anterior inmediata y ejecuta la macro sobre esa fila.

Cells(Idx + 2, 1).Select

Que podrá ser?

No estoy seguro, tendria que ver un ejemplo de cómo filtras la informacion, puede que al filtrar se muevan los indices, es lo mas probable. Como le habia dicho, esa linea se me escapó, no fue intencional incluirla en el codigo que le proporcioné. No soy partidiario de seleccionar celdas con VBA, la forma ideal seria tomar los datos del listbox, no de la hoja. Si me cuentas mas sobre tu proyecto talvez pueda darte mas ideas sobre una mejor alternativa.

Ante todo gracias por tu tiempo.

Tengo un formulario que realiza desde un Combobox una búsqueda en principio eligiendo la columna dónde buscar y luego con un textbox filtrando finalmente la información.

La información filtrada se pasan a una hoja auxiliar por tener más de 10 filas el listbox.

Una muestra del archivo con el que estoy trabajando es: 

Archivo 

Espero puedas ayudarme.

Saludos.

Lo que pasa es lo que imaginaba. Cómo explicarlo: La celda seleccionada sera aquella cuyo indice sea igual al indice de la fila seleccionada en el listbox, + 2, y eso no tiene por que ser necesariamente fiel, ya que si en la hoja tienes 10 registros y tu filtro reduce el ListBox a 1 registro, el listbox solo contiene un indice, el indice 0, por lo que 0 + 2 = 2, así que la celda a seleccionar está en la fila 2 de la hoja, y eso no tiene por que ser igual al dato filtrado, no sé si me explico.

Esta no es la manera correcta de hacer lo que deseas, para arreglarlo, habría que cambiar casi todo y se me va a dificultar cambiar todo debido a mi tiempo disponible para dedicar aquí. Si me animo a ayudarte sera un proceso lento y no te garantizo nada. Por ahora puedo darte consejos si lo deseas y de ahí partir para reestructurar tu proyecto. Me dejas saber.

¡Gracias y agradezco todo este tiempo! Me gustaría saber si estoy realizando lo correcto para ir hacia lo que necesito:

1. obtener el valor de la numerico de la fila en la columna A al ser selecciondo en el list box.

2. pegar ese resultado en una celda.

3. buscar ese valor en la tabla original.

4. encontrar el numero de fila.

5. ese valor es el que debe ser Idx

Desde de ya y de ante mano gracias.

Saludos

Disculpa la demora, veo que estamos en continentes diferentes.

Bueno el tema "buscar" en Excel es bastante relativo y complejo, primero que nada, ¿el dato que se busca es único e irrepetible? En un escenario de un proyecto de programación profesional donde se usen bases de datos reales (las hojas de Excel no son bases de datos!), estas bases contarían con lo que se llama "llave primaria" que es un ID único e irrepetible para cada registro. Si queremos hacer algo parecido en Excel, mi primera recomendación seria usar a la columna A para asignar un ID único e irrepetible a cada registro, esto a la larga va a ahorrarte muchos dolores de cabeza.

Otro consejo, en VBA los métodos "copiar" y "pegar" deben evitarse a toda costa, son lentos, torpes y causan pobre rendimiento. Así que mi siguiente recomendación es librarte de esa "hoja temporal" a la que llevas los datos filtrados, es un "para adelante y para atrás" innecesario.

Un consejo más, al igual que copiar y pegar, los métodos "activate" y "select" son muy malos en VBA, también deben evitarse a toda costa. En el 99% de los casos, no se necesita "activar" una hoja para hacer algo con ella, tampoco se necesita "seleccionar" una celda o un rango para hacer algo con ella. Las referencias relativas funcionan a la perfección en VBA.

Ya planteado esto, a partir de aquí puedes abrir preguntas relacionadas a estos temas y etiquetarme para así verla más rápido y poderte asistir.

¡Gracias! Voy a tomar todos tus consejos. Lo bueno de todo esto es que los datos de la primer columna son únicos.

Saludos y hasta pronto.

Añade tu respuesta

Haz clic para o

Más respuestas relacionadas