sql >> Base de Datos >  >> RDS >> Access

ListView Control Arrastrar y soltar Ordenar eventos

Reorganización de filas de datos en el control ListView.

En el episodio anterior de este Tutorial, aprendimos cómo reorganizar las Columnas habilitando esta función:AllowColumnReorder opción en la hoja de propiedades. Pero, la reubicación de una fila se realiza arrastrándola y colocándola en otra fila. Para reorganizar las filas de control de ListView, la acción de arrastrar y colocar ListItem requiere habilitar esta función en la hoja de propiedades. Pero esto por sí solo no funcionará, necesita el código VBA para reorganizar el artículo en el orden requerido.

Vamos a crear un formulario de acceso de muestra con controles y código VBA en nuestra base de datos para este ejercicio. La imagen de muestra del formulario con controles ListBox y ListView se proporciona a continuación.

Hemos creado una lista de tablas y consultas (no consultas de acción) en el cuadro de lista. Al seleccionar uno de los elementos de la lista, se mostrarán los registros instantáneamente en el control ListView, tal como los vemos en la vista Hoja de datos.

La tarea de diseño.

  1. Cree una nueva tabla con un solo campo de texto, con el nombre de campo DataList .

  2. Guarde la tabla con el nombre lvTables (lv significa ListView).

  3. Abra la tabla en la vista Hoja de datos.

  4. Agregue algunos nombres de tabla y seleccione los nombres de consulta de su base de datos en la tabla. Importé tablas de la base de datos de muestra Northwind para mi lista.

    Nota: El archivo adjunto El campo no es válido en ListView Control. Cree consultas de selección para tablas con campo adjunto y seleccione todos los campos excepto el campo Adjunto.

  5. Cree y abra un nuevo formulario en la vista de diseño.

  6. Inserte un Control ListBox en el formulario, muestre la Hoja de propiedades y cambie su Nombre valor de propiedad a List0 .

  7. Cambiar su etiqueta secundaria Caption valor a Tablas .

  8. Muestre la Hoja de propiedades del control ListBox y configure el Fuente de fila valor de la propiedad a las lvTables nombre.

  9. Compruebe si el Tipo de fuente de fila está configurado como Tabla/Consulta y el valor de la propiedad Columna enlazada es 1. Si es diferente, cámbielo.

  10. Inserte un control ListView de la lista de controles ActiveX y cambie su valor de propiedad de nombre a ListView1 .

  11. Cambie el tamaño de ambos controles como se muestra en la imagen del formulario de demostración anterior.

  12. Inserte una etiqueta encima de los controles y cambie sus valores de propiedad de nombre y título a Encabezado. El valor del título se cambiará del código vba cuando se seleccione una tabla o consulta del cuadro de lista.

  13. Cree un botón de comando debajo de los controles y cambie su valor de propiedad de nombre a cmdClose y el valor de la propiedad Caption para Cerrar .

  14. Haga clic derecho en el Control ListView, resalte el Objeto ListViewCtrl y seleccione Propiedades .

  15. Cambie la configuración de la propiedad para que coincida con la configuración en General Imagen de la pestaña que se muestra a continuación.

  16. Imagen de la hoja de propiedades del control ListView:la vista de la pestaña General se muestra a continuación:

    Algunas de estas opciones ya las hemos establecido en las sesiones anteriores. Aquí necesitamos las siguientes opciones para nuestra acción Arrastrar y Soltar:

    • OLEDdragAutomatic - 1

    • Manual OLEDdrop - 1

    • FullRowSelect - Verdadero

    • Seguimiento activo - Verdadero

Asegúrese de que la configuración anterior coincida con su hoja de propiedades y luego guarde el formulario.

Muestre el módulo VBA del formulario.

El código VBA del módulo de formulario.

Copie y pegue el siguiente código VBA en el módulo, sobrescribiendo las líneas de código existentes, si las hay:

Option Compare Database
Option Explicit

Dim lvwList As MSComctlLib.ListView
Dim strTable As String
Dim db As DAO.Database
Dim rst As DAO.Recordset

Private Sub Form_Load()
    Set lvwList = Me.ListView1.Object

End Sub


Private Sub Form_Unload(Cancel As Integer)
On Error GoTo Form_Unload_Err
Dim lvItem As ListItem
Dim tmp As Long
Dim criteria As String
Dim strfield As String
Dim flag As Boolean
Dim fld As String

If strTable = "" Then
Set lvwList = Nothing
    Exit Sub
End If

Set db = CurrentDb
Set rst = db.OpenRecordset(strTable, dbOpenDynaset)
flag = False
For Each lvItem In lvwList.ListItems
    tmp = lvItem.Index
    strfield = lvwList.ColumnHeaders(1).Text
    criteria = strfield & " = " & Chr(34) & lvItem.Text & Chr(34)
    
    rst.FindFirst criteria
  
    If Not rst.NoMatch Then
       If (rst.Fields(strfield).Value = lvItem.Text) _
       And (rst.Fields(1).Value = tmp) Then
         'GoTo nextitem
       Else
            rst.Edit
            rst.Fields(1).Value = tmp
            rst.Update
       End If
    Else
        MsgBox "Item: " & tmp & " Not Found!"
    End If
Next
rst.Close

Set lvwList = Nothing
Set lvItem = Nothing
Set rst = Nothing
Set db = Nothing

Form_Unload_Exit:
Exit Sub

Form_Unload_Err:
MsgBox Err & " : " & Err.Description, , "Form_Unload()"
Resume Form_Unload_Exit

End Sub

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As Object)
' When a ColumnHeader object is clicked, the ListView control
' sorts the data of that column. On the first Click on the Column
'will sort in Ascending Order, second Click will sort in Descending
With Me.ListView1
    ' Set the SortKey to the Index of the ColumnHeader - 1
    .SortKey = ColumnHeader.Index - 1
    
' Set Sorted to True to sort the list.
 If .SortOrder = lvwAscending Then
    .SortOrder = lvwDescending
 Else
    .SortOrder = lvwAscending
 End If
 
    .Sorted = True
End With

End Sub

Private Sub List0_Click()

strTable = List0.Value

Call LoadListView(strTable)

End Sub

Private Sub LoadListView(ByVal s_Datasource As String)
On Error GoTo LoadListView_Err
    Dim j As Integer
    Dim tmpLItem As MSComctlLib.ListItem
    Dim strHeading As String
    
    strHeading = UCase(s_Datasource)
    With Me.Heading
        .caption = strHeading
        .FontName = "Courier New"
        .FontSize = 20
        .FontItalic = True
        .FontBold = True
    End With
    
   'Initialize ListView Control
    lvwList.ColumnHeaders.Clear
    lvwList.ListItems.Clear
    
    Set db = CurrentDb
    Set rst = db.OpenRecordset(s_Datasource, dbOpenSnapshot)
       
    'Initialize ListView & Column Headers Property Values
     With lvwList
        .Font.Size = 10
        .Font.Name = "Verdana"
        .Font.Bold = False
        .GridLines = True
    End With
    
    With lvwList
        'Syntax: .ColumnHeaders.Add Index, Key, Text, Width in Pixels, Alignment, Icon
       For j = 0 To rst.Fields.Count - 1
        .ColumnHeaders.Add , , rst.Fields(j).Name, IIf(j = 0, 3000, 1400), 0
       Next
    End With
   Dim I As Long
    rst.MoveFirst
    Do While Not rst.BOF And Not rst.EOF
    'Syntax: lvwList.ListItems.Add Index, Key, Text, Icon, SmallIcon
        Set tmpLItem = lvwList.ListItems.Add(, , rst.Fields(0).Value) 'Name column
        
         'Syntax: tmpLItem.ListSubItems.Add Index, Key, Text, ReportIcon, ToolTipText
          With tmpLItem
                For j = 1 To rst.Fields.Count - 1
                    .ListSubItems.Add , , Nz(rst.Fields(j).Value, "")
                Next
          End With
        rst.MoveNext
    Loop
    rst.Close
    
    With lvwList
        If .ListItems.Count > 0 Then
            .ListItems(1).Selected = True
        End If
    End With
  
    Set db = Nothing
    Set rst = Nothing
    
LoadListView_Exit:
Exit Sub

LoadListView_Err:
MsgBox Err & " : " & Err.Description, , "LoadListView()"
Resume LoadListView_Exit
End Sub


Private Sub ListView1_OLEDragOver(data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer)
    'Highlight the item when draged over it
    Set ListView1.DropHighlight = ListView1.HitTest(x, y)

End Sub

Private Sub ListView1_OLEDragDrop(data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)

'Item being dropped
Dim lvwDrag As ListItem
'Item being dropped on
Dim lvwDrop As ListItem
'Item being readded to the list
Dim lvwTarget As ListItem
'Subitem reference in dropped item
Dim lvwSub As ListSubItem
'Drop position
Dim intTgtIndex As Integer
Dim j As Integer

Set lvwDrop = lvwList.HitTest(x, y)
Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item

'Ignore overlapping drag or drop Item actions
If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing) Or (lvwDrop = lvwDrag) Then
    Set lvwList.DropHighlight = Nothing
    Set lvwDrop = Nothing
    Set lvwDrag = Nothing
    Exit Sub
End If

'Save the droped position Index Number
intTgtIndex = lvwDrop.Index
'Remove Dragged Item from its old position
lvwList.ListItems.Remove lvwDrag.Index

'For j = intTgtIndex To ListItems.Count
    
'Creates a new Item in the Target Item position
'with the Dropped Item Index Number and Dragged Item.Text.
'Saves the new Item reference in lvwTarget Item.

'* The original Droped-on Target) Item will be moved down
'* by incrementing its original Index Number
Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text)

'Copy the original Draged Item's subitems to the new item
If lvwDrag.ListSubItems.Count > 0 Then
    For Each lvwSub In lvwDrag.ListSubItems
        lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text
    Next
End If

'Highlight the draged item in its new position
lvwTarget.Selected = True

'Destroy all objects
Set lvwTarget = Nothing
Set lvwDrag = Nothing
Set lvwDrop = Nothing
Set lvwList.DropHighlight = Nothing

End Sub

Private Sub cmdClose_Click()
    DoCmd.Close acForm, Me.Name
End Sub

Está familiarizado con el código VBA anterior, excepto las subrutinas recién agregadas:ListView1_OLEDragOver(), ListView1_OLEDragDrop(), Form_Unload(), y el ListView1_ColumnClik() procedimientos. Los dos primeros procedimientos nos ayudarán a arrastrar un elemento (fila) y soltarlo sobre otro elemento para insertarlo en una nueva ubicación. Los procedimientos Form_Unload() y ListView1_ColumnClick() ordenarán los elementos.

Las siguientes imágenes muestran la acción de arrastrar y soltar en secuencias de su ejecución

La primera imagen a continuación muestra la secuencia de acción de arrastrar y soltar. El ListItem, con EmployeeID 7, es arrastrado por el usuario y lo coloca sobre el ListItem con ID 3.

La segunda imagen muestra el movimiento de ListItem en orden inverso.

Cuando el puntero del mouse se mueve sobre una fila con el elemento arrastrado, entre las filas de origen y de destino, se resaltará una tras otra en el camino hacia arriba.

La acción de arrastrar y soltar en imágenes.

La fila con ID de empleado 7 se coloca en el artículo con ID de empleado 3 anterior.

El análisis por segmentos del código VBA.

Una selección de elementos de ListBox, el procedimiento de evento List0_Click() se ejecuta y carga los registros en ListView Control.

Private Sub List0_Click()
Dim strTable As String

strTable = List0.Value

  Call LoadListView(strTable)

End Sub

El nombre de la tabla/consulta seleccionada se guarda en la strTable variable de cadena LoadListView() la subrutina se ejecuta con la variable strTable como parámetro. Hemos revisado este Código más de una vez en sesiones anteriores, y puede visitar esas Páginas utilizando los Enlaces proporcionados en la parte inferior de esta página para obtener más detalles. Es posible que encuentre algunos cambios menores que hice en este Código.

No hemos utilizado ImageList Control en este episodio Icon, SmallIcon Valores de parámetros en el método ListItems.Add() y ReportIcon, TooltipText los valores de los parámetros en el método ListSubItems.Add() tampoco se usan.

Veamos lo que sucede en ListView1_OLEDragOver() y ListView1_OLEDragDrop() Segmentos de código VBA.

El procedimiento ListView1_OLEDragOver().

Private Sub ListView1_OLEDragOver(Data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single, State As Integer)
    'Highlight the item when draged over it
    Set ListView1.DropHighlight = ListView1.HitTest(x, y)
End Sub 

Este procedimiento se ejecuta automáticamente cuando intenta hacer clic y mantener presionada una fila, comienza a arrastrar y se mueve sobre otras filas en el camino hacia la fila de destino. La acción de arrastrar se mueve sobre otra fila y se resaltará.

El ListView1.HitTest(x, y) La función lee las coordenadas x, y que determinan la posición de la fila en el control ListView y resalta esa fila. Este proceso continúa cuando está sobre otras filas hasta que lo suelta en la fila de destino soltando el botón del mouse. La acción de soltar activa el ListView1_OLEDragDrop() y ejecuta los procedimientos de cambio de la fila de origen.

El procedimiento ListView1_OLEDragDrop.

Private Sub ListView1_OLEDragDrop(Data As Object, Effect As Long, Button As Integer, Shift As Integer, x As Single, y As Single)

'Item being dragged
Dim lvwDrag As ListItem
'Item being dropped on
Dim lvwDrop As ListItem
'Item being added to the list
Dim lvwTarget As ListItem
'Subitem reference used in For . . .Next loop
Dim lvwSub As ListSubItem 'Drop position index Dim intTgtIndex As Integer Set lvwDrop = lvwList.HitTest(x, y) 'save the source item Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item 'Ignore overlapping drag or drop Item actions If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing) Or (lvwDrop = lvwDrag) Then Set lvwList.DropHighlight = Nothing Set lvwDrop = Nothing Set lvwDrag = Nothing Exit Sub End If 'Save the droped position Index Number intTgtIndex = lvwDrop.Index 'Remove Dragged Item from its old position lvwList.ListItems.Remove lvwDrag.Index 'Creates a new Item in the Target Item position 'with the Dropped Item Index Number and Dragged Item.Text. 'Saves the new Item reference in lvwTarget Item. '* The original Droped-on Target) Item will be moved down '* by incrementing its original Index Number Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text) 'Copy the original Draged Item's subitems to the new item If lvwDrag.ListSubItems.Count > 0 Then For Each lvwSub In lvwDrag.ListSubItems lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text Next End If 'Highlight the draged item in its new position lvwTarget.Selected = True 'Destroy all objects Set lvwTarget = Nothing Set lvwDrag = Nothing Set lvwDrop = Nothing Set lvwList.DropHighlight = Nothing End Sub

Revisemos este procedimiento parte por parte y entendamos lo que está sucediendo allí. El siguiente segmento de código declara las variables de objeto necesarias para manejar la acción de arrastrar y soltar:

'Item being dragged
Dim lvwDrag As ListItem
'Item being dropped on
Dim lvwDrop As ListItem
'Reference of the Item being added to the list
Dim lvwTarget As ListItem
'Subitem reference used in For . . .Next loop
Dim lvwSub As ListSubItem
'Drop position index
Dim intTgtIndex As Integer

Set lvwDrop = lvwList.HitTest(x, y)
Set lvwDrag = lvwList.SelectedItem 'save a copy of draged item

Los tres primeros objetos temporales ListItem se declaran con nombres diferentes.

El lvwDrag El objeto ListItem contendrá la copia de la fila que elegimos para arrastrar a una nueva ubicación.

El lvwDrop El objeto ListItem guardará la referencia de la fila en la que soltamos el elemento de la lista arrastrado.

Durante el cambio de la acción ListItems, eliminaremos el elemento de origen de su ubicación original y luego lo crearemos en la ubicación de destino, con el número de índice ListItem de origen. Las referencias de este nuevo ListItem se guardan en el lvwTarget Variable de objeto ListItem.

El lvwSub Variable declarada como variable de objeto de secuenciación en For . . .Siguiente Círculo. Este bucle requiere una secuencia a través de los ListSubItems, (2ª columna en adelante) uno por uno, desde el objeto lvwDrag. Aunque hemos eliminado el ListItem original, hemos guardado una copia en el objeto lvwDrag ListItem.

El número de índice lvwDrop ListItem se guarda en el intTgtIndex variables.

La lvwList.HitTest(x, y) La función lee las coordenadas x, y del Control ListView e identifica el ListItem de destino donde soltamos el ListItem de origen y hace una copia del mismo en lvwDrop Object.

Primero seleccionaremos un ListItem antes de arrastrarlo a la nueva posición.

El lvwList.SelectedItem La propiedad se establecerá como True. Con la ayuda de este estado de propiedad, hacemos una copia del ListItem seleccionado en lvwDrag Objeto ListItem. El siguiente segmento de código valida los objetos ListItem de origen y de destino.

Comprobaciones de validación en la acción de arrastrar y soltar.

'Ignore overlapping drag or drop Item actions, 
'OR drag and drop happens on the same ListItem.
If (lvwDrop Is Nothing) Or (lvwDrag Is Nothing)  Or (lvwDrop = lvwDrag) Then
    Set lvwList.DropHighlight = Nothing
    Set lvwDrop = Nothing
    Set lvwDrag = Nothing
    Exit Sub
End If

El segmento de código anterior valida la acción de arrastrar y soltar. Si estas acciones no comenzaron o terminaron en un elemento válido, los objetos lvwDrop o lvwDrag o ambos estarán vacíos. O puede ocurrir otro movimiento inválido cuando el usuario mueve una fila hacia arriba o hacia abajo, pero puede cambiar de opinión y volver a colocarlo en la misma fila. La detección de este tipo de movimientos incorrectos terminará el programa.

Si la prueba anterior resulta válida, el programa continuará ejecutando el siguiente procedimiento para reorganizar las Filas.

'Save the dropped position ListItem Index Number
intTgtIndex = lvwDrop.Index

'Remove Dragged Item from its old position
lvwList.ListItems.Remove lvwDrag.Index

'Creates a new Item in the Target Item position
'with the Dropped Item Index Number and Dragged Item.Text.
'Saves the new Item reference in lvwTarget Item.

'* The original Droped-on Target) Item will be moved down
'* by incrementing its original Index Number
Set lvwTarget = lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text)

'Copy the original Draged Item's subitems to the new item
If lvwDrag.ListSubItems.Count > 0 Then
    For Each lvwSub In lvwDrag.ListSubItems
        lvwTarget.ListSubItems.Add , lvwSub.Key, lvwSub.Text
    Next
End If

'Highlight the draged item in its new position
lvwTarget.Selected = True

Las acciones de las nueve líneas anteriores de código ejecutable (otras líneas son comentarios) son algo sencillas.

El intTgtIndex =lvwDrop.Index La instrucción guarda el número de índice de ListItem de destino en intTgtIndex variables.

Dado que ya hemos guardado el listItem de fila de origen en el objeto temporal lvwDrag, el siguiente paso es eliminar el ListItem de origen del control ListView. El procedimiento ListItems.Remove() se llama, con la sentencia lvwList.ListItems.Remove lvwDrag.Index .

En resumen, la acción de Arrastrar y Soltar consiste en eliminar un ListItem de su ubicación original y volver a crearlo en la ubicación de destino con el número de índice de la fila de destino.

La instrucción Establecer lvwTarget =lvwList.ListItems.Add(intTgtIndex, , lvwDrag.Text) crea el nuevo ListItem con su número de índice de ubicación de destino intTgtIndex y el Texto valor de Source ListItem guardado en el objeto lvwDrag anteriormente.

Al crear ListItem por primera vez, hemos usado solo estos dos valores, el índice y el Texto valores paramétricos. No hemos utilizado las otras opciones de parámetros Key, Icon, y PequeñoIcono de lo contrario, debemos incluir esos valores de parámetros también del objeto lvwDrag.

De acuerdo con nuestras imágenes de ejemplo de arrastrar y soltar que se muestran arriba, hemos movido el 7.° ListItem y lo soltamos en el 3.° ListItem. Después de eso, hemos eliminado el 7º elemento (o elemento de lista de origen) del control ListView. Creó un nuevo ListItem con el índice de destino número 3.

Ahora, hay dos elementos con el mismo número de índice 3, el existente con el número de índice 3 y el nuevo que hemos creado con el número de índice 3. Toda la demás información se toma del objeto lvwDrag (o el 7º ListItem guardado en lvwDrag Objeto anterior).

El sistema incrementa automáticamente el ListItem 3 existente en adelante a los siguientes números de secuencia 3,4,5. . . a 4,5,6 . . . y los mueve hacia adelante para dejar espacio para que el elemento entrante se inserte en el medio.

El impacto de eliminar una fila y crearla en otro lugar.

Supongamos que hacemos ese movimiento en el orden inverso, como arrastrar ListItem número 3 desde arriba y soltarlo en el elemento número 7, ¿entonces qué sucede?

Naturalmente, eliminaremos el tercer elemento e intentaremos crear un nuevo elemento con el número de índice 7 en la nueva ubicación. Cuando se elimina el artículo número 3, el artículo número 4 en adelante se desplazará hacia arriba o 4,5,6,7,8,9 se convertirá en 3,4,5,6,7,8 (para hacer todos los artículos en secuencia) o el anterior el elemento con el número de índice 7 se convertirá en 6.

Cuando creamos el nuevo elemento con el número de índice 7, el 7,8 existente se convertirá nuevamente en 8,9. Cuando observamos el movimiento de las filas durante el tiempo de eliminación y creación de filas, el primer ejemplo moverá la fila de destino hacia abajo para dar paso al elemento entrante. En el segundo ejemplo explicado (mover 3 a 7) la fila de destino se moverá hacia arriba.

Nota: Ver El valor de identificación de los empleados para su ubicación como una pista para que ListItem se desplace hacia abajo o hacia arriba cuando reorganizamos ListItem.

He mencionado ListItem en todas partes en las operaciones de arrastrar y soltar. ListItem hace referencia únicamente a la primera columna de ListView Row. Otros valores de columna son ListSubItems o los elementos secundarios de ListItem. Eso significa que solo podrá arrastrar y soltar la primera columna. Otras columnas o ListSubItems se moverán debajo de ListItem con código VBA.

Esto es cierto si no ha habilitado la FullRowSelection en la hoja de propiedades del control ListView en General Pestaña

Si está habilitado, puede seleccionar cualquier columna, pero el sistema se refiere al índice ListItem para fines de reordenación de filas. Compare las dos imágenes anteriores con otro conjunto de dos imágenes de muestra, la tercera y cuarta imágenes desde la parte superior de esta página.

La acción de arrastrar y colocar no funcionará si los dos valores de propiedad siguientes no están establecidos en la hoja de propiedades del control ListView en General Pestaña:

  • ccOLEDragAutomatic =1
  • ccOLEDdropManual =1

Las próximas cinco declaraciones moverán los ListSubItems, si lo hay, al ListItem recién creado en la nueva ubicación.

A continuación, se resalta el ListItem recién creado.

A continuación, todos los objetos temporales creados se borran de la memoria.

Nota: Otro punto importante a tener en cuenta aquí es que este arreglo es temporal y se pierde cuando cierra el formulario o carga otra tabla/consulta en el control ListView.

Si queremos que el orden cambiado de ListItems permanezca permanente, o hasta que el orden se cambie la próxima vez, entonces debemos poder actualizar el número de orden indexado actual en la tabla misma. Hemos agregado un nuevo campo Integer con el ID de nombre de campo en la Tabla de empleados.

La pantalla de muestra con los datos de los empleados reorganizados en orden alfabético se muestra a continuación:

Dado que el campo Id. de empleados es un campo Autonumérico y está vinculado con otras tablas relacionadas, hemos agregado un nuevo campo numérico con el Id. de nombre de campo. Este valor de campo se establece inicialmente con los mismos números de secuencia de la ID de empleados de forma manual. Este valor de campo estará inicialmente en este orden. Sin embargo, los datos de ListView Rows pueden cambiar su orden cuando reorganiza los datos en ListView Control debido a la acción de arrastrar y soltar.

Mire los EmpleadosQ SQL de consulta dado a continuación:

SELECT [FirstName] & " " & [LastName] AS EmployeeName, 
Employees.ID, 
Employees.EmployeeID, 
Employees.TitleOfCourtesy, 
Employees.Title, 
Employees.Address, 
Employees.City, 
Employees.Region, 
Employees.PostalCode, 
Employees.Country, 
Employees.HomePhone, 
Employees.Extension, 
Employees.Notes
FROM Employees
ORDER BY Employees.ID;

La consulta anterior se utiliza como fuente de datos para el control ListView y se ordenan en el campo ID. El campo ID se actualiza con el orden modificado de los números de índice en el control ListView. El proceso de actualización se ejecuta desde Form_Unload() Procedimiento de evento al cerrar el formulario. Este método garantiza que cuando abra ListView Control la próxima vez, los datos estarán en el orden en que los reordenó la última vez.

El Form_Unload() Procedimiento de evento Código VBA.

Private Sub Form_Unload(Cancel As Integer)
Dim lvItem As ListItem
Dim tmp As Long
Dim criteria As String
Dim strfield As String
Dim fld As String

If strTable = "" Then
Set lvwList = Nothing
    Exit Sub
End If

Set db = CurrentDb
Set rst = db.OpenRecordset(strTable, dbOpenDynaset)

For Each lvItem In lvwList.ListItems
    tmp = lvItem.Index
    strfield = lvwList.ColumnHeaders(1).Text 'EmployeeName
    criteria = strfield & " = " & Chr(34) & lvItem.Text & Chr(34)
    
    rst.FindFirst criteria
  
    If Not rst.NoMatch Then
       If (rst.Fields(strfield).Value = lvItem.Text) And (rst.Fields(1).Value = tmp) Then
         'GoTo nextitem
       Else
            rst.Edit
            rst.Fields(1).Value = tmp 'replace ID number
            rst.Update
       End If
    Else
        MsgBox "Item: " & tmp & " Not Found!"
    End If
Next
rst.Close

Set lvwList = Nothing
Set lvItem = Nothing
Set rst = Nothing
Set db = Nothing

End Sub

Compruebe el Nombre del empleado Valor de campo en la imagen de arriba. Están ordenados en orden alfabético. El nuevo valor del campo ID en la tabla de empleados se actualizará con su secuencia de números de índice ListView Control ListItem actual.

Si observa los siguientes puntos, puede comprender fácilmente lo que hacemos con el código anterior:

  1. El texto de ListItem (primera columna) el valor del parámetro es el nombre del empleado y está ordenado alfabéticamente.

  2. Los ListItems en el control ListView tienen números de índice del 1 al 9 en el orden en que se muestran en la pantalla, es decir, el número de índice del primer elemento es 1 y el último es 9. Los datos originales en el valor del campo ID de la tabla de empleados no son en este orden.

  3. Tomamos el Texto Valor (Nombre del empleado) del primer ListItem y busque el nombre en la tabla.

  4. Cuando se encuentra el registro, el número de índice de ListItem actual se actualiza (reemplaza) en el campo ID de la tabla.

  5. Este proceso se repitió para todos los registros restantes de la tabla.

Repasemos el código VBA. Al principio, verificamos si la tabla/consulta de datos de origen se cargó en el control ListView o no.

Si la strTable La variable no se inicializa con el nombre de consulta, entonces el control ListView está vacío. Si este es el caso, el usuario abrió el formulario y lo cerró sin seleccionar el nombre de consulta para cargar los datos en el control ListView. El Descargar_formulario El procedimiento de evento se aborta en este punto y cierra el formulario.

Si el control ListView tiene datos, se ejecuta el siguiente paso y se abre la consulta de datos de origen EmployeesQ para actualizar.

El siguiente paso es revisar cada ListItem y actualizar el número de índice en el campo ID del registro de Empleados.

Primero, el número de índice de fila actual se guarda en el tmp variables.

El primer nombre lvwList.ColumnHeader EmployeeName y el nombre del empleado se toma del ListItem.Text en una expresión en los Criterios variable de cadena, como EmployeeName ="Andrew Fuller".

Los criterios rst.FindFirst El comando busca en la tabla de datos de origen para encontrar el registro con el nombre dado. Cuando se encuentra el registro, el número de índice ListItem actual se actualiza en el campo ID.

Este proceso se repite para todas las filas del control ListView y cuando finaliza, el formulario se cierra.

La próxima vez que cargue los registros de esta consulta en el control ListView, se mostrarán en el mismo orden en que cerró el formulario la última vez.

Nota:La Consulta se volvió necesaria aquí para ordenar los datos en el campo ID y mostrarlos en el orden modificado en el control ListView.

Todo este trabajo fue para guardar los datos en el último orden ordenado para que la próxima vez que abra el Formulario, los datos en el Control ListView estén en ese orden.

Método de clasificación similar al Explorador de Windows.

En el Explorador de Windows, puede ordenar la lista mostrada en orden ascendente o descendente haciendo clic en cualquier encabezado de columna. El encabezado de columna funcionará como un botón de alternancia. Los clics repetidos en el encabezado de la columna ordenarán los datos de la columna en orden ascendente/descendente según el siguiente ListView1_ColumnClick() Procedimiento de evento:

Private Sub ListView1_ColumnClick(ByVal ColumnHeader As Object)
' When a ColumnHeader object is clicked, the ListView control is
' sorted by the subitems of that column.

With Me.ListView1
' Set the SortKey to the Index of the ColumnHeader - 1
    .SortKey = ColumnHeader.Index - 1
    
 If .SortOrder = lvwAscending Then
    .SortOrder = lvwDescending
 Else
    .SortOrder = lvwAscending
 End If
 ' Set Sorted to True to sort the list.
     .Sorted = True
End With
End Sub

Nota: La clasificación de todos los datos se realiza únicamente en el modo de comparación de texto. Los elementos de la lista y ListSubItems Añadir() tercer parámetro del método, la información que se muestra en el control ListView es Texto tipo. La fecha y los valores numéricos se tratan solo como texto.

El Explorador de Windows guarda el último orden ordenado de elementos en la carpeta. Cuando abramos esa carpeta nuevamente, la lista se mostrará en el orden ordenado anterior.

Con Form_Unload() Procedimiento de evento Esta función del Explorador de Windows se vuelve posible en la Tabla de empleados. Cuando cierre el formulario después de ordenar en cualquier columna, esa secuencia de orden indexada se guardará en la tabla de empleados en el campo ID. La consulta EmployeesQ siempre ordena los datos en el campo ID cuando se abre.

La base de datos de demostración se adjunta para su descarga. Hay dos formularios de demostración en la base de datos. El primer formulario demuestra la apertura de tablas y consultas en el control ListView para ver los datos en la vista Hoja de datos. El segundo formulario usa solo EmployeesQ Consulta solo para arrastrar, soltar, ordenar y guardar el último orden de clasificación de datos para uso futuro.



  1. Tutorial de control ActiveX ListView-01.
  2. Tutorial de control ListView-02.
  3. Asignación de imágenes a elementos de ListView.
  4. ListView Control Arrastrar y Soltar Ordenar Eventos
  5. Control ListView con MS-Access TreeView
  6. TreeView/ListView controla los eventos de arrastrar y soltar