A veces, por los motivos que sean, se presenta la necesidad de ordenar datos dentro de un ListBox. Es posible que queramos tenerlos en un determinado orden para después procesarlos o, simeplemente, porque nos resulte mas fácil identificar los elementos en una determinada ordenación.
Vamos a ver aquí, mediante un sencillo ejemplo, como implementar unas rutinas para mover elementos arriba o abajo dentro de la la lista.
Creación de un UserForm
El primer paso será crear un UserForm que nos sirva para desarrollar el ejemplo. Será un UF muy sencillo con los elementos básicos:
- Un ListBox en el que estáran los datos a ordenar
- Un botón para subir una posición el elemento seleccionado
- Otro botón para bajar una posición el elemento seleccionado
- Un botón para cerrar el UF
- Añadiremos otro botón que utilizará el FileSystemObject para poder cargar nombres de ficheros en el ListBox y así tener datos susceptibles de ser ordenados
El UF nos debe quedar algo así:

Para poder reproducir el ejemplo, los nombres que he asignado son los siguientes:
- UserForm: UF_OrdenarListBox
- ListBox: Lst_Ficheros
- Botón Seleccionar ficheros: Btn_SelFichero
- Botón Subir: Btn_Subir
- Botón Bajar: Btn_Bajar
- Bot´ón Eliminar: Btn_Eliminar
- Botón Salir: Btn_Fin
Como podréis ver, todo un derroche de imaginación.
ListBox de varias columnas
Para hacer el ejemplo mas genérico, el ListBox creado tiene dos columnas (propiedad ColumnCount = 2). De esta forma veremos como reordenar todos los datos de las diferentes columnas.
En la primera columna, se carga el nombre del fichero y en la segunda, la ruta completa del mismo.
Programación Btn_SelFichero
Para poder ordenar datos dentro de un ListBox, lo primero que necesitamos es tener datos en el mismo.
Para nuestro ejemplo, vamos a cargar esos datos usando nombres de ficheros y, para ello, nos serviremos del FSO.
El código será el siguiente:
Private Sub Btn_SelFichero_Click()
Dim fd As FileDialog
Dim FicherosSel As Integer
Dim RutaCompleta As String
Dim PosFinRuta As Integer
Dim Fichero As String
Dim Indice As Integer
Dim i As Integer
Set fd = Application.FileDialog(msoFileDialogFilePicker)
fd.InitialView = msoFileDialogViewList
fd.AllowMultiSelect = True
FicherosSel = fd.Show
If FicherosSel = -1 Then
For i = 1 To fd.SelectedItems.Count
RutaCompleta = fd.SelectedItems(i)
PosFinRuta = InStrRev(RutaCompleta, "\")
Fichero = Right(RutaCompleta, Len(RutaCompleta) - PosFinRuta)
Indice = Me.Lst_Ficheros.ListCount
Me.Lst_Ficheros.AddItem
Me.Lst_Ficheros.List(Indice, 0) = Fichero
Me.Lst_Ficheros.List(Indice, 1) = RutaCompleta
Next i
End If
End Sub
Con este código, al hacer click en el botón de Seleccionar fichero, se nos abrirá una ventana desde la que podremos seleccionar ficheros. Al hacer click en Aceptar en dicha ventana, los nombres de los ficheros seleccionados se cargarán en el ListBox.
Como no es el objeto de este artículo, no explicaré el código. De todas formas, si tienes cualquier duda sobre el mismo, puedes ponerla en el foro:https://informaticamuyfacil.com/ForoExcel/macros-vba/
Programación Btn_Salir
Este es fácil: cierra el UF. Su código es muy sencillo:
Private Sub Btn_Fin_Click()
Unload Me
End Sub
Programación Btn_Eliminar
Con este botón eliminamos del ListBox el dato seleccionado. Para ello usaremos el siguiente código:
Private Sub Btn_Eliminar_Click()
If Me.Lst_Ficheros.ListIndex = -1 Or Me.Lst_Ficheros.ListIndex = Me.Lst_Ficheros.ListCount - 1 Then Exit Sub
Me.Lst_Ficheros.RemoveItem (Me.Lst_Ficheros.ListIndex)
End Sub
Como el botón anterior, el código no lo explicaré, pero como ves, es muy sencillo.
Programación Btn_Subir
Aquí empieza la parte interesante. Vamos a ver el código usado para ordenar datos dentro de un ListBox y después veremos el funcionamiento paso a paso.
Private Sub Btn_Subir_Click()
Dim Fichero As String
Dim RutaCompleta As String
Dim Indice As Integer
If Me.Lst_Ficheros.ListIndex = -1 Or Me.Lst_Ficheros.ListIndex = 0 Then Exit Sub
Indice = Me.Lst_Ficheros.ListIndex
Fichero = Me.Lst_Ficheros.List(Indice, 0)
RutaCompleta = Me.Lst_Ficheros.List(Indice, 1)
Me.Lst_Ficheros.List(Indice, 0) = Me.Lst_Ficheros.List(Indice - 1, 0)
Me.Lst_Ficheros.List(Indice, 1) = Me.Lst_Ficheros.List(Indice - 1, 1)
Me.Lst_Ficheros.List(Indice - 1, 0) = Fichero
Me.Lst_Ficheros.List(Indice - 1, 1) = RutaCompleta
Me.Lst_Ficheros.ListIndex = Indice - 1
Me.Lst_Ficheros.Selected(Indice - 1) = True
End Sub
El primer paso, será comprobar que haya algún elemento seleccionado y que éste no sea ya el primero, en cuyo caso no puede ir mas arriba. Si se da alguna de estas dos situaciones, se termina la ejecución de la rutina. De esto se encarga la línea
If Me.Lst_Ficheros.ListIndex = -1 Or Me.Lst_Ficheros.ListIndex = 0 Then Exit Sub
Si la propiedad ListInedx es -1, quiere decir que no hay elementos seleccionados.
Si la propiedad ListIndex es 0, significa que el elemento seleccionado es el primero del ListBox. Recuerda que el primer elemento es el 0 y no el 1.
Si el elemento seleccionado no es el primero, se puede reordenar. Esto significa que debemos intercambiar los datos de las posiciones seleccionada e inmediatamente anterior.
La posición del dato seleccionado se carga en la variable Indice en la siguiente línea:
Indice = Me.Lst_Ficheros.ListIndex
Y los valores de sus columnas en las variables Fichero y RutaCompleta en las dos siguientes:
Fichero = Me.Lst_Ficheros.List(Indice, 0)
RutaCompleta = Me.Lst_Ficheros.List(Indice, 1)
Ahora ya solo nos queda reescribir en la posición Indice los datos de la posición previa (Indice-1), que se hace con el código:
Me.Lst_Ficheros.List(Indice, 0) = Me.Lst_Ficheros.List(Indice - 1, 0)
Me.Lst_Ficheros.List(Indice, 1) = Me.Lst_Ficheros.List(Indice - 1, 1)
Y escribir en la posición Indice-1 los datos que estamos moviendo:
Me.Lst_Ficheros.List(Indice - 1, 0) = Fichero
Me.Lst_Ficheros.List(Indice - 1, 1) = RutaCompleta
Y, para que nos quede bonito, hacemos que la línea que acabamos de subir sea la seleccionada en el ListBox. Para eso son las dos últimas líneas del código:
Me.Lst_Ficheros.ListIndex = Indice - 1
Me.Lst_Ficheros.Selected(Indice - 1) = True
Programación Btn_Bajar
La lógica para bajar es la misma que para subir. Lo único que tendremos que modificar es:
- La condición para poder bajar un elemento será que no sea el último de la lista
- Tendremos que intercambiar los datos de la posición Indice por los de la Indice+1.
El código quedaría como sigue:
Private Sub Btn_Bajar_Click()
Dim Fichero As String
Dim RutaCompleta As String
Dim Indice As Integer
If Me.Lst_Ficheros.ListIndex = -1 Or Me.Lst_Ficheros.ListIndex = Me.Lst_Ficheros.ListCount - 1 Then Exit Sub
Indice = Me.Lst_Ficheros.ListIndex
Fichero = Me.Lst_Ficheros.List(Indice, 0)
RutaCompleta = Me.Lst_Ficheros.List(Indice, 1)
Me.Lst_Ficheros.List(Indice, 0) = Me.Lst_Ficheros.List(Indice + 1, 0)
Me.Lst_Ficheros.List(Indice, 1) = Me.Lst_Ficheros.List(Indice + 1, 0)
Me.Lst_Ficheros.List(Indice + 1, 0) = Fichero
Me.Lst_Ficheros.List(Indice + 1, 1) = RutaCompleta
Me.Lst_Ficheros.ListIndex = Indice + 1
Me.Lst_Ficheros.Selected(Indice + 1) = True
End Sub
Como es similar al de subir con solo las consideraciones que indico mas arriba, te dejo el análisis a ti.
Conclusión
Hemos visto que ordenar datos dentro de un ListBox es un proceso con una lógica bastante sencilla que, una vez entendida, no presenta grandes dificultades para su programación.
Espero que este ejemplo te sirva en tus desarrollo.
Si quieres aprender mas, echa un vistazo al listado de entradas de VBA en https://informaticamuyfacil.com/category/excel/macros-vba/